tracesrv/tracecompiler/src/com.nokia.tracecompiler/src/com/nokia/tracecompiler/engine/header/TraceHeaderWriter.java
changeset 56 aa2539c91954
child 62 1c2bb2fc7c87
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tracesrv/tracecompiler/src/com.nokia.tracecompiler/src/com/nokia/tracecompiler/engine/header/TraceHeaderWriter.java	Fri Oct 08 14:56:39 2010 +0300
@@ -0,0 +1,1401 @@
+/*
+ * Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of "Eclipse Public License v1.0"
+ * which accompanies this distribution, and is available
+ * at the URL "http://www.eclipse.org/legal/epl-v10.html".
+ *
+ * Initial Contributors:
+ * Nokia Corporation - initial contribution.
+ *
+ * Contributors:
+ *
+ * Description:
+ *
+ * Writes the TraceHeader to a file
+ *
+ */
+package com.nokia.tracecompiler.engine.header;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.nokia.tracecompiler.TraceCompilerLogger;
+import com.nokia.tracecompiler.engine.LocationListBase;
+import com.nokia.tracecompiler.engine.LocationProperties;
+import com.nokia.tracecompiler.engine.TraceCompilerEngineGlobals;
+import com.nokia.tracecompiler.engine.TraceLocation;
+import com.nokia.tracecompiler.engine.TraceCompilerEngineErrorCodes.TraceCompilerErrorCode;
+import com.nokia.tracecompiler.engine.source.SourceFormatter;
+import com.nokia.tracecompiler.engine.source.TraceFormattingRule;
+import com.nokia.tracecompiler.engine.source.TraceParameterFormattingRule;
+import com.nokia.tracecompiler.file.FileCompareOutputStream;
+import com.nokia.tracecompiler.file.FileUtils;
+import com.nokia.tracecompiler.model.Trace;
+import com.nokia.tracecompiler.model.TraceCompilerException;
+import com.nokia.tracecompiler.model.TraceGroup;
+import com.nokia.tracecompiler.model.TraceModel;
+import com.nokia.tracecompiler.model.TraceParameter;
+import com.nokia.tracecompiler.plugin.TraceFormatConstants;
+import com.nokia.tracecompiler.plugin.TraceHeaderContribution;
+import com.nokia.tracecompiler.plugin.TraceAPIFormatter.TraceFormatType;
+import com.nokia.tracecompiler.plugin.TraceHeaderContribution.TraceHeaderContributionType;
+import com.nokia.tracecompiler.rules.FillerParameterRule;
+import com.nokia.tracecompiler.source.SourceConstants;
+import com.nokia.tracecompiler.source.SourceExcludedArea;
+import com.nokia.tracecompiler.source.SourceParser;
+import com.nokia.tracecompiler.source.SourceUtils;
+import com.nokia.tracecompiler.source.SymbianConstants;
+import com.nokia.tracecompiler.utils.TraceCompilerVersion;
+
+/**
+ * Writes the TraceHeader to a file
+ * 
+ */
+final class TraceHeaderWriter {
+
+	/**
+	 * return type text of a generated OstTraceGenx function.
+	 */
+	private static final String INLINE_TBOOL = "inline TBool";
+
+	/**
+	 * open bracket in a type cast
+	 */
+	private static final String BEGINCAST = "OBR"; //$NON-NLS-1$
+	
+	/**
+	 * closing bracket in a type cast
+	 */
+	private static final String ENDCAST = "CBR"; //$NON-NLS-1$
+
+	/**
+	 * REF replaces & in a function guard
+	 */
+	private static final String REF = "REF"; //$NON-NLS-1$
+
+	/**
+	 * & character
+	 */
+	private static final String AMPERSANT = "&"; //$NON-NLS-1$
+
+	/**
+	 * closing bracket
+	 */
+	private static final String CLOSING_BRACKET = ")"; //$NON-NLS-1$
+
+	/**
+	 * open bracket
+	 */
+	private static final String OPEN_BRACKET = "("; //$NON-NLS-1$
+
+	/**
+	 * TUint32 definition
+	 */
+	private static final String TUINT32_DEF = "TUint32 "; //$NON-NLS-1$
+
+	/**
+	 * TInt32 definition
+	 */
+	private static final String TINT32_DEF = "TInt32 "; //$NON-NLS-1$
+
+	/**
+	 * TUint definition
+	 */
+	private static final String TUINT_DEF = "TUint "; //$NON-NLS-1$
+
+	/**
+	 * TInt definition
+	 */
+	private static final String TINT_DEF = "TInt "; //$NON-NLS-1$
+
+	/**
+	 * Length variable defined flag
+	 */
+	private boolean lenghtVariableDefined = false;
+	
+	
+	/**
+	 * List of dynamic elements that can be used from the templates
+	 * 
+	 */
+	enum HeaderTemplateElementType {
+
+		/**
+		 * Licence text
+		 */
+		LICENCE_TEXT,
+		
+		/**
+		 * TraceCompiler version number
+		 */
+		TRACE_COMPILER_VERSION,
+
+		/**
+		 * Header guard based on file name
+		 */
+		HEADER_GUARD,
+
+		/**
+		 * Opening brace
+		 */
+		OPEN_BRACE,
+
+		/**
+		 * Closing brace
+		 */
+		CLOSE_BRACE,
+
+		/**
+		 * New line and indent based on open brace count
+		 */
+		NEW_LINE,
+
+		/**
+		 * Writes currentTraceFormatted
+		 */
+		FORMATTED_TRACE,
+
+		/**
+		 * Adds all closing braces except the one that closes the function
+		 */
+		CLOSE_EXTRA_BRACES,
+
+		/**
+		 * Type of current parameter
+		 */
+		PARAMETER_TYPE,
+
+		/**
+		 * Name of current parameter
+		 */
+		PARAMETER_NAME,
+
+		/**
+		 * Name of current trace
+		 */
+		TRACE_NAME,
+
+		/**
+		 * ID of current trace
+		 */
+		TRACE_ID_HEX,
+
+		/**
+		 * Calls a function to add the trace buffer initialization code
+		 */
+		BUILD_TRACE_BUFFER_CHECK,
+
+		/**
+		 * Calls a function to add the function body
+		 */
+		TRACE_FUNCTION_BODY,
+
+		/**
+		 * Calls a function to add function parameters
+		 */
+		TRACE_FUNCTION_PARAMETERS,
+
+		/**
+		 * Writes the fixedBufferSize member variable
+		 */
+		FIXED_BUFFER_SIZE,
+
+		/**
+		 * Writes the dynamicBufferSize member variable
+		 */
+		DYNAMIC_BUFFER_SIZE,
+
+		/**
+		 * Index of the parameter being processed
+		 */
+		PARAMETER_INDEX
+	}
+
+	/**
+	 * Group ID shift bits
+	 */
+	private static final int GROUP_SHIFT = 16; // CodForChk_Dis_Magic
+
+	/**
+	 * Number of bytes in parameter
+	 */
+	private static final int BYTES_IN_PARAMETER = 4; // CodForChk_Dis_Magic
+
+	/**
+	 * Indent
+	 */
+	private static final String INDENT = "    "; //$NON-NLS-1$
+
+	/**
+	 * The header file to be updated
+	 */
+	private TraceHeader header;
+
+	/**
+	 * Output stream for the header
+	 */
+	private OutputStream headerOutput;
+
+	/**
+	 * Temporary flag that specifies if a trace requires a trace buffer or it
+	 * can be represented by the default trace macros
+	 */
+	private boolean buildTraceBuffer;
+
+	/**
+	 * Temporary variable for fixed size
+	 */
+	private int fixedBufferSize;
+
+	/**
+	 * Dynamic size flag
+	 */
+	private boolean dynamicBufferSizeFlag;
+
+	/**
+	 * Flag which is set it trace needs #endif for __KERNEL_MODE__
+	 */
+	private boolean needsKernelEndif;
+
+	/**
+	 * Used via HeaderTemplateElementType.FORMATTED_TRACE
+	 */
+	private String currentTraceFormatted;
+
+	/**
+	 * Type of current parameter
+	 */
+	private String currentParameterType;
+
+	/**
+	 * Name of current parameter
+	 */
+	private String currentParameterName;
+
+	/**
+	 * Index of current parameter
+	 */
+	private int currentParameterIndex;
+
+	/**
+	 * Number of opened brackets
+	 */
+	private int openBraceCount;
+
+	/**
+	 * Trace being processed
+	 */
+	private Trace currentTrace;
+
+	/**
+	 * Parameter being processed
+	 */
+	private TraceParameter currentParameter;
+
+	/**
+	 * List of trace functions already in the header
+	 */
+	private ArrayList<String> traceDeclarations = new ArrayList<String>();
+
+	/**
+	 * Number of sequential new lines
+	 */
+	private int newLineCount;
+
+	/**
+	 * Number of allowed sequential new lines
+	 */
+	private int maxNewLines;
+
+	/**
+	 * Indicates that writing a function to the header file is going
+	 */
+	private boolean firstOpenBraceFound;
+	
+	/**
+	 * boolean indication that we are buffering a function text
+	 */
+	private boolean bufferingFunction;
+
+	/**
+	 * While writing a function to the header file, it's gathered to this
+	 * member. The member is then checked if the function parameters contain
+	 * TInt or TUint values. If so, the function is replicated so that TInt is
+	 * replaced by TInt32 and TUint with TUint32.
+	 */
+	private StringBuilder functionText = new StringBuilder();
+
+	/**
+	 * Number of brackets seen when writing a function. When it gets to 0, the
+	 * function in previousFunction variable is complete and can be written.
+	 */
+	private int numberOfBrackets;
+		
+	/**
+	 * string to hold the function guard
+	 */
+	private String ostTraceGenxFunGuard;
+
+	/**
+	 * Creates a new header writer
+	 * 
+	 * @param header
+	 *            the header to be written
+	 */
+	TraceHeaderWriter(TraceHeader header) {
+		this.header = header;
+	}
+
+	/**
+	 * Writes the header
+	 * 
+	 * @return true if header was written, false if it matched the existing
+	 *         header
+	 * @throws TraceCompilerException
+	 *             if writing fails
+	 */
+	boolean write() throws TraceCompilerException {
+		boolean headerWritten = false;
+		try {
+			openBraceCount = 0;
+			createHeader();
+			writeTemplate(HeaderTemplate.HEADER_TEMPLATE);
+			headerWritten = closeHeader();
+		} catch (IOException e) {
+			e.printStackTrace();
+			throw new TraceCompilerException(
+					TraceCompilerErrorCode.CANNOT_WRITE_PROJECT_FILE, e);
+		} finally {
+			traceDeclarations.clear();
+			if (headerOutput != null) {
+				try {
+					headerOutput.close();
+				} catch (IOException e) {
+				}
+			}
+			headerOutput = null;
+		}
+		return headerWritten;
+	}
+
+	/**
+	 * Creates the header file
+	 * 
+	 * @throws IOException
+	 *             if creation fails
+	 */
+	private void createHeader() throws IOException {
+		File file = new File(header.getAbsolutePath());
+		if (file.exists()) {
+			// If header exists, data is written to a byte array and compared
+			// with existing file. If they are the same, the file is not
+			// updated.
+			headerOutput = new FileCompareOutputStream(file);
+		} else {
+			// If header does not exist, the data is written directly to file
+			headerOutput = FileUtils.createOutputStream(file);
+		}
+	}
+
+	/**
+	 * Closes the header file. If data was written to a byte buffer this
+	 * compares the contents of the buffer with the existing file and re-writes
+	 * the file if contents do not match.
+	 * 
+	 * @return true if header was written, false if it matched the existing
+	 *         header
+	 * @throws IOException
+	 *             if closing fails
+	 */
+	private boolean closeHeader() throws IOException {
+		boolean headerWritten = true;
+		if (headerOutput instanceof FileCompareOutputStream) {
+			headerWritten = ((FileCompareOutputStream) headerOutput)
+					.writeFile();
+		}
+		headerOutput.close();
+		headerOutput = null;
+		return headerWritten;
+	}
+
+	/**
+	 * Writes a template to the stream
+	 * 
+	 * @param template
+	 *            the template
+	 * @throws IOException
+	 *             if writing fails
+	 */
+	void writeTemplate(Object[] template) throws IOException {
+		for (Object o : template) {
+			if (o instanceof String) {
+				write((String) o);
+			} else if (o instanceof TraceHeaderContributionType) {
+				writeHeaderContributions((TraceHeaderContributionType) o);
+			} else if (o instanceof HeaderTemplateElementType) {
+				writeTemplateElement((HeaderTemplateElementType) o);
+			} else if (o instanceof Object[]) {
+				// Template within template
+				writeTemplate((Object[]) o);
+			} else if (o instanceof TemplateChoice) {
+				TemplateChoice choice = (TemplateChoice) o;
+				// Gets the array index from template
+				Class<? extends TemplateCheckBase> c = choice.getChoiceClass();
+				try {
+					// Creates a switch-case object based on array index
+					TemplateCheckBase check = c.newInstance();
+					check.setWriter(this);
+					// Gets the case from the switch-case object and uses it to
+					// get the correct template
+					if (check.check()) {
+						writeTemplate(choice.getTrueTemplate());
+					} else {
+						writeTemplate(choice.getFalseTemplate());
+					}
+				} catch (InstantiationException e) {
+				} catch (IllegalAccessException e) {
+				}
+			} else if (o instanceof TemplateIterator) {
+				Class<? extends TemplateIteratorEntry> c = ((TemplateIterator) o)
+						.getIteratorClass();
+				try {
+					// Creates an iterator object based on array index
+					TemplateIteratorEntry itr = c.newInstance();
+					itr.setWriter(this);
+					itr.iterate(((TemplateIterator) o).getTemplate());
+				} catch (InstantiationException e) {
+				} catch (IllegalAccessException e) {
+				}
+			} else if (o instanceof SetNewLineCount) {
+				maxNewLines = ((SetNewLineCount) o).getLineCount();
+			} else if (o instanceof TraceFormatType) {
+				// Stores the formatted trace, but does not write anything
+				// HeaderTemplateElementType.FORMATTED_TRACE writes the trace
+				currentTraceFormatted = SourceFormatter.formatTrace(
+						currentTrace, (TraceFormatType) o);
+			}
+		}
+	}
+
+	/**
+	 * Writes an element from the HeaderTemplateElementType enumeration
+	 * 
+	 * @param type
+	 *            the element type
+	 * @throws IOException
+	 *             if writing fails
+	 */
+	private void writeTemplateElement(HeaderTemplateElementType type)
+			throws IOException { // CodForChk_Dis_ComplexFunc
+		switch (type) {
+		case NEW_LINE:
+			writeNewLine();
+			break;
+		case OPEN_BRACE:
+			writeOpenBrace();
+			break;
+		case CLOSE_BRACE:
+			writeCloseBrace();
+			break;
+		case PARAMETER_INDEX:
+			write(String.valueOf(currentParameterIndex));
+			break;
+		case PARAMETER_TYPE:
+			write(currentParameterType);
+			break;
+		case PARAMETER_NAME:
+			write(currentParameterName);
+			break;
+		case FORMATTED_TRACE:
+			writeFormattedTrace(currentTraceFormatted);
+			break;
+		case TRACE_NAME:
+			write(currentTrace.getName());
+			break;
+		case TRACE_ID_HEX:
+			writeTraceID();
+			break;
+		case FIXED_BUFFER_SIZE:
+			write(String.valueOf(fixedBufferSize));
+			break;
+		case TRACE_FUNCTION_BODY:
+			writeFunctionBody(currentTrace);
+			break;
+		case TRACE_FUNCTION_PARAMETERS:
+			writeParameter(currentParameter);
+			break;
+		case BUILD_TRACE_BUFFER_CHECK:
+			buildTraceBuffer = traceNeedsBuffer(currentTrace);
+			break;
+		case HEADER_GUARD:
+			write(SourceUtils.createHeaderGuard(header.getFileName()));
+			break;
+		case TRACE_COMPILER_VERSION:
+			write(TraceCompilerVersion.getVersion());
+			break;
+		case CLOSE_EXTRA_BRACES:
+			while (openBraceCount > 1) {
+				writeCloseBrace();
+			}
+			break;
+		case LICENCE_TEXT:
+		    writeLicence();
+		    break;
+		}
+	}
+
+	/**
+	 * Writes the trace ID to header
+	 * 
+	 * @throws IOException
+	 *             if writing fails
+	 */
+	private void writeTraceID() throws IOException {
+		int gid = currentTrace.getGroup().getID() << GROUP_SHIFT;
+		write(Integer.toHexString(gid | currentTrace.getID()));
+		ComplexHeaderRule rule = currentTrace
+				.getExtension(ComplexHeaderRule.class);
+		if (rule != null) {
+			String ext = rule.getTraceIDDefineExtension();
+			if (ext != null) {
+				write(ext);
+			}
+		}
+	}
+
+	/**
+	 * Writes the header contributions from plug-in's
+	 * 
+	 * @param type
+	 *            the contribution type
+	 * @throws IOException
+	 *             if writing fails
+	 */
+	private void writeHeaderContributions(TraceHeaderContributionType type)
+			throws IOException {
+		Iterator<String> contributions = getContributions(type);
+		boolean written = false;
+		while (contributions.hasNext()) {
+			writeContribution(contributions.next(), type);
+			written = true;
+		}
+		if (written) {
+			writeNewLine();
+		}
+	}
+
+	/**
+	 * Gets a list of contributions from plug-in's
+	 * 
+	 * @param type
+	 *            the contribution type
+	 * @return the contributions
+	 */
+	private Iterator<String> getContributions(TraceHeaderContributionType type) {
+		Iterator<TraceHeaderContribution> contributions = header.getOwner()
+				.getExtensions(TraceHeaderContribution.class);
+		ArrayList<String> list = new ArrayList<String>();
+		while (contributions.hasNext()) {
+			String[] s = contributions.next().getContribution(type);
+			if (s != null) {
+				for (String element : s) {
+					list.add(element);
+				}
+			}
+		}
+		return list.iterator();
+	}
+
+	/**
+	 * Writes a contribution to the stream
+	 * 
+	 * @param contribution
+	 *            the contribution
+	 * @param type
+	 *            the contribution type
+	 * @throws IOException
+	 *             if writing fails
+	 */
+	private void writeContribution(String contribution,
+			TraceHeaderContributionType type) throws IOException {
+		switch (type) {
+		case GLOBAL_DEFINES:
+			writeDefine(contribution);
+			break;
+		case GLOBAL_INCLUDES:
+			writeSystemInclude(contribution);
+			break;
+		case MAIN_HEADER_CONTENT:
+			// Handled by HeaderEngine
+			break;
+		}
+	}
+	
+	/**
+	 * write start of function guard
+	 * @throws IOException
+	 */
+	private void writeStartFunctionGuard() throws IOException {
+		Pattern p = Pattern.compile("inline\\s+TBool\\s+([^\\(]+)\\s*\\((.*)\\)\\s*\\{"); //$NON-NLS-1$
+		String guard = null;
+		String functionName = null;
+		
+		// Get the function definition line
+		int startIndex = functionText.indexOf(SourceConstants.OPENING_BRACE) + 1;
+		String funcDef = functionText.substring(0, startIndex);
+		
+		Matcher m = p.matcher(funcDef);
+		if (m.matches()) {
+			//get function name
+			functionName = m.group(1);
+			if (functionName == null || functionName.length() == 0) {
+				throw new IOException(Messages.getString("TraceHeader.internalError1")); //$NON-NLS-1$
+			}
+			//get raw parameters
+			String parameters = m.group(2);
+			if (parameters == null || parameters.length() == 0) {//there must be at least TraceID
+				throw new IOException(Messages.getString("TraceHeader.internalError2")); //$NON-NLS-1$
+			}
+			
+			functionName = functionName.trim();
+			parameters = parameters.trim();
+			//remove parameters names
+			guard = parameters.replaceAll("(\\S+,)|(\\S+\\s*$)", ""); //$NON-NLS-1$ //$NON-NLS-2$
+			//replace repeated spaces by one space
+			guard = guard.replaceAll("\\s+", SourceConstants.SPACE).trim(); //$NON-NLS-1$
+			//replace space by underscore
+			guard = guard.replace(SourceConstants.SPACE, SourceConstants.UNDERSCORE);
+			//replace ampersant by REF
+			guard = guard.replace(AMPERSANT, REF);
+			//replace ( by OBR
+			guard = guard.replace(OPEN_BRACKET, BEGINCAST);
+			//replace ) by CBR
+			guard = guard.replace(CLOSING_BRACKET, ENDCAST);
+		} else {
+			throw new IOException(Messages.getString("TraceHeader.internalError3")); //$NON-NLS-1$
+		}
+		
+		guard = SourceConstants.DOUBLE_UNDERSCORE 
+				+ functionName.toUpperCase()
+				+ SourceConstants.UNDERSCORE
+				+ guard.toUpperCase()
+				+ SourceConstants.DOUBLE_UNDERSCORE;
+		
+		ostTraceGenxFunGuard = guard;
+		write( SourceConstants.IFNDEF + SourceConstants.SPACE_CHAR + ostTraceGenxFunGuard);
+		write(SourceConstants.LINE_FEED);
+		write( SourceConstants.DEFINE +SourceConstants.SPACE_CHAR + ostTraceGenxFunGuard);
+		write(SourceConstants.LINE_FEED);
+		write(SourceConstants.LINE_FEED);
+	}
+
+	/**
+	 * write end of function guard
+	 * @throws IOException
+	 */
+	private void writeEndFunctionGuard() throws IOException {
+		if (ostTraceGenxFunGuard != null) {
+			write(SourceConstants.LINE_FEED);
+			write(SourceConstants.LINE_FEED);
+			write(SourceConstants.ENDIF 
+					+ SourceConstants.SPACE_CHAR
+					+ SourceConstants.FORWARD_SLASH_CHAR
+					+ SourceConstants.FORWARD_SLASH_CHAR
+					+ SourceConstants.SPACE_CHAR
+					+ ostTraceGenxFunGuard);
+			write(SourceConstants.LINE_FEED);
+		}
+	}
+	/**
+	 * Writes the function body to the stream
+	 * 
+	 * @param trace
+	 *            the trace to be written
+	 * @throws IOException
+	 *             if writing fails
+	 */
+	private void writeFunctionBody(Trace trace) throws IOException {
+		writeTraceBufferAllocation(trace);
+		writeTemplate(HeaderTemplate.PARAMETERS_TEMPLATE);
+		// If buffer is not used (single descriptor parameter), trace line is
+		// already written in template
+		if (isTraceBufferBuilt()) {
+			writeTraceLine(trace);
+		}
+	}
+
+	/**
+	 * Writes trace buffer allocation code to the function
+	 * 
+	 * @param trace
+	 *            the trace to be written
+	 * @throws IOException
+	 *             if writing fails
+	 */
+	private void writeTraceBufferAllocation(Trace trace) throws IOException {
+		// If buffer is not used (single descriptor parameter), this function
+		// does nothing
+		if (isTraceBufferBuilt()) {
+			Iterator<TraceParameter> parameters = trace.getParameters();
+			lenghtVariableDefined = false;
+			int fixedSizeParametersTotalSize = 0;
+			while (parameters.hasNext()) {
+				TraceParameter parameter = parameters.next();
+				TraceParameterFormattingRule sourceRule = parameter
+						.getExtension(TraceParameterFormattingRule.class);
+				if (sourceRule == null || sourceRule.isShownInSource()
+						|| sourceRule instanceof FillerParameterRule) {
+					// Fillers do not increment parameter index
+					if (!(sourceRule instanceof FillerParameterRule)) {
+						currentParameterIndex++;
+					}
+					int paramSize = SourceUtils
+							.mapParameterTypeToSize(parameter);
+					// calculateParameterSize returns 0 for dynamic parameters,
+					// but 4 extra bytes need to be reserved for the length
+					if (paramSize == 0) {
+						paramSize = BYTES_IN_PARAMETER;
+					}
+					fixedBufferSize += paramSize;
+					fixedSizeParametersTotalSize += paramSize;
+					if (SourceUtils.isParameterSizeDynamic(parameter)) {
+
+						// Define length variable only once
+						if (lenghtVariableDefined == false) {
+							writeTemplate(HeaderTemplate.LENGTH_VARIABLE_DEFINITION_TEMPLATE);
+							lenghtVariableDefined = true;
+						}
+
+						// Increase length variable if needed
+						// This is needed in case that there has been fixed size
+						// parameter
+						// before dynamic parameter
+						if (fixedSizeParametersTotalSize - paramSize > 0) {
+							fixedSizeParametersTotalSize -= paramSize;
+							writeTemplate(HeaderTemplate.LENGTH_VARIABLE_INCREASE_TEMPLATE_BEGIN);
+							write(String.valueOf(fixedSizeParametersTotalSize));
+							writeTemplate(HeaderTemplate.LENGTH_VARIABLE_INCREASE_TEMPLATE_END);
+						}
+
+						fixedSizeParametersTotalSize = 0;
+
+						writeTemplate(HeaderTemplate.DYNAMIC_PARAMETER_LENGTH_TEMPLATE);
+						dynamicBufferSizeFlag = true;
+					}
+				}
+			}
+			writeTemplate(HeaderTemplate.BUFFER_ALLOCATION_TEMPLATE);
+			currentParameterIndex = 0;
+		}
+	}
+
+	/**
+	 * Writes the given parameter to the header
+	 * 
+	 * @param parameter
+	 *            the parameter
+	 * @throws IOException
+	 *             if writing fails
+	 */
+	void writeParameter(TraceParameter parameter) throws IOException {
+		TraceParameterFormattingRule sourceRule = parameter
+				.getExtension(TraceParameterFormattingRule.class);
+		if (sourceRule == null || sourceRule.isShownInSource()
+				|| sourceRule instanceof FillerParameterRule) {
+			String paramType = SourceUtils
+					.mapParameterTypeToSymbianType(parameter);
+			if (SourceUtils.isParameterSizeDynamic(parameter)) {
+				currentParameterIndex++;
+				currentParameterName = SymbianConstants.PARAMETER_DECLARATION_PREFIX
+						+ currentParameterIndex;
+				writeTemplate(HeaderTemplate.DYNAMIC_PARAMETER_TEMPLATE);
+			} else {
+				currentParameterType = paramType;
+				if (sourceRule instanceof FillerParameterRule) {
+					currentParameterName = "0"; //$NON-NLS-1$
+					writeTemplate(HeaderTemplate.FIXED_PARAMETER_TEMPLATE);
+				} else {
+					currentParameterIndex++;
+					currentParameterName = SymbianConstants.PARAMETER_DECLARATION_PREFIX
+							+ currentParameterIndex;
+					if (lenghtVariableDefined == true) {
+						writeTemplate(HeaderTemplate.FIXED_PARAMETER_TEMPLATE_WITH_LENGTH_CHECK);
+					} else {
+						writeTemplate(HeaderTemplate.FIXED_PARAMETER_TEMPLATE);
+					}
+				}
+			}
+		}
+	}
+
+	/**
+	 * Writes the trace line to the function
+	 * 
+	 * @param trace
+	 *            the trace to be written
+	 * @throws IOException
+	 *             if writing fails
+	 */
+	private void writeTraceLine(Trace trace) throws IOException {
+		StringBuffer sb;
+		StringBuffer bufferData = new StringBuffer();
+		StringBuffer lengthData = new StringBuffer();
+		if (isBufferSizeDynamic()) {
+			sb = writeBufferedTraceLine(trace, bufferData, lengthData);
+		} else {
+			// If buffer size is 4, the buffer can be traced using the
+			// the 32-bit parameter trace macro instead of data macro
+			if (fixedBufferSize / BYTES_IN_PARAMETER == 1) {
+				sb = writePackedTraceLine(trace, bufferData);
+			} else {
+				sb = writeBufferedTraceLine(trace, bufferData, lengthData);
+			}
+		}
+		int index = sb.indexOf(TraceFormatConstants.DATA_BUFFER_FORMAT);
+		if (index >= 0) {
+			sb.replace(index, index
+					+ TraceFormatConstants.DATA_BUFFER_FORMAT.length(),
+					bufferData.toString());
+		}
+		index = sb.indexOf(TraceFormatConstants.DATA_LENGTH_FORMAT);
+		if (index >= 0) {
+			sb.replace(index, index
+					+ TraceFormatConstants.DATA_LENGTH_FORMAT.length(),
+					lengthData.toString());
+		}
+		String s = sb.toString();
+		write("retval = "); //$NON-NLS-1$
+		writeFormattedTrace(s);
+		writeNewLine();
+	}
+
+	/**
+	 * Writes a trace line when the parameters can be fitted into a direct API
+	 * call
+	 * 
+	 * @param trace
+	 *            the trace
+	 * @param bufferData
+	 *            the buffer
+	 * @return formatted trace
+	 */
+	private StringBuffer writePackedTraceLine(Trace trace,
+			StringBuffer bufferData) {
+		StringBuffer sb;
+		// The formatting rule is used to get the API macro
+		sb = new StringBuffer(SourceFormatter.formatTrace(trace,
+				TraceFormatType.TRACE_PACKED));
+		TraceFormattingRule rule = trace
+				.getExtension(TraceFormattingRule.class);
+		if (rule == null) {
+			rule = trace.getModel().getExtension(TraceFormattingRule.class);
+		}
+		int index = sb.indexOf(TraceFormatConstants.PARAM_COUNT_FORMAT);
+		if (index >= 0) {
+			// Single parameter is supported
+			sb.replace(index, index
+					+ TraceFormatConstants.PARAM_COUNT_FORMAT.length(), rule
+					.mapParameterCountToSource(trace, 1));
+		}
+		bufferData.append("*( ( TUint32* )ptr )"); //$NON-NLS-1$
+		return sb;
+	}
+
+	/**
+	 * Writes a trace line when the trace contains more data that the API
+	 * supports
+	 * 
+	 * @param trace
+	 *            the trace
+	 * @param bufferData
+	 *            the trace buffer
+	 * @param lengthData
+	 *            the trace length buffer
+	 * @return the formatted trace
+	 */
+	private StringBuffer writeBufferedTraceLine(Trace trace,
+			StringBuffer bufferData, StringBuffer lengthData) {
+		StringBuffer sb;
+		// Buffer parameter
+		// *( ( TUint32* )ptr ), *( ( TUint32* )( ptr + 4 ) ), ..., ptr + x
+		sb = new StringBuffer(SourceFormatter.formatTrace(trace,
+				TraceFormatType.TRACE_BUFFER));
+		if (isTraceBufferBuilt()) {
+			bufferData.append("ptr"); //$NON-NLS-1$
+			if (isBufferSizeDynamic()) {
+				// In case of dynamic buffer, the length has been calculated
+				// into length variable
+				lengthData.append("length"); //$NON-NLS-1$
+			} else {
+				// Fixed size case
+				lengthData.append(String.valueOf(fixedBufferSize));
+			}
+		} else {
+			// In case of no-buffer, the size variable contain the data size
+			bufferData.append("ptr"); //$NON-NLS-1$
+			lengthData.append("size"); //$NON-NLS-1$
+		}
+		return sb;
+	}
+
+	/**
+	 * Writes a formatted trace to the stream. This removes the newline from the
+	 * trace if it exists
+	 * 
+	 * @param trace
+	 *            the trace
+	 * @throws IOException
+	 *             if writing fails
+	 */
+	private void writeFormattedTrace(String trace) throws IOException {
+		if (trace.endsWith(SourceConstants.LINE_FEED)) {
+			write(trace.substring(0, trace.length()
+					- SourceConstants.LINE_FEED.length()));
+		} else {
+			write(trace);
+		}
+	}
+
+	/**
+	 * Increases indent and writes a new line, brace, new line combination
+	 * 
+	 * @throws IOException
+	 *             if writing fails
+	 */
+	private void writeOpenBrace() throws IOException {
+		openBraceCount++;
+		writeNewLine();
+		write(SourceConstants.OPENING_BRACE);
+		writeNewLine();
+	}
+
+	/**
+	 * Write brace, decreases indent and writes a new line
+	 * 
+	 * @throws IOException
+	 *             if writing fails
+	 */
+	private void writeCloseBrace() throws IOException {
+		write(SourceConstants.CLOSING_BRACE);
+		openBraceCount--;
+		writeNewLine();
+	}
+	
+	/**
+	 * write licence Text
+	 * @throws IOException if write fails
+	 */
+	private void writeLicence() throws IOException {
+		String licence = null;
+		SourceParser parser = null;
+		//first get any of the traces belonging to this header
+		TraceModel model = header.getOwner().getModel();
+		for (TraceGroup group : model) {
+			for (Trace trace : group) {
+				Iterator<LocationListBase> itr = trace.getExtensions(LocationListBase.class);
+				// The trace must have at least one location that belong to this header
+				while (itr.hasNext() && parser == null) {
+					LocationListBase list = itr.next();
+					for (LocationProperties loc : list) {
+						if (isValidTraceForHeader(loc.getFileName())) {
+								parser = ((TraceLocation)loc).getParser();
+								break;
+						}
+					}
+				}
+				if (parser!= null)  {
+					break;
+				}
+			}
+			if (parser != null) {
+				break;
+			}
+		}
+		
+		if (parser!= null) {
+		List<SourceExcludedArea> excludedAreas = parser.getExcludedAreas();
+		//try to find licence from the source
+		if (!excludedAreas.isEmpty()) {
+			SourceExcludedArea sourceExcludedArea = excludedAreas.get(0);
+			int offset = sourceExcludedArea.getOffset();
+			int type = sourceExcludedArea.getType();
+			int length = sourceExcludedArea.getLength();
+			if (offset == 0 && type == SourceExcludedArea.MULTILINE_COMMENT) {
+				String data = sourceExcludedArea.getParser().getData(offset, length);
+				if (data.contains("Copyright")) { //$NON-NLS-1$
+					// licence found write it
+					TraceCompilerLogger.printInfo("Add Licence text from: " + sourceExcludedArea.getFileName() + " to : " + header.getAbsolutePath()); //$NON-NLS-1$
+					licence = data;
+					write(licence);
+				}
+			}	
+		}
+		}
+		
+		if (licence == null) {
+			//get default licence from the licence file
+			licence = TraceCompilerEngineGlobals.getDefaultLicence(true);
+			
+			if(licence != null) {
+				TraceCompilerLogger.printInfo("Add default EPL Licence to : " + header.getAbsolutePath()); //$NON-NLS-1$
+				write(licence);
+			}
+		}
+	}
+
+	/**
+	 * Writes a new line and indent to the stream
+	 * 
+	 * @throws IOException
+	 *             if writing fails
+	 */
+	private void writeNewLine() throws IOException {
+		int newLines = newLineCount;
+		while (newLines < maxNewLines) {
+			write(SourceConstants.LINE_FEED);
+			for (int i = 0; i < openBraceCount; i++) {
+				write(INDENT);
+			}
+			newLines++;
+		}
+		newLineCount = maxNewLines;
+	}
+
+	/**
+	 * Writes a define to stream
+	 * 
+	 * @param name
+	 *            the name for the define
+	 * @throws IOException
+	 *             if writing fails
+	 */
+	private void writeDefine(String name) throws IOException {
+		write(SourceConstants.DEFINE);
+		write(SourceConstants.SPACE);
+		write(name);
+		writeNewLine();
+	}
+
+	/**
+	 * Writes include to header
+	 * 
+	 * @param name
+	 *            the header name
+	 * @throws IOException
+	 *             if writing fails
+	 */
+	private void writeSystemInclude(String name) throws IOException {
+		write(SourceConstants.INCLUDE);
+		write(SourceConstants.SPACE);
+		write("<"); //$NON-NLS-1$
+		write(name);
+		write(">"); //$NON-NLS-1$
+		writeNewLine();
+	}
+
+	/**
+	 * Writes data to a stream
+	 * 
+	 * @param data
+	 *            the string of data
+	 * @throws IOException
+	 *             if writing fails
+	 */
+	private void write(String data) throws IOException {
+		// Check if function starts
+		if (data.contains(INLINE_TBOOL) || bufferingFunction) {
+			bufferingFunction = true;
+			functionText.append(data);
+		} else {
+			headerOutput.write(data.getBytes());
+		}
+			newLineCount = 0;
+
+		//try to duplicate function if the current function processing is complete and duplicate is needed.
+		writeAndDuplicateFunction(data);
+	}
+
+	/**
+	 * Duplicates the function if needed
+	 * 
+	 * @param data
+	 *            data String
+	 * @throws IOException
+	 *             if writing fails
+	 */
+	private void writeAndDuplicateFunction(String data) throws IOException {
+			// This assumes there is only one start or end bracket in one line!
+			if (data.contains(SourceConstants.OPENING_BRACE)) {
+				firstOpenBraceFound = true;
+				numberOfBrackets++;
+			} else if (data.contains(SourceConstants.CLOSING_BRACE)) {
+				numberOfBrackets--;
+
+				// Function ends
+				if (numberOfBrackets == 0 && firstOpenBraceFound) {
+					firstOpenBraceFound = false;
+					bufferingFunction = false;
+					//write start function guard
+					writeStartFunctionGuard();
+					//write the function
+					headerOutput.write(functionText.toString().getBytes());
+					//write end function guard
+					writeEndFunctionGuard();
+
+					//process duplicate if needed
+					// Get the function definition line
+					int startIndex = functionText.indexOf(SourceConstants.OPENING_BRACE);
+					String funcDef = functionText.substring(0, startIndex);
+
+					// Replace TInt with TInt32 and TUint with TUint32 from the
+					// header and write the function back again
+					if (funcDef.contains(TINT_DEF)
+							|| funcDef.contains(TUINT_DEF)) {
+						//replace and duplicate
+						funcDef = funcDef.replace(TINT_DEF, TINT32_DEF);
+						funcDef = funcDef.replace(TUINT_DEF, TUINT32_DEF);
+						functionText.replace(0, startIndex, funcDef);
+						
+						//write start function guard for duplicate
+						write(SourceConstants.LINE_FEED);
+						write(SourceConstants.LINE_FEED);
+						writeStartFunctionGuard();
+						
+						//write duplicate function
+						headerOutput.write(functionText.toString().getBytes());
+						
+						//write end function guard for duplicate
+						writeEndFunctionGuard();
+					}
+
+					functionText.setLength(0);
+				}
+			}
+	}
+
+	/**
+	 * Checks if a trace needs a buffer or it can be represented with regular
+	 * trace macros.
+	 * 
+	 * @param trace
+	 *            the trace
+	 * @return true if trace needs a buffer
+	 */
+	private boolean traceNeedsBuffer(Trace trace) {
+		// A single dynamic parameter can be passed through the regular
+		// API macros. In that case the parameter length is determined
+		// by the trace message length
+		Iterator<TraceParameter> parameters = trace.getParameters();
+		boolean needsBuffer = false;
+		boolean dynamicFound = false;
+		while (parameters.hasNext() && !needsBuffer) {
+			TraceParameter parameter = parameters.next();
+			if (isParameterVisible(parameter)) {
+				if (SourceUtils.isParameterSizeDynamic(parameter)) {
+					if (dynamicFound) {
+						needsBuffer = true;
+					} else {
+						dynamicFound = true;
+					}
+				} else {
+					needsBuffer = true;
+				}
+			}
+		}
+		return needsBuffer;
+	}
+
+	/**
+	 * Checks if a parameter is visible
+	 * 
+	 * @param parameter
+	 *            the parameter to be checked
+	 * @return true if visible, false if not
+	 */
+	private boolean isParameterVisible(TraceParameter parameter) {
+		boolean retval;
+		TraceParameterFormattingRule sourceRule = parameter
+				.getExtension(TraceParameterFormattingRule.class);
+		if (sourceRule == null || sourceRule.isShownInSource()) {
+			retval = true;
+		} else {
+			retval = false;
+		}
+		return retval;
+	}
+
+	/**
+	 * Gets the formatted trace
+	 * 
+	 * @return the trace
+	 */
+	String getCurrentTraceFormatted() {
+		return currentTraceFormatted;
+	}
+
+	/**
+	 * Checks if trace is already formatted to header
+	 * 
+	 * @return true if formatted
+	 */
+	boolean isTraceFormatDuplicate() {
+		boolean retval;
+		if (traceDeclarations.contains(currentTraceFormatted)) {
+			retval = true;
+		} else {
+			traceDeclarations.add(currentTraceFormatted);
+			retval = false;
+		}
+		return retval;
+	}
+
+	/**
+	 * Checks if the buffer size for current trace is fixed
+	 * 
+	 * @return the flag
+	 */
+	boolean isTraceBufferFixed() {
+		return fixedBufferSize != 0;
+	}
+
+	/**
+	 * Checks if the buffer is built
+	 * 
+	 * @return the flag
+	 */
+	boolean isTraceBufferBuilt() {
+		return buildTraceBuffer;
+	}
+
+	/**
+	 * Gets the current trace
+	 * 
+	 * @return the trace
+	 */
+	Trace getCurrentTrace() {
+		return currentTrace;
+	}
+
+	/**
+	 * Gets the header
+	 * 
+	 * @return the header
+	 */
+	TraceHeader getHeader() {
+		return header;
+	}
+
+	/**
+	 * Starts writing a trace
+	 * 
+	 * @param trace
+	 *            the trace
+	 * @return true if trace can be written, false if not
+	 */
+	boolean startTrace(Trace trace) {
+		boolean validTrace = false;
+		Iterator<LocationListBase> itr = trace
+				.getExtensions(LocationListBase.class);
+		// The trace must have at least one location that belong to this header
+		while (itr.hasNext() && !validTrace) {
+			LocationListBase list = itr.next();
+			for (LocationProperties loc : list) {
+				validTrace = isValidTraceForHeader(loc.getFileName());
+				if (validTrace) {
+					break;
+				}
+			}
+		}
+		if (validTrace) {
+			currentTrace = trace;
+			fixedBufferSize = 0;
+			dynamicBufferSizeFlag = false;
+			buildTraceBuffer = false;
+			currentTraceFormatted = null;
+			currentParameterName = null;
+			currentParameterType = null;
+			currentParameterIndex = 0;
+		}
+		return validTrace;
+	}
+
+	/**
+	 * Checks if the location belongs to this header
+	 * 
+	 * @param locFileName
+	 *            the location
+	 * @return true if location belongs here
+	 */
+	private boolean isValidTraceForHeader(String locFileName) {
+		boolean valid = false;
+		if (locFileName != null) {
+			int index = locFileName.lastIndexOf('.');
+			if (index >= 0) {
+				locFileName = locFileName.substring(0, index);
+			}
+			if (locFileName.equals(header.getProjectName())) {
+				valid = true;
+			}
+		}
+		return valid;
+	}
+
+	/**
+	 * Starts writing a parameter
+	 * 
+	 * @param parameter
+	 *            the parameter
+	 */
+	void startParameter(TraceParameter parameter) {
+		currentParameterName = null;
+		currentParameterType = null;
+		currentParameter = parameter;
+	}
+
+	/**
+	 * Sets the kernel mode #endif needed flag
+	 * 
+	 * @param flag
+	 *            the flag
+	 */
+	void setKernelModeEndifNeeded(boolean flag) {
+		needsKernelEndif = flag;
+	}
+
+	/**
+	 * Gets the kernel mode endif needed flag
+	 * 
+	 * @return the flag
+	 */
+	boolean isKernelModeEndifNeeded() {
+		return needsKernelEndif;
+	}
+
+	/**
+	 * Returns the dynamic buffer size flag
+	 * 
+	 * @return true if buffer size is dynamic
+	 */
+	boolean isBufferSizeDynamic() {
+		return dynamicBufferSizeFlag;
+	}
+
+	/**
+	 * Checks if current parameter needs alignment
+	 * 
+	 * @return true if needed
+	 */
+	boolean isParameterAlignmentNeeded() {
+		return SourceUtils.isParameterAlignementNeeded(currentParameter
+				.getType());
+	}
+
+}