Browse Source

Merge pull request #629 from Yakindu/issue_627

Issue 627
jdicks 9 years ago
parent
commit
725720ae26
14 changed files with 399 additions and 146 deletions
  1. 20 1
      plugins/org.yakindu.sct.generator.c/src/org/yakindu/sct/generator/c/CCodeGenerator.java
  2. 41 9
      plugins/org.yakindu.sct.generator.c/src/org/yakindu/sct/generator/c/CGenerator.xtend
  3. 143 0
      plugins/org.yakindu.sct.generator.c/src/org/yakindu/sct/generator/c/GenArtifactConfigurations.java
  4. 9 0
      plugins/org.yakindu.sct.generator.c/src/org/yakindu/sct/generator/c/IContentTemplate.java
  5. 57 0
      plugins/org.yakindu.sct.generator.c/src/org/yakindu/sct/generator/c/IGenArtifactConfigurations.java
  6. 19 13
      plugins/org.yakindu.sct.generator.c/src/org/yakindu/sct/generator/c/StatemachineHeader.xtend
  7. 80 86
      plugins/org.yakindu.sct.generator.c/src/org/yakindu/sct/generator/c/StatemachineRequiredHeader.xtend
  8. 10 16
      plugins/org.yakindu.sct.generator.c/src/org/yakindu/sct/generator/c/StatemachineSource.xtend
  9. 2 18
      plugins/org.yakindu.sct.generator.c/src/org/yakindu/sct/generator/c/Types.xtend
  10. 3 0
      plugins/org.yakindu.sct.generator.core/src/org/yakindu/sct/generator/core/filesystem/EFSResourceFileSystemAccess.java
  11. 2 0
      plugins/org.yakindu.sct.generator.core/src/org/yakindu/sct/generator/core/filesystem/ISCTFileSystemAccess.java
  12. 5 1
      plugins/org.yakindu.sct.generator.core/src/org/yakindu/sct/generator/core/util/EFSHelper.java
  13. 6 0
      plugins/org.yakindu.sct.generator.cpp/src/org/yakindu/sct/generator/cpp/CppCodeGenerator.java
  14. 2 2
      plugins/org.yakindu.sct.generator.cpp/src/org/yakindu/sct/generator/cpp/StatemachineHeader.xtend

+ 20 - 1
plugins/org.yakindu.sct.generator.c/src/org/yakindu/sct/generator/c/CCodeGenerator.java

@@ -44,13 +44,26 @@ public class CCodeGenerator extends GenericJavaBasedGenerator {
 	@Inject
 	private CGenerator delegate;
 	
+	@Inject
+	private IGenArtifactConfigurations artifactConfigs;
+	
+	@Override
+	protected void prepareGenerator(GeneratorEntry entry) {
+		super.prepareGenerator(entry);
+		initGenArtifactConfigurations();
+	}
+
+	protected void initGenArtifactConfigurations() {
+		artifactConfigs.setFileSystemAccess(sctFsa);
+	}
+	
 	@Override
 	public void runGenerator(Statechart statechart, GeneratorEntry entry) {
 		ExecutionFlow flow = createExecutionFlow(statechart, entry);
 		if (debugFeatureHelper.isDumpSexec(entry)) {
 			dumpSexec(entry, flow);
 		}
-		delegate.generate(flow, entry, sctFsa.getIFileSystemAccess());
+		delegate.generate(flow, entry, sctFsa.getIFileSystemAccess(), artifactConfigs);
 	}
 
 	@Override
@@ -63,6 +76,12 @@ public class CCodeGenerator extends GenericJavaBasedGenerator {
 				binder.bind(GeneratorEntry.class).toInstance(entry);
 				binder.bind(INamingService.class).to(CNamingService.class);
 				binder.bind(ICodegenTypeSystemAccess.class).to(CTypeSystemAccess.class);
+				
+				binder.bind(IGenArtifactConfigurations.class).to(GenArtifactConfigurations.class);
+				// default binding to ensure consistency of already used API
+				binder.bind(IGenArtifactConfigurations.class)
+						.annotatedWith(Names.named(IGenArtifactConfigurations.DEFAULT))
+						.toInstance(GenArtifactConfigurations.DEFAULT);
 
 				// Enable generation of trace steps in case the Tracing feature
 				// is specified and at least one of enter/exit states is

+ 41 - 9
plugins/org.yakindu.sct.generator.c/src/org/yakindu/sct/generator/c/CGenerator.xtend

@@ -11,11 +11,13 @@
 package org.yakindu.sct.generator.c
 
 import com.google.inject.Inject
+import com.google.inject.name.Named
 import org.eclipse.xtext.generator.IFileSystemAccess
 import org.yakindu.sct.generator.core.impl.IExecutionFlowGenerator
 import org.yakindu.sct.model.sexec.ExecutionFlow
 import org.yakindu.sct.model.sgen.GeneratorEntry
-import org.yakindu.sct.model.sgraph.Statechart
+import org.yakindu.sct.generator.core.library.IOutletFeatureHelper
+import org.yakindu.sct.generator.c.GenArtifactConfigurations.GenArtifactConfiguration
 
 /**
  * This is the C code generators main class. 
@@ -24,19 +26,49 @@ import org.yakindu.sct.model.sgraph.Statechart
  */
 class CGenerator implements IExecutionFlowGenerator {
 	 
-	@Inject extension Types
-	@Inject extension StatemachineHeader
-	@Inject extension StatemachineSource
-	@Inject extension StatemachineRequiredHeader
+	@Inject extension Types types
+	@Inject extension StatemachineHeader statemachineHeader
+	@Inject extension StatemachineSource statemachineSource
+	@Inject extension StatemachineRequiredHeader statemachineRequiredHeader
 	@Inject extension Navigation
 	@Inject extension GenmodelEntries
+	@Inject extension Naming
 	
+	@Inject IOutletFeatureHelper outletFeatureHelper
+
+	@Inject @Named(IGenArtifactConfigurations.DEFAULT)
+	IGenArtifactConfigurations defaultConfigs
+	
+	/**
+	 * @Deprecated use {@link #generate(ExecutionFlow, GeneratorEntry, IFileSystemAccess, ArtifactLocationProvider)} instead
+	 */
+	@Deprecated
 	override generate(ExecutionFlow flow, GeneratorEntry entry, IFileSystemAccess fsa) {
-		flow.generateTypesH(flow.sourceElement as Statechart, fsa, entry)
-		flow.generateStatemachineHeader(flow.sourceElement as Statechart, fsa, entry)
+		generate(flow, entry, fsa, defaultConfigs)
+	}
+	
+	def generate(ExecutionFlow flow, GeneratorEntry entry, IFileSystemAccess fsa, IGenArtifactConfigurations locations) {
+		initGenerationArtifacts(flow, entry, locations)
+		generateArtifacts(flow, entry, fsa, locations);
+	}
+	
+	def generateArtifacts(ExecutionFlow flow, GeneratorEntry entry, IFileSystemAccess fsa, IGenArtifactConfigurations locations) {
+		for (GenArtifactConfiguration a : locations.configurations) {
+			fsa.generateFile(a.getName, a.getOutputName, a.getContentTemplate.content(flow, entry, locations))
+		}
+	}
+	
+	def protected initGenerationArtifacts(ExecutionFlow flow, GeneratorEntry entry, IGenArtifactConfigurations locations) {
+		if (outletFeatureHelper.getLibraryTargetFolderValue(entry) != null) {
+			locations.configure(flow.typesModule.h, IExecutionFlowGenerator.LIBRARY_TARGET_FOLDER_OUTPUT, types)
+		} else {
+			locations.configure(flow.typesModule.h, IExecutionFlowGenerator.TARGET_FOLDER_OUTPUT, types)
+		}
+		locations.configure(flow.module.h, IExecutionFlowGenerator.TARGET_FOLDER_OUTPUT, statemachineHeader)
+		locations.configure(flow.module.c, IExecutionFlowGenerator.TARGET_FOLDER_OUTPUT, statemachineSource)
 		if (flow.timed || !flow.operations.empty || entry.tracingEnterState || entry.tracingExitState) {
-			flow.generateStatemachineRequiredHeader(flow.sourceElement as Statechart, fsa, entry)
+			locations.configure(flow.module.client.h, IExecutionFlowGenerator.TARGET_FOLDER_OUTPUT, statemachineRequiredHeader)
 		}
-		flow.generateStatemachineSource(flow.sourceElement as Statechart, fsa, entry)
 	}
+	
 }

+ 143 - 0
plugins/org.yakindu.sct.generator.c/src/org/yakindu/sct/generator/c/GenArtifactConfigurations.java

@@ -0,0 +1,143 @@
+/**
+ * Copyright (c) 2016 committers of YAKINDU and others.
+ * 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:
+ * 	committers of YAKINDU - initial API and implementation
+ * 
+ */
+package org.yakindu.sct.generator.c;
+
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.emf.common.util.URI;
+import org.yakindu.sct.generator.core.filesystem.ISCTFileSystemAccess;
+
+/**
+ * 
+ * @author thomas kutz - Initial API and contribution
+ *
+ */
+public class GenArtifactConfigurations implements IGenArtifactConfigurations {
+
+	private static final String MSG_FSA_NOT_CONFIGURED = "File system access needs to be configured before artifact locations can be computed.";
+	private static final String MSG_LOCATION_NOT_FOUND = "Artifact location for {0} not configured";
+	private ISCTFileSystemAccess sctFsa;
+
+	public static class GenArtifactConfiguration {
+		
+		private String outputName;
+		private String name;
+		private IContentTemplate contentTemplate;
+		
+		public GenArtifactConfiguration(String name, String outputConfigName, IContentTemplate contentTemplate) {
+			this.name = name;
+			this.outputName = outputConfigName;
+			this.contentTemplate = contentTemplate;
+		}
+
+		public String getName() {
+			return name;
+		}
+
+		public String getOutputName() {
+			return outputName;
+		}
+		
+		public IContentTemplate getContentTemplate() {
+			return contentTemplate;
+		}
+	}
+	
+	/**
+	 * Default instance which does not compute any relative paths and hence does not need to be configured in any way.
+	 * This is useful when an API needs to be served but relative path computation is not relevant.
+	 */
+	public static final IGenArtifactConfigurations DEFAULT = new GenArtifactConfigurations() {
+		/**
+		 * As default behavior, this will always return the target path/artifact instead of a relative path.
+		 */
+		public String relativeTo(String target, String fromArtifact) {
+			return target;
+		};
+	};
+	
+	@Override
+	public void setFileSystemAccess(ISCTFileSystemAccess sctFsa) {
+		this.sctFsa = sctFsa;
+	}
+	
+	protected List<GenArtifactConfiguration> generationArtifacts = new ArrayList<GenArtifactConfiguration>();
+	
+	@Override
+	public List<GenArtifactConfiguration> getConfigurations() {
+		return generationArtifacts;
+	}
+	
+	@Override
+	public void configure(String artifactName, String outputConfigName, IContentTemplate contentTemplate) {
+		generationArtifacts.add(new GenArtifactConfiguration(artifactName, outputConfigName, contentTemplate));
+	}
+
+	protected URI getOutputFolder(String artifactName) {
+		checkFSA();
+		for (GenArtifactConfiguration artifact : generationArtifacts) {
+			if (artifact.getName().equals(artifactName)) {
+				return sctFsa.getURI("", artifact.getOutputName());
+			}
+		}
+		return null;
+	}
+	
+	protected URI getURI(String artifactName) {
+		checkFSA();
+		for (GenArtifactConfiguration artifact : generationArtifacts) {
+			if (artifact.getName().equals(artifactName)) {
+				return sctFsa.getURI(artifact.getName(), artifact.getOutputName());
+			}
+		}
+		return null;
+	}
+
+	private void checkFSA() {
+		if (sctFsa == null)
+			throw new IllegalStateException(MSG_FSA_NOT_CONFIGURED);
+	}
+	
+	/**
+	 * @param target either target artifact name or absolute target path which will be transformed to a relative path based on <code>fromArtifact</code> location
+	 * @param fromArtifact artifact name whose location is used as base for relative path computation
+	 * @return the relative path from <code>fromArtifact</code> to <code>toTarget</code>
+	 */
+	@Override
+	public String relativeTo(String target, String fromArtifact) {
+		URI baseUri = getOutputFolder(fromArtifact);
+		if (baseUri == null) {
+			throw new IllegalArgumentException(MessageFormat.format(MSG_LOCATION_NOT_FOUND, fromArtifact));
+		}
+		
+		Path targetPath = new Path(target);
+		if (targetPath.isAbsolute()) {
+			return relativePath(target, baseUri.toFileString());
+		}
+		
+		URI absUri = getURI(target);
+		if (absUri != null) {
+			return relativePath(absUri.toFileString(), baseUri.toFileString());
+		}
+		throw new IllegalArgumentException(MessageFormat.format(MSG_LOCATION_NOT_FOUND, target));
+	}
+	
+	protected String relativePath(String to, String from) {
+		IPath basePath = new Path(from);
+		IPath toPath = new Path(to);
+		return toPath.makeRelativeTo(basePath).toOSString();
+	}
+
+}

+ 9 - 0
plugins/org.yakindu.sct.generator.c/src/org/yakindu/sct/generator/c/IContentTemplate.java

@@ -0,0 +1,9 @@
+package org.yakindu.sct.generator.c;
+
+import org.yakindu.sct.model.sexec.ExecutionFlow;
+import org.yakindu.sct.model.sgen.GeneratorEntry;
+
+public interface IContentTemplate {
+
+	String content(ExecutionFlow flow, GeneratorEntry entry, IGenArtifactConfigurations locations);
+}

+ 57 - 0
plugins/org.yakindu.sct.generator.c/src/org/yakindu/sct/generator/c/IGenArtifactConfigurations.java

@@ -0,0 +1,57 @@
+/**
+ * Copyright (c) 2016 committers of YAKINDU and others.
+ * 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:
+ * 	committers of YAKINDU - initial API and implementation
+ * 
+ */
+package org.yakindu.sct.generator.c;
+
+import java.util.List;
+
+import org.yakindu.sct.generator.c.GenArtifactConfigurations.GenArtifactConfiguration;
+import org.yakindu.sct.generator.core.filesystem.ISCTFileSystemAccess;
+
+/**
+ * Holds the configuration of generation artifacts. A configuration comprises
+ * the artifact's name, its output configuration name and a template defining
+ * the artifact's contents.
+ * 
+ * @author thomas kutz - Initial API and contribution
+ *
+ */
+public interface IGenArtifactConfigurations {
+
+	/**
+	 * Used as key in Guice to mark a default configuration instance
+	 */
+	String DEFAULT = "DefaultGenArtifactConfigurations";
+
+	/**
+	 * A file system access is needed to define the target location of a
+	 * generation artifact. Without this, relative paths via
+	 * {@link getRelativePath(String, String)} will not work.
+	 */
+	void setFileSystemAccess(ISCTFileSystemAccess sctFsa);
+
+	/**
+	 * Adds a configuration for a generation artifact.
+	 */
+	void configure(String artifactName, String outputConfigName, IContentTemplate contentTemplate);
+
+	/**
+	 * @return all stored configurations
+	 */
+	List<GenArtifactConfiguration> getConfigurations();
+
+	/**
+	 * Computes the relative path from a base artifact to a target which can be
+	 * an artifact name or an absolute path. For the former case, the artifact
+	 * configuration needs to be stored beforehand.
+	 */
+	String relativeTo(String target, String fromArtifact);
+
+}

+ 19 - 13
plugins/org.yakindu.sct.generator.c/src/org/yakindu/sct/generator/c/StatemachineHeader.xtend

@@ -11,7 +11,7 @@
 package org.yakindu.sct.generator.c
 
 import com.google.inject.Inject
-import org.eclipse.xtext.generator.IFileSystemAccess
+import com.google.inject.name.Named
 import org.yakindu.base.types.Declaration
 import org.yakindu.base.types.Direction
 import org.yakindu.sct.generator.core.types.ICodegenTypeSystemAccess
@@ -20,7 +20,6 @@ import org.yakindu.sct.model.sexec.TimeEvent
 import org.yakindu.sct.model.sexec.naming.INamingService
 import org.yakindu.sct.model.sgen.GeneratorEntry
 import org.yakindu.sct.model.sgraph.Scope
-import org.yakindu.sct.model.sgraph.Statechart
 import org.yakindu.sct.model.stext.stext.EventDefinition
 import org.yakindu.sct.model.stext.stext.InterfaceScope
 import org.yakindu.sct.model.stext.stext.InternalScope
@@ -29,27 +28,26 @@ import org.yakindu.sct.model.stext.stext.VariableDefinition
 
 import static org.eclipse.xtext.util.Strings.*
 
-class StatemachineHeader {
+class StatemachineHeader implements IContentTemplate {
 
 	@Inject extension Naming cNaming
 	@Inject extension Navigation
 	@Inject extension ICodegenTypeSystemAccess
 	@Inject extension GenmodelEntries
 	@Inject extension INamingService
-
 	
-	def generateStatemachineHeader(ExecutionFlow flow, Statechart sc, IFileSystemAccess fsa, GeneratorEntry entry) {
-		flow.initializeNamingService
-		fsa.generateFile(flow.module.h, flow.generateStatemachineHeaderContents(entry))
-	}
-
-	def generateStatemachineHeaderContents(ExecutionFlow it, GeneratorEntry entry) '''
+	@Inject @Named(IGenArtifactConfigurations.DEFAULT)
+	IGenArtifactConfigurations defaultConfigs
+	
+	override content(ExecutionFlow it, GeneratorEntry entry , IGenArtifactConfigurations artifactConfigs) {
+		initializeNamingService
+	'''
 		«entry.licenseText»
 		
 		#ifndef «module.define»_H_
 		#define «module.define»_H_
 		
-		«includes»
+		«includes(artifactConfigs)»
 				
 		#ifdef __cplusplus
 		extern "C" { 
@@ -109,9 +107,17 @@ class StatemachineHeader {
 		
 		#endif /* «module.define»_H_ */
 	'''
+	}
+	/**
+	 * @Deprecated use {@link #includes(ExecutionFlow, ArtifactLocationProvider)} instead
+	 */
+	@Deprecated
+	def includes(ExecutionFlow it) {
+		includes(it, defaultConfigs)
+	}
 
-	def includes(ExecutionFlow it) '''
-		#include "«typesModule.h»"
+	def includes(ExecutionFlow it, extension IGenArtifactConfigurations artifactConfigs) '''
+		#include "«(typesModule.h).relativeTo(module.h)»"
 	'''
 	
 	def statesEnumDecl(ExecutionFlow it) '''

+ 80 - 86
plugins/org.yakindu.sct.generator.c/src/org/yakindu/sct/generator/c/StatemachineRequiredHeader.xtend

@@ -11,17 +11,15 @@
 package org.yakindu.sct.generator.c
 
 import com.google.inject.Inject
-import org.eclipse.xtext.generator.IFileSystemAccess
 import org.yakindu.base.types.Declaration
 import org.yakindu.sct.generator.core.types.ICodegenTypeSystemAccess
 import org.yakindu.sct.model.sexec.ExecutionFlow
 import org.yakindu.sct.model.sexec.naming.INamingService
 import org.yakindu.sct.model.sgen.GeneratorEntry
-import org.yakindu.sct.model.sgraph.Statechart
 import org.yakindu.sct.model.stext.stext.OperationDefinition
 import org.yakindu.sct.model.stext.stext.StatechartScope
 
-class StatemachineRequiredHeader {
+class StatemachineRequiredHeader implements IContentTemplate {
 
 	@Inject extension Naming cNaming
 	@Inject extension Navigation
@@ -29,94 +27,90 @@ class StatemachineRequiredHeader {
 	@Inject extension GenmodelEntries
 	@Inject extension INamingService
 	
-	def generateStatemachineRequiredHeader(ExecutionFlow flow, Statechart sc, IFileSystemAccess fsa, GeneratorEntry entry) {
-		 fsa.generateFile(flow.module.client.h, flow.statemachineRequiredHeaderContents(entry) )
-	}
-	
-	def statemachineRequiredHeaderContents(ExecutionFlow it, GeneratorEntry entry) '''
-			«entry.licenseText»
-			
-			#ifndef «module.client.define»_H_
-			#define «module.client.define»_H_
+	override content(ExecutionFlow it, GeneratorEntry entry, extension IGenArtifactConfigurations artifactConfigs) '''
+		«entry.licenseText»
+		
+		#ifndef «module.client.define»_H_
+		#define «module.client.define»_H_
 
-			#include "«typesModule.h»"
-			«IF timed || operations.size > 0»#include "«module.h»"«ENDIF»
+		#include "«(typesModule.h).relativeTo(module.client.h)»"
+		«IF timed || operations.size > 0»#include "«(module.h).relativeTo(module.client.h)»"«ENDIF»
 
-			#ifdef __cplusplus
-			extern "C"
-			{
-			#endif 
-			
-			/*! \file This header defines prototypes for all functions that are required by the state machine implementation.
+		#ifdef __cplusplus
+		extern "C"
+		{
+		#endif 
+		
+		/*! \file This header defines prototypes for all functions that are required by the state machine implementation.
+		
+		«IF timed»
+			This is a state machine uses time events which require access to a timing service. Thus the function prototypes:
+				- «type.toFirstLower»_setTimer and
+				- «type.toFirstLower»_unsetTimer
+			are defined.
 			
-			«IF timed»
-				This is a state machine uses time events which require access to a timing service. Thus the function prototypes:
-					- «type.toFirstLower»_setTimer and
-					- «type.toFirstLower»_unsetTimer
-				are defined.
-				
-			«ENDIF»
-			«IF operations.size > 0»
-				This state machine makes use of operations declared in the state machines interface or internal scopes. Thus the function prototypes:
-					«FOR o : operations»
-					- «o.asFunction»
-					«ENDFOR»
-				are defined.
-				
-			«ENDIF»
-			These functions will be called during a 'run to completion step' (runCycle) of the statechart. 
-			There are some constraints that have to be considered for the implementation of these functions:
-				- never call the statechart API functions from within these functions.
-				- make sure that the execution time is as short as possible.
-			 
-			*/
-			«FOR s : it.scopes »
-			«s.scopeFunctionPrototypes»
+		«ENDIF»
+		«IF operations.size > 0»
+			This state machine makes use of operations declared in the state machines interface or internal scopes. Thus the function prototypes:
+				«FOR o : operations»
+				- «o.asFunction»
+				«ENDFOR»
+			are defined.
 			
-			«ENDFOR»
-			«IF timed»
-			/*!
-			 * This is a timed state machine that requires timer services
-			 */ 
-			
-			/*! This function has to set up timers for the time events that are required by the state machine. */
-			/*! 
-				This function will be called for each time event that is relevant for a state when a state will be entered.
-				\param evid An unique identifier of the event.
-				\time_ms The time in milli seconds
-				\periodic Indicates the the time event must be raised periodically until the timer is unset 
-			*/
-			extern void «type.toFirstLower»_setTimer(«scHandleDecl», const sc_eventid evid, const sc_integer time_ms, const sc_boolean periodic);
+		«ENDIF»
+		These functions will be called during a 'run to completion step' (runCycle) of the statechart. 
+		There are some constraints that have to be considered for the implementation of these functions:
+			- never call the statechart API functions from within these functions.
+			- make sure that the execution time is as short as possible.
+		 
+		*/
+		«FOR s : it.scopes »
+		«s.scopeFunctionPrototypes»
+		
+		«ENDFOR»
+		«IF timed»
+		/*!
+		 * This is a timed state machine that requires timer services
+		 */ 
+		
+		/*! This function has to set up timers for the time events that are required by the state machine. */
+		/*! 
+			This function will be called for each time event that is relevant for a state when a state will be entered.
+			\param evid An unique identifier of the event.
+			\time_ms The time in milli seconds
+			\periodic Indicates the the time event must be raised periodically until the timer is unset 
+		*/
+		extern void «type.toFirstLower»_setTimer(«scHandleDecl», const sc_eventid evid, const sc_integer time_ms, const sc_boolean periodic);
 
-			/*! This function has to unset timers for the time events that are required by the state machine. */
-			/*! 
-				This function will be called for each time event taht is relevant for a state when a state will be left.
-				\param evid An unique identifier of the event.
-			*/
-			extern void «type.toFirstLower»_unsetTimer(«scHandleDecl», const sc_eventid evid);
-			«ENDIF»
-			
-			
-			«IF entry.tracingEnterState || entry.tracingExitState»
-			/*!
-			 * Tracing callback functions
-			 */
-			«IF entry.tracingEnterState»
-				/*! This function is called when a state is entered. */
-				extern void «type.toFirstLower»_stateEntered(«scHandleDecl», const «statesEnumType» state);
-			«ENDIF»
-			
-			«IF entry.tracingExitState»
-				/*! This function is called when a state is exited. */
-				extern void «type.toFirstLower»_stateExited(«scHandleDecl», const «statesEnumType» state);
-			«ENDIF»
-			«ENDIF»
-			
-			#ifdef __cplusplus
-			}
-			#endif 
-			
-			#endif /* «module.client.define»_H_ */
+		/*! This function has to unset timers for the time events that are required by the state machine. */
+		/*! 
+			This function will be called for each time event taht is relevant for a state when a state will be left.
+			\param evid An unique identifier of the event.
+		*/
+		extern void «type.toFirstLower»_unsetTimer(«scHandleDecl», const sc_eventid evid);
+		«ENDIF»
+		
+		
+		«IF entry.tracingEnterState || entry.tracingExitState»
+		/*!
+		 * Tracing callback functions
+		 */
+		«IF entry.tracingEnterState»
+			/*! This function is called when a state is entered. */
+			extern void «type.toFirstLower»_stateEntered(«scHandleDecl», const «statesEnumType» state);
+		«ENDIF»
+		
+		«IF entry.tracingExitState»
+			/*! This function is called when a state is exited. */
+			extern void «type.toFirstLower»_stateExited(«scHandleDecl», const «statesEnumType» state);
+		«ENDIF»
+		«ENDIF»
+		
+		#ifdef __cplusplus
+		}
+		#endif 
+		
+		#endif /* «module.client.define»_H_ */
 	'''
 	
 	

+ 10 - 16
plugins/org.yakindu.sct.generator.c/src/org/yakindu/sct/generator/c/StatemachineSource.xtend

@@ -12,7 +12,7 @@ package org.yakindu.sct.generator.c
 
 import com.google.inject.Inject
 import java.util.List
-import org.eclipse.xtext.generator.IFileSystemAccess
+import org.eclipse.xtext.util.Strings
 import org.yakindu.sct.generator.core.types.ICodegenTypeSystemAccess
 import org.yakindu.sct.model.sexec.Check
 import org.yakindu.sct.model.sexec.ExecutionFlow
@@ -20,12 +20,10 @@ import org.yakindu.sct.model.sexec.Step
 import org.yakindu.sct.model.sexec.extensions.StateVectorExtensions
 import org.yakindu.sct.model.sexec.naming.INamingService
 import org.yakindu.sct.model.sgen.GeneratorEntry
-import org.yakindu.sct.model.sgraph.Statechart
-import org.yakindu.sct.model.stext.stext.VariableDefinition
 import org.yakindu.sct.model.stext.stext.StatechartScope
-import org.eclipse.xtext.util.Strings
+import org.yakindu.sct.model.stext.stext.VariableDefinition
 
-class StatemachineSource {
+class StatemachineSource implements IContentTemplate {
 	
 	@Inject extension Naming
 	@Inject extension GenmodelEntries
@@ -36,22 +34,17 @@ class StatemachineSource {
 	@Inject extension ConstantInitializationResolver
 	@Inject protected extension StateVectorExtensions
 	
-	def generateStatemachineSource(ExecutionFlow flow, Statechart sc, IFileSystemAccess fsa, GeneratorEntry entry) {
-		flow.initializeNamingService
-		var content = flow.generateStatemachineSourceContents(entry)
-		var target = flow.module.c
-		fsa.generateFile(target , content)
-	}
-	
-	def generateStatemachineSourceContents(ExecutionFlow it, GeneratorEntry entry) '''
+	override content(ExecutionFlow it, GeneratorEntry entry, extension IGenArtifactConfigurations artifactConfigs) { 
+		initializeNamingService
+	'''
 		«entry.licenseText»
 		
 		#include <stdlib.h>
 		#include <string.h>
-		#include "«typesModule.h»"
-		#include "«module.h»"
+		#include "«(typesModule.h).relativeTo(module.c)»"
+		#include "«(module.h).relativeTo(module.c)»"
 		«IF timed || !it.operations.empty»
-			#include "«module.client.h»"
+			#include "«(module.client.h).relativeTo(module.c)»"
 		«ENDIF»
 		/*! \file Implementation of the state machine '«name»'
 		*/
@@ -84,6 +77,7 @@ class StatemachineSource {
 		
 		«functionImplementations»
 	'''
+	}
 	
 	def initFunction(ExecutionFlow it) '''
 		void «functionPrefix»init(«scHandleDecl»)

+ 2 - 18
plugins/org.yakindu.sct.generator.c/src/org/yakindu/sct/generator/c/Types.xtend

@@ -11,31 +11,15 @@
 package org.yakindu.sct.generator.c
 
 import com.google.inject.Inject
-import org.eclipse.xtext.generator.IFileSystemAccess
-import org.yakindu.sct.generator.core.impl.IExecutionFlowGenerator
-import org.yakindu.sct.model.sgraph.Statechart
 import org.yakindu.sct.model.sexec.ExecutionFlow
 import org.yakindu.sct.model.sgen.GeneratorEntry
-import org.yakindu.sct.generator.core.library.IOutletFeatureHelper
 
-class Types {
+class Types implements IContentTemplate {
 
 	@Inject extension Naming
 	@Inject extension GenmodelEntries
-	@Inject IOutletFeatureHelper outletFeatureHelper
 
-	def generateTypesH(ExecutionFlow flow, Statechart sc, IFileSystemAccess fsa, GeneratorEntry entry) {
-		if (outletFeatureHelper.getLibraryTargetFolderValue(entry) != null) {
-			// sc_types.h is static, so we use the library target folder in case its configured
-			fsa.generateFile(flow.typesModule.h, IExecutionFlowGenerator.LIBRARY_TARGET_FOLDER_OUTPUT,
-				flow.typesHContent(entry))
-		} else {
-			// use default target folder path in case no library target folder is specified (the file will be overwritten there)
-				fsa.generateFile(flow.typesModule.h, flow.typesHContent(entry))
-		}
-	}
-
-	def typesHContent(ExecutionFlow it, GeneratorEntry entry) '''
+	override content(ExecutionFlow it, GeneratorEntry entry, IGenArtifactConfigurations locations) '''
 		«entry.licenseText»
 		
 		#ifndef «typesModule.define»_H_

+ 3 - 0
plugins/org.yakindu.sct.generator.core/src/org/yakindu/sct/generator/core/filesystem/EFSResourceFileSystemAccess.java

@@ -202,6 +202,9 @@ public class EFSResourceFileSystemAccess extends AbstractFileSystemAccess2 imple
 	public URI getURI(String path, String outputConfiguration) {
 		OutputConfiguration outputConfig = getOutputConfig(outputConfiguration);
 		String outputDir = outputConfig.getOutputDirectory();
+		if (efsHelper.isRootPath(outputDir) && efsHelper.isRootPath(path)) {
+			return URI.createFileURI(getProject().getLocationURI().getPath());
+		}
 		IFile file = getProject().getFile(outputDir + File.separator + path);
 		if (file != null) {
 			return URI.createFileURI(file.getLocationURI().getPath());

+ 2 - 0
plugins/org.yakindu.sct.generator.core/src/org/yakindu/sct/generator/core/filesystem/ISCTFileSystemAccess.java

@@ -38,6 +38,8 @@ public interface ISCTFileSystemAccess {
 	 * @return
 	 */
 	URI getURI(String path);
+	
+	URI getURI(String path, String outputName);
 
 	/**
 	 * Add an output path for an output name.

+ 5 - 1
plugins/org.yakindu.sct.generator.core/src/org/yakindu/sct/generator/core/util/EFSHelper.java

@@ -88,11 +88,15 @@ public class EFSHelper {
 	 */
 	public IContainer getContainer(OutputConfiguration outputConfig,IProject project) {
 		String path = outputConfig.getOutputDirectory();
-		if (".".equals(path) ||"/".equals(path) || "./".equals(path) || "".equals(path) || project == null) {
+		if (isRootPath(path) || project == null) {
 			return project;
 		}
 		return project.getFolder(new Path(path));
 	}
+	
+	public boolean isRootPath(String path) {
+		return (".".equals(path) ||"/".equals(path) || "./".equals(path) || "".equals(path));
+	}
 
 	public void createContainer(IContainer container) {
 		try {

+ 6 - 0
plugins/org.yakindu.sct.generator.cpp/src/org/yakindu/sct/generator/cpp/CppCodeGenerator.java

@@ -10,6 +10,8 @@
  */
 package org.yakindu.sct.generator.cpp;
 
+import org.yakindu.sct.generator.c.GenArtifactConfigurations;
+import org.yakindu.sct.generator.c.IGenArtifactConfigurations;
 import org.yakindu.sct.generator.c.types.CTypeSystemAccess;
 import org.yakindu.sct.generator.core.impl.GenericJavaBasedGenerator;
 import org.yakindu.sct.generator.core.types.ICodegenTypeSystemAccess;
@@ -21,6 +23,7 @@ import org.yakindu.sct.model.sgraph.Statechart;
 import com.google.inject.Binder;
 import com.google.inject.Inject;
 import com.google.inject.Module;
+import com.google.inject.name.Names;
 import com.google.inject.util.Modules;
 
 /**
@@ -50,6 +53,9 @@ public class CppCodeGenerator extends GenericJavaBasedGenerator {
 				binder.bind(ICodegenTypeSystemAccess.class).to(CTypeSystemAccess.class);
 				binder.bind(INamingService.class).to(CppNamingService.class);
 				binder.bind(GeneratorEntry.class).toInstance(entry);
+				binder.bind(IGenArtifactConfigurations.class)
+						.annotatedWith(Names.named(IGenArtifactConfigurations.DEFAULT))
+						.toInstance(GenArtifactConfigurations.DEFAULT);
 			}
 		});
 	}

+ 2 - 2
plugins/org.yakindu.sct.generator.cpp/src/org/yakindu/sct/generator/cpp/StatemachineHeader.xtend

@@ -40,12 +40,12 @@ class StatemachineHeader extends org.yakindu.sct.generator.c.StatemachineHeader
 
 	protected GeneratorEntry entry
 
-	override generateStatemachineHeader(ExecutionFlow flow, Statechart sc, IFileSystemAccess fsa, GeneratorEntry entry) {
+	def generateStatemachineHeader(ExecutionFlow flow, Statechart sc, IFileSystemAccess fsa, GeneratorEntry entry) {
 		this.entry = entry
 		fsa.generateFile(flow.module().h, flow.generateStatemachineHeaderContents(entry))
 	}
 
-	override generateStatemachineHeaderContents(ExecutionFlow it, GeneratorEntry entry) '''
+	def generateStatemachineHeaderContents(ExecutionFlow it, GeneratorEntry entry) '''
 		«entry.licenseText»
 		
 		#ifndef «module().define»_H_