Skip to main content
aboutsummaryrefslogblamecommitdiffstats
blob: b1aa47ff53256224021170ed7f9513e4ef6b807f (plain) (tree)
1
2
3
4
5
6
7
8
9


                                                                                
                                                                       
                                                           


                                         
  


                                                                               
  











                                                                                 

                                                      
                                                    
                                                                   
                                                          


                                             

                                                   
                                                
                                           
                                               


                                                 
                                                    

                                                              

                                                                  



                                                 

                                                      
                                                          
 

                                                             
                                                                                                                            



                  





                                                         
 







                                                                       
 

                                                                                          


                                                                                               



                                                                              
 





                                                                      
                                                









                                                     




                                                    






                                                        
 










































                                                                                                  
 


                                            
 


                                         
 


                                                                                         
 









                                                              
                                                
         
 


                                                 
 




                                                                                              


                                                       









                                                                                     
                                                                          



                                                                                                                                     
                                                                                   
                                
                                     

                 
 




                                                                                                                               
                                                             
         
 
                                                                                 


                                                           
                                                  
                                            

                                                                     




                                                                          
                                        
                                                   
                                      
                                                                     
                                                                        

                                                                                                                                                     
                         
                                  








                                                                                     
 





                                                                 
 



















                                                                         
 

                                                            
                                




                                                        
                                        


                                                    
                                                                               
         
 
                                                         

                                                                        
                                                       
 

                                           
                                                       
 
                                                                                        


                                                                                   

                                                                                

                                                             
 

                                                                                              
                                                       



                                        


                                                                                  



                                               
 
                                                     
                                                                                                                                             









                                                               
 






                                                                                                                                           
 

                                                                      
 


                                                                                                           
 



                                                                                                          
                                                      
                                                   



                                                               
 


                                                                  
 
                                              



                                                                                  
 
                                                    
                                                   



                                                             
 



                                                   
 
 
/*******************************************************************************
 * 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 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * CONTRIBUTORS:
 * 		Thomas Schuetz and Henrik Rentz-Reichert (initial contribution)
 * 		Thomas Schuetz (changed for C code generator)
 *
 *******************************************************************************/

/*
	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 java.util.List
import org.eclipse.emf.ecore.EObject
import org.eclipse.etrice.core.common.base.LiteralType
import org.eclipse.etrice.core.etphys.eTPhys.NodeRef
import org.eclipse.etrice.core.genmodel.etricegen.SubSystemInstance
import org.eclipse.etrice.core.genmodel.fsm.IDiagnostician
import org.eclipse.etrice.core.room.Attribute
import org.eclipse.etrice.core.room.DataClass
import org.eclipse.etrice.core.room.DataType
import org.eclipse.etrice.core.room.EnumLiteral
import org.eclipse.etrice.core.room.EnumerationType
import org.eclipse.etrice.core.room.ExternalType
import org.eclipse.etrice.core.room.Message
import org.eclipse.etrice.core.room.MessageData
import org.eclipse.etrice.core.room.PrimitiveType
import org.eclipse.etrice.core.room.RoomClass
import org.eclipse.etrice.core.room.RoomModel
import org.eclipse.etrice.core.room.util.RoomHelpers
import org.eclipse.etrice.generator.generic.ILanguageExtension
import org.eclipse.xtext.util.Pair
import org.eclipse.etrice.generator.c.setup.GeneratorOptionsHelper
import org.eclipse.etrice.generator.c.Main

@Singleton
class CExtensions implements ILanguageExtension {

	@Inject protected IDiagnostician diagnostician
	@Inject protected extension RoomHelpers
	@Inject protected extension GeneratorOptionsHelper

	override String getTypedDataDefinition(EObject msg) {
	    if (msg instanceof Message) {
    		generateArglistAndTypedData((msg as Message).data).get(TypedDataKind.DECLARATION_AND_INITIALIZATION.ordinal)
	    }
	    else {
	        ""
	    }
	}

	// in C no access levels can be defined
	override String accessLevelPrivate(){"static "}
	override String accessLevelProtected(){"static "}
	override String accessLevelPublic(){""}

	override String memberAccess(){"self->"}
	override String selfPointer(String classname, boolean hasArgs){
		classname+
		if (hasArgs)
			"* self, "
		else
			"* self"
	}

	override String selfPointer(boolean hasArgs) { if (hasArgs) "self, " else "self" }

	override String scopeSeparator() {""}
	
	override String operationScope(String classname, boolean isDeclaration) {classname+"_"}

	override String memberInDeclaration(String namespace, String member) {
		return namespace+"_"+member
	}

	override String memberInUse(String namespace, String member) {
		return namespace+"_"+member
	}


	//****  C-Specific
	/* TODO: move specific code elsewhere */
	// used
	def String getCHeaderFileName(RoomClass rc) {
		return rc.name+".h";
	}

	// used
	def String getCSourceFileName(RoomClass rc) {
		return rc.name+".c";
	}

	// used
	def String getCUtilsFileName(RoomClass rc) {
		return rc.name+"_Utils.h";
	}

	def String getInstSourceFileName(RoomClass rc) {
		return rc.name+"_Inst.h";
	}

	def String getDispSourceFileName(RoomClass rc) {
		return rc.name+"_Disp.h";
	}

	// used
	def String getCHeaderFileName(NodeRef nr, SubSystemInstance ssi) {
		return nr.name+"_"+ssi.name+".h";
	}

	def String getCSourceFileName(NodeRef nr, SubSystemInstance ssi) {
		return nr.name+"_"+ssi.name+".c";
	}

	def String getInstSourceFileName(NodeRef nr, SubSystemInstance ssi) {
		return nr.name+"_"+ssi.name+"_Inst.h";
	}

	def String getDispSourceFileName(NodeRef nr, SubSystemInstance ssi) {
		return nr.name+"_"+ssi.name+"_Disp.h";
	}

	def getIncludeGuardString(String filename){
		'''_«filename.toUpperCase»_H_'''
	}

	def generateIncludeGuardBegin(RoomClass rc) {
		val filename = (rc.eContainer as RoomModel).name.replaceAll("\\.","_")+"_"+rc.name
		filename.generateIncludeGuardBegin
	}

	def generateIncludeGuardEnd(RoomClass rc) {
		val filename = (rc.eContainer as RoomModel).name.replaceAll("\\.","_")+"_"+rc.name
		filename.generateIncludeGuardEnd
	}

	def generateIncludeGuardBegin(String filename) {
		'''
		#ifndef «filename.getIncludeGuardString»
		#define «filename.getIncludeGuardString»
		'''
	}

	def generateIncludeGuardEnd(String filename) {
		'''
		#endif /* «filename.getIncludeGuardString» */
		'''
	}

	override boolean usesInheritance() {
		return false
	}

	override boolean usesPointers() {
		return true
	}

	override String genEnumeration(String name, List<Pair<String, String>> entries) {
		if (entries.empty)
			return "/* empty enum not generated */"

		'''
		enum «name» {
			«FOR entry: entries SEPARATOR ","»
				«entry.first» = «entry.second»
			«ENDFOR»
		};
		'''.toString
	}

	override String booleanConstant(boolean b) {
		if (b) "ET_TRUE" else "ET_FALSE"
	}

	override String pointerLiteral() { "*" }
	override String nullPointer() { "NULL" }
	override String voidPointer() { "void*" }

	override String arrayType(String type, int size, boolean isRef)'''
			«type»«IF isRef»*«ENDIF»
		'''

	override String arrayDeclaration(String type, int size, boolean isRef, String name)'''
		«type»«IF isRef»*«ENDIF» «name»[«size»]
	'''

	override String superCall(String baseClassName, String method, String args) {
		""
	}
	override String toValueLiteral(PrimitiveType type, String value){
		switch(type.targetName){
			// TODO JH: char* with length 1
			case type.targetName.equals("char") && value.length == 1:
				"'"+value+"'"
			case type.type == LiteralType::CHAR:
				"\""+value+"\""
			case value.contains(',') || value.contains('{'): {
					var singleValues = value.replace('{', '').replace('}', '').trim.split(',')
					'''{ «FOR v: singleValues SEPARATOR ', '»«toValueLiteral(type, v.trim)»«ENDFOR» }'''.toString
				}
			case "boolean":
				if (value.equals("true")) "ET_TRUE" else "ET_FALSE"
			default:
				value
		}
	}

	override toEnumLiteral(EnumerationType type, String value) {
		if(value.contains(',') || value.contains('{')){
			var singleValues = value.replace('{', '').replace('}', '').trim.split(',')
			'''{ «FOR v: singleValues SEPARATOR ', '»«convertStringEnumLiteral(type, v.trim)»«ENDFOR» }'''.toString
		} else
			convertStringEnumLiteral(type, value)
	}

	def private convertStringEnumLiteral(EnumerationType type, String value){
		var v = value
		if (v.startsWith(type.name))
			v = v.substring(type.name.length+1)
		for(EnumLiteral l : type.literals)
			if(l.name.equals(v))
				return type.getName()+"_"+l.getName()
	}

	override String defaultValue(DataType dt) {
		switch dt{
			PrimitiveType:
				toValueLiteral(dt, dt.defaultValueLiteral)
			EnumerationType:
				getDefaultValue(dt)
			ExternalType:{
				if (dt.defaultValueLiteral !== null )
					return dt.getDefaultValueLiteral
				diagnostician.error("external type "+dt.name + "has no default initialization", dt.eContainer, dt.eContainingFeature)
				""
			}
			DataClass:
			'''
				{
					«FOR att : dt.allAttributes SEPARATOR ","»
						«att.initializationWithDefaultValues»
					«ENDFOR»
				}
			'''
		}
	}

	def String getDefaultValue(EnumerationType type) {
		if (type.getLiterals().isEmpty())
			""
		else
			getCastedValue(type.getLiterals().get(0))
	}

	override initializationWithDefaultValues(DataType dt, int size) {
		val dv = dt.defaultValue
		dv.initializer(size)
	}

	def private initializer(String dv, int size) {
		if (size>1) {
			var res = "{"
			var i = 0
			while (i<size) {
				res = res + dv
				i = i+1
				if (i<size)
					res = res + ","
			}
			res+"}"
		}
		else
			dv
	}

	def initializationWithDefaultValues(Attribute att) {
		val dv = att.defaultValueLiteral
		if (dv!==null) {
			if (dv.startsWith("{"))
				dv
			else
				dv.initializer(att.size)
		}
		else if (att.type.ref) {
			"NULL".initializer(att.size)
		}
		else
			att.type.type.initializationWithDefaultValues(att.size)
	}

	override generateArglistAndTypedData(EObject d) {
		// TODO 529445: d will be a RefableType, not MessageData
		if (d===null || !(d instanceof MessageData))
			return newArrayList("", "", "")

		val data = d as MessageData
		if (data===null)
			return newArrayList("", "", "")

		var typeName = if (data.getRefType().getType() instanceof PrimitiveType)
			(data.getRefType().getType() as PrimitiveType).targetName
		else if (data.getRefType().getType() instanceof EnumerationType)
			(data.getRefType().getType() as EnumerationType).targetType
		else if (data.getRefType().getType() instanceof ExternalType)
			(data.getRefType().getType() as ExternalType).targetName
		else
			data.getRefType().getType().getName()

		var castTypeName = if (data.getRefType().getType() instanceof PrimitiveType) {
			val ct = (data.getRefType().getType() as PrimitiveType).getCastName()
			if (ct!==null && !ct.isEmpty())
				ct
			else
				typeName
		}
		else if (data.getRefType().getType() instanceof EnumerationType) {
			(data.getRefType().getType() as EnumerationType).castType
		}
		else
			typeName
		castTypeName = castTypeName+"*"
		var deRef = "*"

		val isRef = data.getRefType().isRef()
		val isPrim = (data.getRefType().getType() instanceof PrimitiveType || data.getRefType().getType() instanceof EnumerationType)
		if (isRef) {
				typeName = typeName+"*"
				castTypeName = castTypeName+"*"
		}
		else {
			if (!isPrim) {
				typeName = typeName+"*"
				deRef = ""
			}
		}

		val dataName = if (Main.settings.isOldStyleTransitionData && data.deprecatedName!==null && !data.deprecatedName.trim.empty)
				data.deprecatedName
			else
				GENERIC_DATA_NAME
		val dataArg = ", "+dataName
		val typedData = typeName+" "+dataName + " = "+deRef+"(("+castTypeName+") generic_data__et);\n"
		val typedArgList = ", "+typeName+" "+dataName

		return newArrayList(dataArg, typedData, typedArgList);
	}

	def getIncludePath(RoomClass rc) {
		"\""+(rc.eContainer as RoomModel).name.replaceAll("\\.","/")+"/"+rc.getCHeaderFileName+"\""
	}

	def getUtilsIncludePath(RoomClass rc) {
		"\""+(rc.eContainer as RoomModel).name.replaceAll("\\.","/")+"/"+rc.getCUtilsFileName+"\""
	}

	override getTargetType(EnumerationType type) {
		if (type.getPrimitiveType()!==null)
			type.getPrimitiveType().getTargetName()
		else
			type.getName()
	}

	override getCastedValue(EnumLiteral literal) {
		val type = literal.eContainer() as EnumerationType
		val cast = type.targetType

		if (type.primitiveType===null)
			Long.toString(literal.getLiteralValue())
		else
			"(("+cast+")"+Long.toString(literal.getLiteralValue())+")"
	}

	override getCastType(EnumerationType type) {
		if (type.getPrimitiveType()!==null)
			type.getPrimitiveType().getCastName()
		else
			type.getName()
	}

	override makeOverridable() {
		// not possible for C: empty string
		""
	}

}

Back to the top