Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Schuetz2011-12-23 15:12:42 +0000
committerThomas Schuetz2011-12-23 15:12:42 +0000
commitf502cbe9485f647ecd273222bf53717fa00c5043 (patch)
treef7e19a27ecb36d9255ea8f7a5f22bcb98a625c78 /plugins/org.eclipse.etrice.generator.c/src
parentf9975ec475dc447886695489cfafba8adb5b7860 (diff)
downloadorg.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')
-rw-r--r--plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/Main.java119
-rw-r--r--plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/ActorClassGen.xtend170
-rw-r--r--plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/CExtensions.xtend107
-rw-r--r--plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/DataClassGen.xtend100
-rw-r--r--plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/MainGen.xtend52
-rw-r--r--plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/ProcedureHelpers.xtend72
-rw-r--r--plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/ProtocolClassGen.xtend253
-rw-r--r--plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/StateMachineGen.xtend258
-rw-r--r--plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/SubSystemClassGen.xtend177
-rw-r--r--plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/SubSystemRunnerGen.xtend75
-rw-r--r--plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/Validator.java101
-rw-r--r--plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/setup/GeneratorModule.java33
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);
+ }
+
+}

Back to the top