diff options
author | Thomas Schuetz | 2011-12-23 15:12:42 +0000 |
---|---|---|
committer | Thomas Schuetz | 2011-12-23 15:12:42 +0000 |
commit | f502cbe9485f647ecd273222bf53717fa00c5043 (patch) | |
tree | f7e19a27ecb36d9255ea8f7a5f22bcb98a625c78 /plugins/org.eclipse.etrice.generator.c/src | |
parent | f9975ec475dc447886695489cfafba8adb5b7860 (diff) | |
download | org.eclipse.etrice-f502cbe9485f647ecd273222bf53717fa00c5043.tar.gz org.eclipse.etrice-f502cbe9485f647ecd273222bf53717fa00c5043.tar.xz org.eclipse.etrice-f502cbe9485f647ecd273222bf53717fa00c5043.zip |
[generator.c] added project for C-Generator, moved more language independent generator code to plugin generator
Diffstat (limited to 'plugins/org.eclipse.etrice.generator.c/src')
12 files changed, 1517 insertions, 0 deletions
diff --git a/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/Main.java b/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/Main.java new file mode 100644 index 000000000..35ddee8a2 --- /dev/null +++ b/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/Main.java @@ -0,0 +1,119 @@ +/******************************************************************************* + * Copyright (c) 2011 protos software gmbh (http://www.protos.de). + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * CONTRIBUTORS: + * Henrik Rentz-Reichert (initial contribution) + * + *******************************************************************************/ + +package org.eclipse.etrice.generator.c; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.etrice.generator.base.AbstractGenerator; +import org.eclipse.etrice.generator.etricegen.Root; +import org.eclipse.etrice.generator.doc.gen.InstanceDiagramGen; // TODO: fix import +import org.eclipse.etrice.generator.c.gen.Validator; +import org.eclipse.etrice.generator.c.setup.GeneratorModule; +import org.eclipse.xtext.generator.IGenerator; + +import com.google.inject.Inject; + +public class Main extends AbstractGenerator { + + public static final String OPTION_LIB = "-lib"; + public static final String OPTION_GEN_INST_DIAG = "-genInstDiag"; + public static final String OPTION_SAVE_GEN_MODEL = "-saveGenModel"; + + /** + * print usage message to stderr + */ + private static void printUsage() { + output.println(Main.class.getName()+" [-saveGenModel <genmodel path>] [-genInstDiag] [-lib] <list of model file paths>"); + output.println(" <list of model file paths> # model file paths may be specified as"); + output.println(" # e.g. C:\\path\\to\\model\\mymodel.room"); + output.println(" -saveGenModel <genmodel path> # if specified the generator model will be saved to this location"); + output.println(" -genInstDiag # if specified an instance diagram is created for each subsystem"); + output.println(" -lib # if specified all classes are generated and no instances"); + } + + public static void main(String[] args) { + createAndRunGenerator(new GeneratorModule(), args); + } + + @Inject + private IGenerator mainGenerator; + + @Inject + protected InstanceDiagramGen instanceDiagramGenerator; + + @Inject + private Validator validator; + + public void runGenerator(String[] args) { + if (args.length == 0) { + logger.logError(Main.class.getName()+" - aborting: no arguments!", null); + printUsage(); + return; + } + + // parsing arguments + String genModelPath = null; + List<String> uriList = new ArrayList<String>(); + boolean genInstDiag = false; + boolean asLibrary = false; + for (int i=0; i<args.length; ++i) { + if (args[i].equals(OPTION_SAVE_GEN_MODEL)) { + if (++i<args.length) { + genModelPath = convertToURI(args[i]+"/genmodel.egm"); + } + } + else if (args[i].equals(OPTION_GEN_INST_DIAG)) { + genInstDiag = true; + } + else if (args[i].equals(OPTION_LIB)) { + asLibrary = true; + } + else { + uriList.add(convertToURI(args[i])); + } + } + + setupRoomModel(); + + runGenerator(uriList, genModelPath, genInstDiag, asLibrary); + } + + protected boolean runGenerator(List<String> uriList, String genModelPath, boolean genInstDiag, boolean asLibrary) { + ResourceSet rs = resourceSetProvider.get(); + + loadModels(uriList, rs); + + if (!validateModels(rs)) + return false; + + Root genModel = createGeneratorModel(rs, asLibrary, genModelPath); + if (genModel==null) + return false; + + if (!validator.validate(genModel)) + return false; + + logger.logInfo("-- starting code generation"); + fileAccess.setOutputPath("src-gen/"); + mainGenerator.doGenerate(genModel.eResource(), fileAccess); + + if (genInstDiag) { + instanceDiagramGenerator.doGenerate(genModel); + } + logger.logInfo("-- finished code generation"); + + return true; + } +} diff --git a/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/ActorClassGen.xtend b/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/ActorClassGen.xtend new file mode 100644 index 000000000..f7b828a5e --- /dev/null +++ b/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/ActorClassGen.xtend @@ -0,0 +1,170 @@ +/******************************************************************************* + * Copyright (c) 2011 protos software gmbh (http://www.protos.de). + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * CONTRIBUTORS: + * Henrik Rentz-Reichert (initial contribution) + * + *******************************************************************************/ + +package org.eclipse.etrice.generator.c.gen + +import com.google.inject.Inject +import com.google.inject.Singleton +import org.eclipse.etrice.core.room.ActorClass +import org.eclipse.etrice.core.room.Message +import org.eclipse.etrice.generator.base.ILogger +import org.eclipse.etrice.generator.etricegen.ExpandedActorClass +import org.eclipse.etrice.generator.etricegen.Root +import org.eclipse.xtext.generator.JavaIoFileSystemAccess + +import org.eclipse.etrice.generator.extensions.RoomExtensions + +@Singleton +class ActorClassGen { + + @Inject extension JavaIoFileSystemAccess fileAccess + @Inject extension CExtensions stdExt + @Inject extension RoomExtensions roomExt + + @Inject extension ProcedureHelpers helpers + @Inject extension StateMachineGen stateMachineGen + @Inject ILogger logger + + def doGenerate(Root root) { + for (xpac: root.xpActorClasses) { + var path = xpac.actorClass.generationTargetPath+xpac.actorClass.getPath + var file = xpac.actorClass.getCHeaderFileName + logger.logInfo("generating ActorClass implementation '"+file+"' in '"+path+"'") + fileAccess.setOutputPath(path) + fileAccess.generateFile(file, root.generate(xpac, xpac.actorClass)) + } + } + + def generate(Root root, ExpandedActorClass xpac, ActorClass ac) {''' + package «ac.getPackage»; + + import org.eclipse.etrice.runtime.java.messaging.Address; + import org.eclipse.etrice.runtime.java.messaging.IRTObject; + import org.eclipse.etrice.runtime.java.messaging.IMessageReceiver; + import org.eclipse.etrice.runtime.java.modelbase.ActorClassBase; + import org.eclipse.etrice.runtime.java.modelbase.SubSystemClassBase; + import org.eclipse.etrice.runtime.java.modelbase.InterfaceItemBase; + import org.eclipse.etrice.runtime.java.debugging.DebuggingService; + + «FOR model : root.getReferencedModels(ac)»import «model.name».*; + «ENDFOR» + + «FOR pc : root.getReferencedProtocols(ac)»import «pc.^package».«pc.name».*; + «ENDFOR» + + «helpers.UserCode(ac.userCode1)» + + + public «IF ac.abstract»abstract «ENDIF»class «ac.name» extends «IF ac.base!=null»«ac.base.name»«ELSE»ActorClassBase«ENDIF» { + + «helpers.UserCode(ac.userCode2)» + + //--------------------- ports + «FOR ep : ac.getEndPorts()» + protected «ep.getPortClassName()» «ep.name» = null; + «ENDFOR» + //--------------------- saps + «FOR sap : ac.strSAPs» + protected «sap.getPortClassName()» «sap.name» = null; + «ENDFOR» + //--------------------- services + «FOR svc : ac.serviceImplementations» + protected «svc.getPortClassName()» «svc.spp.name» = null; + «ENDFOR» + + //--------------------- interface item IDs + «FOR ep : ac.getEndPorts()» + protected static final int IFITEM_«ep.name» = «xpac.getInterfaceItemLocalId(ep)+1»; + «ENDFOR» + «FOR sap : ac.strSAPs» + protected static final int IFITEM_«sap.name» = «xpac.getInterfaceItemLocalId(sap)+1»; + «ENDFOR» + «FOR svc : ac.serviceImplementations» + protected static final int IFITEM_«svc.spp.name» = «xpac.getInterfaceItemLocalId(svc.spp)+1»; + «ENDFOR» + + «helpers.Attributes(ac.attributes)» + «helpers.Operations(ac.operations)» + + //--------------------- construction + public «ac.name»(IRTObject parent, String name, Address[][] port_addr, Address[][] peer_addr){ + «IF ac.base==null» + super(parent, name, port_addr[0][0], peer_addr[0][0]); + «ELSE» + super(parent, name, port_addr, peer_addr); + «ENDIF» + setClassName("«ac.name»"); + + // initialize attributes + «FOR a : ac.attributes » + «IF a.defaultValueLiteral!=null» + «a.name» = «a.defaultValueLiteral»; + «ELSEIF a.type.type!=null» + «a.name» = new «a.type.type.name»(); + «ENDIF» + «ENDFOR» + + // own ports + «FOR ep : ac.getEndPorts()» + «ep.name» = new «ep.getPortClassName()»(this, "«ep.name»", IFITEM_«ep.name», «IF ep.multiplicity==1»0, «ENDIF»port_addr[IFITEM_«ep.name»]«IF ep.multiplicity==1»[0]«ENDIF», peer_addr[IFITEM_«ep.name»]«IF ep.multiplicity==1»[0]«ENDIF»); + «ENDFOR» + // own saps + «FOR sap : ac.strSAPs» + «sap.name» = new «sap.getPortClassName()»(this, "«sap.name»", IFITEM_«sap.name», 0, port_addr[IFITEM_«sap.name»][0], peer_addr[IFITEM_«sap.name»][0]); + «ENDFOR» + // own service implementations + «FOR svc : ac.serviceImplementations» + «svc.spp.name» = new «svc.getPortClassName()»(this, "«svc.spp.name»", IFITEM_«svc.spp.name», port_addr[IFITEM_«svc.spp.name»], peer_addr[IFITEM_«svc.spp.name»]); + «ENDFOR» + } + + + //--------------------- lifecycle functions + public void init(){ + initUser(); + } + + public void start(){ + startUser(); + } + + «IF !ac.overridesStop()» + public void stop(){ + stopUser(); + } + «ENDIF» + + public void destroy(){ + destroyUser(); + } + + «IF ac.stateMachine != null» + «stateMachineGen.genStateMachine(xpac, ac)» + «ELSEIF !xpac.hasStateMachine()» + //--------------------- no state machine + @Override + public void receiveEvent(InterfaceItemBase ifitem, int evt, Object data) { + handleSystemEvent(ifitem, evt, data); + } + + @Override + public void executeInitTransition(){ + } + «ENDIF» + }; + ''' + } + + def msgArgs(Message msg) { + '''«IF msg.data!=null»«msg.data.defaultValue()»«ENDIF»''' + } +}
\ No newline at end of file diff --git a/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/CExtensions.xtend b/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/CExtensions.xtend new file mode 100644 index 000000000..af43028a6 --- /dev/null +++ b/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/CExtensions.xtend @@ -0,0 +1,107 @@ +/******************************************************************************* + * Copyright (c) 2010 protos software gmbh (http://www.protos.de). + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * CONTRIBUTORS: + * Thomas Schuetz and Henrik Rentz-Reichert (initial contribution) + * + *******************************************************************************/ + +/* + collection of convenience functions for code generation +*/ + + +package org.eclipse.etrice.generator.c.gen + +import com.google.inject.Inject +import com.google.inject.Singleton +import org.eclipse.etrice.core.room.FreeType +import org.eclipse.etrice.core.room.Message +import org.eclipse.etrice.core.room.PrimitiveType +import org.eclipse.etrice.core.room.RoomClass +import org.eclipse.etrice.core.room.Type +import org.eclipse.etrice.core.room.TypedID +import org.eclipse.etrice.generator.etricegen.ExpandedActorClass +import org.eclipse.etrice.generator.etricegen.TransitionChain +import org.eclipse.etrice.generator.generic.ILanguageExtension +import org.eclipse.etrice.generator.generic.LanguageGenerator + + + +@Singleton +class CExtensions implements ILanguageExtension { + + @Inject LanguageGenerator languageGen + + + + //------------------------------------------------------- + // Java types + + // type names for Type class (distinguish Primitive and DataClass) + override String toType(PrimitiveType prim) { + prim.toString() + } + + override String typeName(Type type) { + if (type.type!=null) + return type.type.name + else + type.prim.toType + } + override String freeTypeName(FreeType type) { + if (type.type!=null) + return type.type + else + type.prim.toType + } + + // default values for data + override String defaultValue(PrimitiveType prim) { + return switch(prim.toString()) { + case 'uint8': '0' + case 'uint16': '0' + case 'uint32': '0' + case 'int8': '0' + case 'int16': '0' + case 'int32': '0' + case 'float32': '0.0' + case 'float64': '0.0' + case 'string': '""' + default: prim.toString() + }; + } + override String defaultValue(TypedID a) { + if (a.type.type!=null) + return "new "+a.type.type.name+"()" + else + return a.type.prim.defaultValue + } + + override String getTypedDataDefinition(Message m) { + return languageGen.getTypedData(m) + } + + //**** C-Specific + + // used + def String getCHeaderFileName(RoomClass rc) { + return rc.name+".h"; + } + + // used + def String getCSourceFileName(RoomClass rc) { + return rc.name+".c"; + } + + //------------------------------------------------------- + // transition chain visitor + + def String getExecuteChainCode(ExpandedActorClass ac, TransitionChain tc) { + return languageGen.getExecuteChain(ac, tc) + } +}
\ No newline at end of file diff --git a/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/DataClassGen.xtend b/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/DataClassGen.xtend new file mode 100644 index 000000000..ed7570080 --- /dev/null +++ b/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/DataClassGen.xtend @@ -0,0 +1,100 @@ +/******************************************************************************* + * Copyright (c) 2011 protos software gmbh (http://www.protos.de). + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * CONTRIBUTORS: + * Henrik Rentz-Reichert (initial contribution) + * Thomas Schuetz (changed for C code generator) + * + *******************************************************************************/ + +package org.eclipse.etrice.generator.c.gen + +import com.google.inject.Inject +import com.google.inject.Singleton +import org.eclipse.etrice.core.room.DataClass +import org.eclipse.etrice.generator.base.ILogger +import org.eclipse.etrice.generator.etricegen.Root +import org.eclipse.xtext.generator.JavaIoFileSystemAccess +import org.eclipse.etrice.generator.extensions.RoomExtensions + +@Singleton +class DataClassGen { + + @Inject extension JavaIoFileSystemAccess fileAccess + @Inject extension CExtensions stdExt + @Inject extension RoomExtensions roomExt + @Inject extension ProcedureHelpers helpers + @Inject ILogger logger + + def doGenerate(Root root) { + for (dc: root.usedDataClasses) { + var path = dc.generationTargetPath+dc.getPath + + // header file + var headerFile = dc.getCHeaderFileName + logger.logInfo("generating DataClass header '"+headerFile+"' in '"+path+"'") + fileAccess.setOutputPath(path) + fileAccess.generateFile(headerFile, root.generateHeaderFile(dc)) + + // header file + var sourceFile = dc.getCSourceFileName + logger.logInfo("generating DataClass source '"+headerFile+"' in '"+path+"'") + fileAccess.setOutputPath(path) + fileAccess.generateFile(sourceFile, root.generateSourceFile(dc)) + + } + } + + def generateHeaderFile(Root root, DataClass dc) {''' + package «dc.getPackage()»; + + «var models = root.getReferencedModels(dc)» + «FOR model : models»import «model.name».*; + «ENDFOR» + + «IF dc.imports.size>0» + // user imports + «FOR imp : dc.imports»import «imp.importedNamespace».*; + «ENDFOR»«ENDIF» + + public class «dc.name»«IF dc.base!=null» extends «dc.base.name»«ENDIF» { + «helpers.Attributes(dc.attributes)» + «helpers.AttributeSettersGetters(dc.attributes)» + «helpers.Operations(dc.operations)» + + // default constructor + public «dc.name»() { + «FOR a : dc.attributes» + «IF a.defaultValueLiteral!=null» + «IF a.size==0»«a.name» = «a.defaultValueLiteral»;«ENDIF» + «ELSEIF a.type.type!=null» + «a.name» = new «a.type.type.name»(); + «ENDIF» + «ENDFOR» + } + + // deep copy + public «dc.name» deepCopy() { + «dc.name» copy = new «dc.name»(); + «FOR a : dc.attributes» + «IF a.type.type!=null» + copy.«a.name» = «a.name».deepCopy(); + «ELSE» + «IF a.size==0»copy.«a.name» = «a.name»;«ELSE»for (int i=0;i<«a.size»;i++){copy.«a.name»[i]=«a.name»[i];}«ENDIF» + «ENDIF» + «ENDFOR» + return copy; + } + }; + ''' + } + + def generateSourceFile(Root root, DataClass dc) {''' + '''} + + +}
\ No newline at end of file diff --git a/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/MainGen.xtend b/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/MainGen.xtend new file mode 100644 index 000000000..8ae420117 --- /dev/null +++ b/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/MainGen.xtend @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2011 protos software gmbh (http://www.protos.de). + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * CONTRIBUTORS: + * Henrik Rentz-Reichert (initial contribution) + * + *******************************************************************************/ + +package org.eclipse.etrice.generator.c.gen + +import com.google.inject.Inject +import com.google.inject.Singleton +import org.eclipse.emf.ecore.resource.Resource +import org.eclipse.etrice.generator.etricegen.Root +import org.eclipse.xtext.generator.IFileSystemAccess +import org.eclipse.xtext.generator.IGenerator +import org.eclipse.etrice.generator.extensions.PrepareFileSystem + +@Singleton +class MainGen implements IGenerator { + + @Inject DataClassGen dataClassGen + @Inject ProtocolClassGen protocolClassGen + @Inject ActorClassGen actorClassGen + @Inject SubSystemClassGen subsystemClassGen + @Inject SubSystemRunnerGen subsystemRunnerGen + @Inject PrepareFileSystem prepFS + + override void doGenerate(Resource resource, IFileSystemAccess fsa) { + prepFS.prepare(resource) + for (e: resource.contents){ + if (e instanceof Root) { + doGenerate(e as Root) + } + } + } + + def void doGenerate(Root e) { + dataClassGen.doGenerate(e); + protocolClassGen.doGenerate(e); + actorClassGen.doGenerate(e); + subsystemClassGen.doGenerate(e); + + if (!e.library) { + subsystemRunnerGen.doGenerate(e); + } + } +}
\ No newline at end of file diff --git a/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/ProcedureHelpers.xtend b/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/ProcedureHelpers.xtend new file mode 100644 index 000000000..9f7179f76 --- /dev/null +++ b/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/ProcedureHelpers.xtend @@ -0,0 +1,72 @@ +/******************************************************************************* + * Copyright (c) 2011 protos software gmbh (http://www.protos.de). + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * CONTRIBUTORS: + * Henrik Rentz-Reichert (initial contribution) + * + *******************************************************************************/ + +package org.eclipse.etrice.generator.c.gen + +import com.google.inject.Inject +import com.google.inject.Singleton +import java.util.List +import org.eclipse.etrice.core.room.ActorClass +import org.eclipse.etrice.core.room.Attribute +import org.eclipse.etrice.core.room.DetailCode +import org.eclipse.etrice.core.room.Operation + +@Singleton +class ProcedureHelpers { + + @Inject extension CExtensions stdExt + + def ActorClassPortIF(ActorClass ac) {''' + «IF ac.extPorts.size > 0»implements«ENDIF» + «FOR ep : ac.extPorts»public «ep.ifport.protocol.name»«IF ep.ifport.conjugated==true»Conj«ENDIF»Port «ep.ifport.name» = null; + «ENDFOR» + ''' + } + + def UserCode(DetailCode dc) {''' + «IF dc!=null» + //--------------------- begin user code + «FOR command : dc.commands» «command» + «ENDFOR»//--------------------- end user code + «ENDIF» + ''' + } + + def Attributes(List<Attribute> attribs) {''' + //--------------------- attributes + «FOR attribute : attribs»«IF attribute.size==0»protected «IF attribute.type.ext != null»«attribute.type.ext»«ELSE»«attribute.type.typeName()»«ENDIF» «attribute.name»;«ELSE»protected «attribute.type.typeName()»[] «attribute.name»«IF attribute.defaultValueLiteral==null» =new «attribute.type.typeName()»[«attribute.size»];«ELSE» = «attribute.defaultValueLiteral»;«ENDIF» + «ENDIF» + «ENDFOR» + ''' + } + + def AttributeSettersGetters(List<Attribute> attribs) {''' + //--------------------- attribute setters and getters + «FOR attribute : attribs»public void set«attribute.name.toFirstUpper()» («IF attribute.type.ext != null» «attribute.type.ext»«ELSE»«attribute.type.typeName()»«ENDIF»«IF attribute.size!=0»[]«ENDIF» «attribute.name») { + this.«attribute.name» = «attribute.name»; + } + public «IF attribute.type.ext != null» «attribute.type.ext»«ELSE»«attribute.type.typeName()»«ENDIF»«IF attribute.size!=0»[]«ENDIF» get«attribute.name.toFirstUpper()» () { + return «attribute.name»; + }«ENDFOR» + ''' + } + + def Operations(List<Operation> operations) {''' + //--------------------- operations + «FOR operation : operations»public «IF operation.returntype==null»void«ELSE»«operation.returntype.freeTypeName()»«ENDIF» «operation.name» («FOR argument : operation.arguments SEPARATOR ", "»«argument.type.freeTypeName()» «argument.name»«ENDFOR»){ + «FOR command : operation.detailCode.commands» «command» + «ENDFOR» + }«ENDFOR» + ''' + } + +}
\ No newline at end of file diff --git a/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/ProtocolClassGen.xtend b/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/ProtocolClassGen.xtend new file mode 100644 index 000000000..a9ae1acc1 --- /dev/null +++ b/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/ProtocolClassGen.xtend @@ -0,0 +1,253 @@ +/******************************************************************************* + * Copyright (c) 2011 protos software gmbh (http://www.protos.de). + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * CONTRIBUTORS: + * Henrik Rentz-Reichert (initial contribution) + * + *******************************************************************************/ + +package org.eclipse.etrice.generator.c.gen + +import com.google.inject.Inject +import com.google.inject.Singleton +import org.eclipse.etrice.core.room.Message +import org.eclipse.etrice.core.room.ProtocolClass +import org.eclipse.etrice.generator.base.ILogger +import org.eclipse.etrice.generator.etricegen.Root +import org.eclipse.xtext.generator.JavaIoFileSystemAccess + +import org.eclipse.etrice.generator.extensions.RoomExtensions + +@Singleton +class ProtocolClassGen { + + @Inject extension JavaIoFileSystemAccess fileAccess + @Inject extension CExtensions stdExt + @Inject extension RoomExtensions roomExt + @Inject extension ProcedureHelpers helpers + @Inject ILogger logger + + def doGenerate(Root root) { + for (pc: root.usedProtocolClasses) { + var path = pc.generationTargetPath+pc.getPath + var file = pc.getCHeaderFileName + logger.logInfo("generating ProtocolClass implementation '"+file+"' in '"+path+"'") + fileAccess.setOutputPath(path) + fileAccess.generateFile(file, root.generate(pc)) + } + } + + def generate(Root root, ProtocolClass pc) {''' + package «pc.getPackage()»; + + import java.util.ArrayList; + + import org.eclipse.etrice.runtime.java.messaging.Address; + import org.eclipse.etrice.runtime.java.messaging.Message; + import org.eclipse.etrice.runtime.java.modelbase.*; + import org.eclipse.etrice.runtime.java.debugging.DebuggingService; + + «helpers.UserCode(pc.userCode1)» + + «var models = root.getReferencedModels(pc)» + «FOR model : models»import «model.name».*; + «ENDFOR» + + public class «pc.name» { + // message IDs + // TODO: separate class for message IDs: class MSG{public static volatile int MSG_MIN = 0; ...} -> better structure + // error if msgID <= MSG_MIN + public static final int MSG_MIN = 0; + //IDs for outgoing messages + «FOR message : pc.getAllOutgoingMessages()» + public static final int OUT_«message.name» = «pc.getAllOutgoingMessages().indexOf(message)+1»; + «ENDFOR» + //IDs for incoming messages + «FOR message : pc.getAllIncomingMessages()» + public static final int IN_«message.name» = «pc.getAllIncomingMessages().indexOf(message)+pc.getAllOutgoingMessages().size+1»; + «ENDFOR» + //error if msgID >= MSG_MAX + public static final int MSG_MAX = «pc.getAllOutgoingMessages().size + pc.getAllIncomingMessages().size+1»; + + «helpers.UserCode(pc.userCode2)» + + private static String messageStrings[] = {"MIN", «FOR m : pc.getAllOutgoingMessages()»"«m.name»",«ENDFOR» «FOR m : pc.getAllIncomingMessages()»"«m.name»",«ENDFOR»"MAX"}; + + public String getMessageString(int msg_id) { + if (msg_id<0 || msg_id>MSG_MAX+1){ + // id out of range + return "Message ID out of range"; + } + else{ + return messageStrings[msg_id]; + } + } + + «portClass(pc, false)» + «portClass(pc, true)» + } + ''' + } + + def portClass(ProtocolClass pc, Boolean conj) {''' + «var name = pc.getPortClassName(conj)» + «var pclass = pc.getPortClass(conj)» + + // port class + static public class «name» extends PortBase { + «IF pclass!=null» + «helpers.UserCode(pclass.userCode)» + «ENDIF» + // constructors + public «name»(IEventReceiver actor, String name, int localId, Address addr, Address peerAddress) { + super(actor, name, localId, 0, addr, peerAddress); + DebuggingService.getInstance().addPortInstance(this); + } + public «name»(IEventReceiver actor, String name, int localId, int idx, Address addr, Address peerAddress) { + super(actor, name, localId, idx, addr, peerAddress); + DebuggingService.getInstance().addPortInstance(this); + } + + @Override + public void receive(Message m) { + if (!(m instanceof EventMessage)) + return; + EventMessage msg = (EventMessage) m; + if (msg.getEvtId() <= 0 || msg.getEvtId() >= MSG_MAX) + System.out.println("unknown"); + else { + if (messageStrings[msg.getEvtId()] != "timerTick"){ + // TODOTS: model switch for activation + DebuggingService.getInstance().addMessageAsyncIn(getPeerAddress(), getAddress(), messageStrings[msg.getEvtId()]); + } + «IF pc.handlesReceive(conj)» + switch (msg.getEvtId()) { + «FOR hdlr : pc.getReceiveHandlers(conj)» + case «hdlr.msg.getCodeName()»: + { + «FOR command : hdlr.detailCode.commands» + «command» + «ENDFOR» + } + break; + «ENDFOR» + default: + «ENDIF» + if (msg instanceof EventWithDataMessage) + getActor().receiveEvent(this, msg.getEvtId(), ((EventWithDataMessage)msg).getData()); + else + getActor().receiveEvent(this, msg.getEvtId(), null); + «IF pc.handlesReceive(conj)» + } + «ENDIF» + } + } + + «IF pclass!=null» + «helpers.Attributes(pclass.attributes)» + «helpers.Operations(pclass.operations)» + «ENDIF» + + // sent messages + «FOR m : pc.getOutgoing(conj)» + «sendMessage(m, conj)» + «ENDFOR» + } + + // replicated port class + static public class «name»Repl { + private ArrayList<«name»> ports; + private int replication; + + public «name»Repl(IEventReceiver actor, String name, int localId, Address[] addr, + Address[] peerAddress) { + replication = addr.length; + ports = new ArrayList<«pc.name».«name»>(replication); + for (int i=0; i<replication; ++i) { + ports.add(new «name»( + actor, name+i, localId, i, addr[i], peerAddress[i])); + } + } + + public int getReplication() { + return replication; + } + + public int getIndexOf(InterfaceItemBase ifitem){ + return ifitem.getIdx(); + } + + public «name» get(int i) { + return ports.get(i); + } + + «IF conj» + // incoming messages + «FOR m : pc.getAllIncomingMessages()» + «messageSignature(m)»{ + for (int i=0; i<replication; ++i) { + ports.get(i).«messageCall(m)»; + } + } + «ENDFOR» + «ELSE» + // outgoing messages + «FOR m : pc.getAllOutgoingMessages()» + «messageSignature(m)»{ + for (int i=0; i<replication; ++i) { + ports.get(i).«messageCall(m)»; + } + } + «ENDFOR» + «ENDIF» + } + + // interface for port class + public interface I«name»{ + «IF conj» + // outgoing messages + «FOR m : pc.getAllOutgoingMessages()» «messageSignature(m)»; + «ENDFOR» + «ELSE» + // incoming messages + «FOR m : pc.getAllIncomingMessages()» «messageSignature(m)»; + «ENDFOR» + «ENDIF» + } + ''' + } + + def messageSignature(Message m) {''' + public void «m.name» («IF m.data!=null»«m.data.type.typeName()» «m.data.name»«ENDIF») + ''' + } + + def messageCall(Message m) {''' + «m.name»(«IF m.data!=null» «m.data.name»«ENDIF») + '''} + + def sendMessage(Message m, boolean conj) {''' + «var dir = if (conj) "IN" else "OUT"» + «var hdlr = m.getSendHandler(conj)» + «messageSignature(m)»{ + «IF hdlr!=null» + «FOR command : hdlr.detailCode.commands» «command» + «ENDFOR» + «ELSE» + if (messageStrings[ «dir»_«m.name»] != "timerTick"){ + // TODOTS: model switch for activation + DebuggingService.getInstance().addMessageAsyncOut(getAddress(), getPeerAddress(), messageStrings[«dir»_«m.name»]); + } + if (getPeerAddress()!=null) + «IF m.data==null»getPeerMsgReceiver().receive(new EventMessage(getPeerAddress(), «dir»_«m.name»)); + «ELSE»getPeerMsgReceiver().receive(new EventWithDataMessage(getPeerAddress(), «dir»_«m.name», «m.data.name»«IF (!m.data.type.ref && m.data.type.type!=null)».deepCopy()«ENDIF»)); + «ENDIF» + «ENDIF» + } + ''' + } +}
\ No newline at end of file diff --git a/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/StateMachineGen.xtend b/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/StateMachineGen.xtend new file mode 100644 index 000000000..44fdc9e43 --- /dev/null +++ b/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/StateMachineGen.xtend @@ -0,0 +1,258 @@ +/******************************************************************************* + * Copyright (c) 2011 protos software gmbh (http://www.protos.de). + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * CONTRIBUTORS: + * Henrik Rentz-Reichert (initial contribution) + * + *******************************************************************************/ + +package org.eclipse.etrice.generator.c.gen + +import com.google.inject.Inject +import com.google.inject.Singleton +import java.util.List +import org.eclipse.etrice.core.room.ActorClass +import org.eclipse.etrice.core.room.NonInitialTransition +import org.eclipse.etrice.core.room.Transition +import org.eclipse.etrice.core.room.TriggeredTransition +import org.eclipse.etrice.generator.etricegen.ExpandedActorClass +import org.eclipse.etrice.generator.etricegen.TransitionChain +import static extension org.eclipse.etrice.generator.extensions.RoomNameProv.* +import org.eclipse.etrice.generator.extensions.RoomExtensions +import org.eclipse.etrice.generator.generic.LanguageGenerator + + +@Singleton +class StateMachineGen { + + @Inject extension CExtensions stdExt + @Inject extension RoomExtensions roomExt + @Inject LanguageGenerator languageGen + + def genStateMachine(ExpandedActorClass xpac, ActorClass ac) {''' + //****************************************** + // START of generated code for FSM + //****************************************** + + // State IDs for FSM + «var offset = ac.getNumberOfInheritedBaseStates()» + «var baseStates = ac.stateMachine.getBaseStateList()» + «FOR state : baseStates» + protected static final int «state.getStateId()» = «baseStates.indexOf(state)+2+offset»; + «ENDFOR» + protected static final String stateStrings[] = {"<no state>","<top>",«FOR state : ac.getAllBaseStates() SEPARATOR ","»"«state.getStatePathName()»" + «ENDFOR»}; + + // history + // TODOHRR: history defined in ActorClassBase, init in constructor + // history = new int[5]; + // for (int i = 0; i < history.length; i++) { + // history[i] = NO_STATE; + // } + protected int history[] = {NO_STATE,NO_STATE«FOR state : ac.getAllBaseStates()»,NO_STATE«ENDFOR»}; + + «var List<TransitionChain> chains = xpac.getOwnTransitionChains()» + «var offset_tc = xpac.getTransitionChains().size-chains.size» + // transition chains + «FOR tc : chains» + protected static final int «tc.getChainId()» = «chains.indexOf(tc)+1+offset_tc»; + «ENDFOR» + + «var triggers = xpac.getOwnTriggers()» + // triggers for FSM + «FOR mif : triggers»protected static final int «xpac.getTriggerCodeName(mif)» = IFITEM_«mif.from.name» + EVT_SHIFT*«xpac.getMessageID(mif)»; + «ENDFOR» + + // receiveEvent contains the main implementation of the FSM + @Override + public void receiveEvent(InterfaceItemBase ifitem, int evt, Object generic_data) { + int trigger = ifitem.getLocalId() + EVT_SHIFT*evt; + int chain = NOT_CAUGHT; + int catching_state = NO_STATE; + boolean is_handler = false; + boolean skip_entry = false; + + if (!handleSystemEvent(ifitem, evt, generic_data)) { + switch (state) { + «FOR state : xpac.stateMachine.getLeafStateList()» + case «state.getStateId()»: + «var atlist = xpac.getActiveTriggers(state)» + «IF !atlist.isEmpty» + switch(trigger) { + «FOR at : atlist» + case «xpac.getTriggerCodeName(at.trigger)»: + «var needData = xpac.hasGuard(at)» + «IF needData»{ «at.msg.getTypedDataDefinition()»«ENDIF» + «FOR tt : at.transitions SEPARATOR " else "» + «var chain = xpac.getChain(tt)» + «guard(chain.transition, at.trigger, xpac)» + { + chain = «chain.getChainId()»; + catching_state = «chain.getContextId()»; + «IF chain.isHandler()»is_handler = true;«ENDIF» + «IF chain.skipEntry»skip_entry = true;«ENDIF» + } + «ENDFOR» + «IF needData»}«ENDIF» + break; + «ENDFOR» + } + «ENDIF» + break; + «ENDFOR» + } + } + if (chain != NOT_CAUGHT) { + exitTo(state, catching_state, is_handler); + int next = executeTransitionChain(chain, ifitem, generic_data); + next = enterHistory(next, is_handler, skip_entry); + setState(next); + } + } + + private void setState(int new_state) { + DebuggingService.getInstance().addActorState(this,stateStrings[new_state]); + if (stateStrings[new_state]!="Idle") { + // TODOTS: model switch for activation + System.out.println(getInstancePath() + " -> " + stateStrings[new_state]); + } + this.state = new_state; + } + + @Override + public void executeInitTransition() { + «var initt = xpac.stateMachine.getInitTransition()» + int chain = «xpac.getChain(initt).getChainId()»; + int next = executeTransitionChain(chain, null, null); + next = enterHistory(next, false, false); + setState(next); + } + + /** + * calls exit codes while exiting from the current state to one of its + * parent states while remembering the history + * @param current - the current state + * @param to - the final parent state + * @param handler - entry and exit codes are called only if not handler (for handler TransitionPoints) + */ + private void exitTo(int current, int to, boolean handler) { + while (current!=to) { + switch (current) { + «FOR state : xpac.stateMachine.getBaseStateList()» + case «state.getStateId()»: + «IF state.hasExitCode()»if (!handler) «state.getExitCodeOperationName()»();«ENDIF» + history[«state.getParentStateId()»] = «state.getStateId()»; + current = «state.getParentStateId()»; + break; + «ENDFOR» + } + } + } + /** + * calls action, entry and exit codes along a transition chain. The generic data are cast to typed data + * matching the trigger of this chain. The ID of the final state is returned + * @param chain - the chain ID + * @param generic_data - the generic data pointer + * @return the ID of the final state + */ + private int executeTransitionChain(int chain, InterfaceItemBase ifitem, Object generic_data) { + switch (chain) { + «var allchains = xpac.getTransitionChains()» + «FOR tc : allchains» + case «tc.getChainId()»: + { + «xpac.getExecuteChainCode(tc)» + } + «ENDFOR» + } + return NO_STATE; + } + /** + * calls entry codes while entering a state's history. The ID of the final leaf state is returned + * @param state - the state which is entered + * @param handler - entry code is executed if not handler + * @return - the ID of the final leaf state + */ + private int enterHistory(int state, boolean handler, boolean skip_entry) { + while (true) { + switch (state) { + «FOR state : xpac.stateMachine.getBaseStateList()» + case «state.getStateId()»: + «IF state.hasEntryCode()»if (!(skip_entry || handler)) «state.getEntryCodeOperationName()»();«ENDIF» + «IF state.isLeaf()» + // in leaf state: return state id + return «state.getStateId()»; + «ELSE» + // state has a sub graph + «IF state.subgraph.hasInitTransition()» + // with init transition + if (history[«state.getStateId()»]==NO_STATE) { + «var sub_initt = state.subgraph.getInitTransition()» + state = executeTransitionChain(«xpac.getChain(sub_initt).getChainId()», null, null); + } + else { + state = history[«state.getStateId()»]; + } + «ELSE» + // without init transition + state = history[«state.getStateId()»]; + «ENDIF» + break; + «ENDIF» + «ENDFOR» + case STATE_TOP: + state = history[STATE_TOP]; + break; + } + skip_entry = false; + } + //return NO_STATE; // required by CDT but detected as unreachable by JDT because of while (true) + } + + //*** Entry and Exit Codes + «FOR state : xpac.stateMachine.getStateList()» + «IF xpac.isOwnObject(state)» + «IF state.hasEntryCode()» + protected void «state.getEntryCodeOperationName()»() { + «xpac.getEntryCode(state)» + } + «ENDIF» + «IF state.hasExitCode()» + protected void «state.getExitCodeOperationName()»() { + «xpac.getExitCode(state)» + } + «ENDIF» + «ENDIF» + «ENDFOR» + + //*** Action Codes + «FOR tr : xpac.stateMachine.getTransitionList()» + «IF xpac.isOwnObject(tr) && tr.hasActionCode()» + protected void «tr.getActionCodeOperationName()»(«IF tr instanceof NonInitialTransition»InterfaceItemBase ifitem«languageGen.getArgumentList(xpac, tr)»«ENDIF») { + «xpac.getActionCode(tr)» + } + «ENDIF» + «ENDFOR» + + //****************************************** + // END of generated code for FSM + //****************************************** + '''} + + def dispatch guard(TriggeredTransition tt, String trigger, ExpandedActorClass ac) {''' + «var tr = tt.triggers.findFirst(e|ac.isMatching(e, trigger))» + «IF tr.hasGuard()» + if («ac.getCode(tr.guard.guard)») + «ENDIF» + ''' + } + + def dispatch guard(Transition t, String trigger, ExpandedActorClass ac) {''' + /* error */ + ''' + } +} diff --git a/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/SubSystemClassGen.xtend b/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/SubSystemClassGen.xtend new file mode 100644 index 000000000..18b6ab74a --- /dev/null +++ b/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/SubSystemClassGen.xtend @@ -0,0 +1,177 @@ +/******************************************************************************* + * Copyright (c) 2011 protos software gmbh (http://www.protos.de). + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * CONTRIBUTORS: + * Henrik Rentz-Reichert (initial contribution) + * + *******************************************************************************/ + +package org.eclipse.etrice.generator.c.gen + +import com.google.inject.Inject +import com.google.inject.Singleton +import org.eclipse.etrice.core.room.SubSystemClass +import org.eclipse.etrice.generator.base.ILogger +import org.eclipse.etrice.generator.etricegen.Root +import org.eclipse.etrice.generator.etricegen.ServiceImplInstance +import org.eclipse.etrice.generator.etricegen.SubSystemInstance +import org.eclipse.xtext.generator.JavaIoFileSystemAccess +import org.eclipse.etrice.generator.extensions.RoomExtensions + +import static extension org.eclipse.etrice.generator.base.Indexed.* + + +@Singleton +class SubSystemClassGen { + + @Inject extension JavaIoFileSystemAccess fileAccess + @Inject extension CExtensions stdExt + @Inject extension RoomExtensions roomExt + @Inject extension ProcedureHelpers helpers + @Inject ILogger logger + + def doGenerate(Root root) { + for (ssi: root.subSystemInstances) { + var path = ssi.subSystemClass.generationTargetPath+ssi.subSystemClass.getPath + var file = ssi.subSystemClass.getCHeaderFileName + logger.logInfo("generating SubSystemClass implementation: '"+file+"' in '"+path+"'") + fileAccess.setOutputPath(path) + fileAccess.generateFile(file, root.generate(ssi, ssi.subSystemClass)) + } + } + + def generate(Root root, SubSystemInstance comp, SubSystemClass cc) {''' + package «cc.getPackage()»; + + import org.eclipse.etrice.runtime.java.messaging.MessageService; + import org.eclipse.etrice.runtime.java.messaging.RTServices; + import org.eclipse.etrice.runtime.java.messaging.Address; + import org.eclipse.etrice.runtime.java.messaging.IRTObject; + import org.eclipse.etrice.runtime.java.messaging.RTSystemServicesProtocol.*; + import org.eclipse.etrice.runtime.java.modelbase.ActorClassBase; + import org.eclipse.etrice.runtime.java.modelbase.SubSystemClassBase; + import org.eclipse.etrice.runtime.java.modelbase.InterfaceItemBase; + + «var models = root.getReferencedModels(cc)» + «FOR model : models»import «model.name».*;«ENDFOR» + + + «helpers.UserCode(cc.userCode1)» + + public class «comp.name» extends SubSystemClassBase{ + + «helpers.UserCode(cc.userCode2)» + + public «comp.name»(IRTObject parent, String name) { + super(parent, name); + } + + @Override + public void receiveEvent(InterfaceItemBase ifitem, int evt, Object data){ + } + + @Override + public void instantiateMessageServices(){ + + RTServices.getInstance().getMsgSvcCtrl().addMsgSvc(new MessageService(this, new Address(0, 0, 0),"MessageService_Main")); + «FOR thread : cc.threads» + RTServices.getInstance().getMsgSvcCtrl().addMsgSvc(new MessageService(this, new Address(0, «cc.threads.indexOf(thread)+1», 0),"MessageService_«thread.name»", «thread.prio»)); + «ENDFOR» + } + + @Override + public void instantiateActors(){ + // all addresses + // Addresses for the Subsystem Systemport + «FOR ai : comp.allContainedInstances.indexed(comp.maxObjId)» + Address addr_item_SystemPort_«comp.allContainedInstances.indexOf(ai.value)» = new Address(0,0,«ai.index1»); + «ENDFOR» + + «FOR ai : comp.allContainedInstances» + // actor instance «ai.path» itself => Systemport Address + // TODOTJ: For each Actor, multiple addresses should be generated (actor?, systemport, debugport) + Address addr_item_«ai.path.getPathName()» = new Address(0,«ai.threadId»,«ai.objId»); + // interface items of «ai.path» + «FOR pi : ai.orderedIfItemInstances» + «IF pi instanceof ServiceImplInstance || pi.peers.size>1» + «FOR peer : pi.peers» + «var i = pi.peers.indexOf(peer)» + Address addr_item_«pi.path.getPathName()»_«i» = new Address(0,«pi.threadId»,«pi.objId+i»); + «ENDFOR» + «ELSE» + Address addr_item_«pi.path.getPathName()» = new Address(0,«ai.threadId»,«pi.objId»); + «ENDIF» + «ENDFOR» + «ENDFOR» + + // instantiate all actor instances + instances = new ActorClassBase[«comp.allContainedInstances.size»]; + «FOR ai : comp.allContainedInstances» + instances[«comp.allContainedInstances.indexOf(ai)»] = new «ai.actorClass.name»( + «IF ai.eContainer instanceof SubSystemInstance» + this, + «ELSE» + instances[«comp.allContainedInstances.indexOf(ai.eContainer)»], + «ENDIF» + "«ai.name»", + // own interface item addresses + new Address[][] {{addr_item_«ai.path.getPathName()»}«IF !ai.orderedIfItemInstances.empty»,«ENDIF» + «FOR pi : ai.orderedIfItemInstances SEPARATOR ","» + { + «IF pi instanceof ServiceImplInstance || pi.peers.size>1» + «FOR peer : pi.peers SEPARATOR ","» + addr_item_«pi.path.getPathName()»_«pi.peers.indexOf(peer)» + «ENDFOR» + «ELSE» + addr_item_«pi.path.getPathName()» + «ENDIF» + } + «ENDFOR» + }, + // peer interface item addresses + new Address[][] {{addr_item_SystemPort_«comp.allContainedInstances.indexOf(ai)»}«IF !ai.orderedIfItemInstances.empty»,«ENDIF» + «FOR pi : ai.orderedIfItemInstances SEPARATOR ","» + { + «IF !(pi instanceof ServiceImplInstance) && pi.peers.isEmpty» + null + «ELSE» + «FOR pp : pi.peers SEPARATOR ","» + «IF pp instanceof ServiceImplInstance || pp.peers.size>1» + addr_item_«pp.path.getPathName()»_«pp.peers.indexOf(pi)» + «ELSE» + addr_item_«pp.path.getPathName()» + «ENDIF» + «ENDFOR» + «ENDIF» + } + «ENDFOR» + } + ); + «ENDFOR» + + // create the subsystem system port + RTSystemPort = new RTSystemServicesProtocolConjPortRepl(this, "RTSystemPort", + 0, //local ID + // own addresses + new Address[]{ + «FOR ai : comp.allContainedInstances SEPARATOR ","» + addr_item_SystemPort_«comp.allContainedInstances.indexOf(ai)» + «ENDFOR» + }, + // peer addresses + new Address[]{ + «FOR ai : comp.allContainedInstances SEPARATOR ","» + addr_item_«ai.path.getPathName()» + «ENDFOR» + }); + + } + }; + ''' + } + +}
\ No newline at end of file diff --git a/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/SubSystemRunnerGen.xtend b/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/SubSystemRunnerGen.xtend new file mode 100644 index 000000000..5e4a1fcf3 --- /dev/null +++ b/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/SubSystemRunnerGen.xtend @@ -0,0 +1,75 @@ +/******************************************************************************* + * Copyright (c) 2011 protos software gmbh (http://www.protos.de). + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * CONTRIBUTORS: + * Henrik Rentz-Reichert (initial contribution) + * + *******************************************************************************/ + +package org.eclipse.etrice.generator.c.gen + +import com.google.inject.Inject +import com.google.inject.Singleton +import org.eclipse.etrice.core.room.SubSystemClass +import org.eclipse.etrice.generator.etricegen.Root +import org.eclipse.etrice.generator.etricegen.SubSystemInstance +import org.eclipse.xtext.generator.JavaIoFileSystemAccess +import org.eclipse.etrice.generator.extensions.RoomExtensions + +@Singleton +class SubSystemRunnerGen { + + @Inject extension JavaIoFileSystemAccess fileAccess + @Inject extension RoomExtensions roomExt + + def doGenerate(Root root) { + for (sc: root.subSystemInstances) { + fileAccess.setOutputPath(sc.subSystemClass.generationTargetPath+sc.subSystemClass.getPath) + fileAccess.generateFile( sc.name+"Runner.java", root.generate(sc, sc.subSystemClass)) + } + } + + def generate(Root root, SubSystemInstance ssc, SubSystemClass cc) {''' + /** + * @author generated by eTrice + * + * this class contains the main function running component «ssc.name» + * it instantiates «ssc.name» and starts and ends the lifecycle + */ + + package «cc.getPackage()»; + + import org.eclipse.etrice.runtime.java.modelbase.SubSystemRunnerBase; + + class «ssc.name+"Runner"» extends SubSystemRunnerBase { + + static «ssc.name» main_component = new «ssc.name»(null, "«ssc.name»"); + + /** + * main function + * creates component and starts and stops the lifecycle + */ + public static void main(String[] args) { + + System.out.println("*** T H E B E G I N ***"); + + main_component.init(); // lifecycle init + main_component.start(); // lifecycle start + + // application runs until quit + waitForQuit(); + + // end the lifecycle + main_component.stop(); // lifecycle stop + main_component.destroy(); // lifecycle destroy + + System.out.println("*** T H E E N D ***"); + } + }; + ''' + } +}
\ No newline at end of file diff --git a/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/Validator.java b/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/Validator.java new file mode 100644 index 000000000..d54869526 --- /dev/null +++ b/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/Validator.java @@ -0,0 +1,101 @@ +/******************************************************************************* + * Copyright (c) 2011 protos software gmbh (http://www.protos.de). + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * CONTRIBUTORS: + * Henrik Rentz-Reichert (initial contribution) + * + *******************************************************************************/ + +package org.eclipse.etrice.generator.c.gen; + +import org.eclipse.emf.common.util.TreeIterator; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.etrice.core.naming.RoomNameProvider; +import org.eclipse.etrice.core.room.Attribute; +import org.eclipse.etrice.core.room.Message; +import org.eclipse.etrice.core.room.Operation; +import org.eclipse.etrice.core.room.RoomClass; +import org.eclipse.etrice.core.room.RoomModel; +import org.eclipse.etrice.core.room.BasicType; +import org.eclipse.etrice.core.room.Type; +import org.eclipse.etrice.core.room.FreeType; +import org.eclipse.etrice.generator.base.ILogger; +import org.eclipse.etrice.generator.etricegen.Root; + +import com.google.inject.Inject; + +/** + * @author Henrik Rentz-Reichert + * + */ +public class Validator { + + @Inject + private ILogger logger; + + public boolean validate(Root genModel) { + int errorCount = 0; + for (RoomModel mdl : genModel.getUsedRoomModels()) { + TreeIterator<EObject> it = mdl.eAllContents(); + while (it.hasNext()) { + EObject obj = it.next(); + if (obj instanceof BasicType) { + if (!checkValidType((BasicType) obj)) + errorCount++; + } + } + } + + if (errorCount>0) { + logger.logError("Java generator detected "+errorCount+" error(s) - terminating", null); + return false; + } + + return true; + } + + /** + * @param type + * @return true if type is a valid Java type + */ + private boolean checkValidType(BasicType type) { + boolean isPrimitive = (type instanceof Type)? ((Type)type).getType()==null : ((FreeType)type).getType()==null; + if (isPrimitive) { + switch (type.getPrim()) { + case UINT8: + case UINT16: + case UINT32: + RoomClass roomClass = RoomNameProvider.getModelClass(type); + String location = RoomNameProvider.getClassLocation(roomClass); + String where = getWhere(type); + logger.logError("Java doesn't support unsigned types ("+where+" of "+location+")", null); + return false; + } + } + return true; + } + + private String getWhere(BasicType type) { + EObject obj = type; + while (obj!=null) { + if (obj instanceof Attribute) { + Attribute att = (Attribute) obj; + return "Attribute "+att.getName(); + } + else if (obj instanceof Operation) { + Operation op = (Operation) obj; + return "Operation "+op.getName(); + } + else if (obj instanceof Message) { + Message msg = (Message) obj; + return "Message "+msg.getName(); + } + obj = obj.eContainer(); + } + return "unknown"; + } +} diff --git a/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/setup/GeneratorModule.java b/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/setup/GeneratorModule.java new file mode 100644 index 000000000..55e11d088 --- /dev/null +++ b/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/setup/GeneratorModule.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2011 protos software gmbh (http://www.protos.de). + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * CONTRIBUTORS: + * Henrik Rentz-Reichert (initial contribution) + * + *******************************************************************************/ + +package org.eclipse.etrice.generator.c.setup; + +import org.eclipse.etrice.generator.base.AbstractGenerator; +import org.eclipse.etrice.generator.base.GeneratorBaseModule; +import org.eclipse.etrice.generator.c.Main; +import org.eclipse.etrice.generator.c.gen.MainGen; +import org.eclipse.xtext.generator.IGenerator; + +import com.google.inject.Binder; + +public class GeneratorModule extends GeneratorBaseModule { + +// @Override + public void configure(Binder binder) { + super.configure(binder); + + binder.bind(AbstractGenerator.class).to(Main.class); + binder.bind(IGenerator.class).to(MainGen.class); + } + +} |