tracefw/tracecompiler/src/com.nokia.tracecompiler/src/com/nokia/tracecompiler/engine/header/TraceHeaderWriter.java
changeset 56 aa2539c91954
parent 54 a151135b0cf9
child 60 e54443a6878c
child 62 1c2bb2fc7c87
equal deleted inserted replaced
54:a151135b0cf9 56:aa2539c91954
     1 /*
       
     2  * Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies). 
       
     3  * All rights reserved.
       
     4  * This component and the accompanying materials are made available
       
     5  * under the terms of "Eclipse Public License v1.0"
       
     6  * which accompanies this distribution, and is available
       
     7  * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8  *
       
     9  * Initial Contributors:
       
    10  * Nokia Corporation - initial contribution.
       
    11  *
       
    12  * Contributors:
       
    13  *
       
    14  * Description:
       
    15  *
       
    16  * Writes the TraceHeader to a file
       
    17  *
       
    18  */
       
    19 package com.nokia.tracecompiler.engine.header;
       
    20 
       
    21 import java.io.File;
       
    22 import java.io.IOException;
       
    23 import java.io.OutputStream;
       
    24 import java.util.ArrayList;
       
    25 import java.util.Iterator;
       
    26 import java.util.List;
       
    27 import java.util.regex.Matcher;
       
    28 import java.util.regex.Pattern;
       
    29 
       
    30 import com.nokia.tracecompiler.TraceCompilerLogger;
       
    31 import com.nokia.tracecompiler.engine.LocationListBase;
       
    32 import com.nokia.tracecompiler.engine.LocationProperties;
       
    33 import com.nokia.tracecompiler.engine.TraceCompilerEngineGlobals;
       
    34 import com.nokia.tracecompiler.engine.TraceLocation;
       
    35 import com.nokia.tracecompiler.engine.TraceCompilerEngineErrorCodes.TraceCompilerErrorCode;
       
    36 import com.nokia.tracecompiler.engine.source.SourceFormatter;
       
    37 import com.nokia.tracecompiler.engine.source.TraceFormattingRule;
       
    38 import com.nokia.tracecompiler.engine.source.TraceParameterFormattingRule;
       
    39 import com.nokia.tracecompiler.file.FileCompareOutputStream;
       
    40 import com.nokia.tracecompiler.file.FileUtils;
       
    41 import com.nokia.tracecompiler.model.Trace;
       
    42 import com.nokia.tracecompiler.model.TraceCompilerException;
       
    43 import com.nokia.tracecompiler.model.TraceGroup;
       
    44 import com.nokia.tracecompiler.model.TraceModel;
       
    45 import com.nokia.tracecompiler.model.TraceParameter;
       
    46 import com.nokia.tracecompiler.plugin.TraceFormatConstants;
       
    47 import com.nokia.tracecompiler.plugin.TraceHeaderContribution;
       
    48 import com.nokia.tracecompiler.plugin.TraceAPIFormatter.TraceFormatType;
       
    49 import com.nokia.tracecompiler.plugin.TraceHeaderContribution.TraceHeaderContributionType;
       
    50 import com.nokia.tracecompiler.rules.FillerParameterRule;
       
    51 import com.nokia.tracecompiler.source.SourceConstants;
       
    52 import com.nokia.tracecompiler.source.SourceExcludedArea;
       
    53 import com.nokia.tracecompiler.source.SourceParser;
       
    54 import com.nokia.tracecompiler.source.SourceUtils;
       
    55 import com.nokia.tracecompiler.source.SymbianConstants;
       
    56 import com.nokia.tracecompiler.utils.TraceCompilerVersion;
       
    57 
       
    58 /**
       
    59  * Writes the TraceHeader to a file
       
    60  * 
       
    61  */
       
    62 final class TraceHeaderWriter {
       
    63 
       
    64 	/**
       
    65 	 * return type text of a generated OstTraceGenx function.
       
    66 	 */
       
    67 	private static final String INLINE_TBOOL = "inline TBool";
       
    68 
       
    69 	/**
       
    70 	 * open bracket in a type cast
       
    71 	 */
       
    72 	private static final String BEGINCAST = "OBR"; //$NON-NLS-1$
       
    73 	
       
    74 	/**
       
    75 	 * closing bracket in a type cast
       
    76 	 */
       
    77 	private static final String ENDCAST = "CBR"; //$NON-NLS-1$
       
    78 
       
    79 	/**
       
    80 	 * REF replaces & in a function guard
       
    81 	 */
       
    82 	private static final String REF = "REF"; //$NON-NLS-1$
       
    83 
       
    84 	/**
       
    85 	 * & character
       
    86 	 */
       
    87 	private static final String AMPERSANT = "&"; //$NON-NLS-1$
       
    88 
       
    89 	/**
       
    90 	 * closing bracket
       
    91 	 */
       
    92 	private static final String CLOSING_BRACKET = ")"; //$NON-NLS-1$
       
    93 
       
    94 	/**
       
    95 	 * open bracket
       
    96 	 */
       
    97 	private static final String OPEN_BRACKET = "("; //$NON-NLS-1$
       
    98 
       
    99 	/**
       
   100 	 * TUint32 definition
       
   101 	 */
       
   102 	private static final String TUINT32_DEF = "TUint32 "; //$NON-NLS-1$
       
   103 
       
   104 	/**
       
   105 	 * TInt32 definition
       
   106 	 */
       
   107 	private static final String TINT32_DEF = "TInt32 "; //$NON-NLS-1$
       
   108 
       
   109 	/**
       
   110 	 * TUint definition
       
   111 	 */
       
   112 	private static final String TUINT_DEF = "TUint "; //$NON-NLS-1$
       
   113 
       
   114 	/**
       
   115 	 * TInt definition
       
   116 	 */
       
   117 	private static final String TINT_DEF = "TInt "; //$NON-NLS-1$
       
   118 
       
   119 	/**
       
   120 	 * Length variable defined flag
       
   121 	 */
       
   122 	private boolean lenghtVariableDefined = false;
       
   123 	
       
   124 	
       
   125 	/**
       
   126 	 * List of dynamic elements that can be used from the templates
       
   127 	 * 
       
   128 	 */
       
   129 	enum HeaderTemplateElementType {
       
   130 
       
   131 		/**
       
   132 		 * Licence text
       
   133 		 */
       
   134 		LICENCE_TEXT,
       
   135 		
       
   136 		/**
       
   137 		 * TraceCompiler version number
       
   138 		 */
       
   139 		TRACE_COMPILER_VERSION,
       
   140 
       
   141 		/**
       
   142 		 * Header guard based on file name
       
   143 		 */
       
   144 		HEADER_GUARD,
       
   145 
       
   146 		/**
       
   147 		 * Opening brace
       
   148 		 */
       
   149 		OPEN_BRACE,
       
   150 
       
   151 		/**
       
   152 		 * Closing brace
       
   153 		 */
       
   154 		CLOSE_BRACE,
       
   155 
       
   156 		/**
       
   157 		 * New line and indent based on open brace count
       
   158 		 */
       
   159 		NEW_LINE,
       
   160 
       
   161 		/**
       
   162 		 * Writes currentTraceFormatted
       
   163 		 */
       
   164 		FORMATTED_TRACE,
       
   165 
       
   166 		/**
       
   167 		 * Adds all closing braces except the one that closes the function
       
   168 		 */
       
   169 		CLOSE_EXTRA_BRACES,
       
   170 
       
   171 		/**
       
   172 		 * Type of current parameter
       
   173 		 */
       
   174 		PARAMETER_TYPE,
       
   175 
       
   176 		/**
       
   177 		 * Name of current parameter
       
   178 		 */
       
   179 		PARAMETER_NAME,
       
   180 
       
   181 		/**
       
   182 		 * Name of current trace
       
   183 		 */
       
   184 		TRACE_NAME,
       
   185 
       
   186 		/**
       
   187 		 * ID of current trace
       
   188 		 */
       
   189 		TRACE_ID_HEX,
       
   190 
       
   191 		/**
       
   192 		 * Calls a function to add the trace buffer initialization code
       
   193 		 */
       
   194 		BUILD_TRACE_BUFFER_CHECK,
       
   195 
       
   196 		/**
       
   197 		 * Calls a function to add the function body
       
   198 		 */
       
   199 		TRACE_FUNCTION_BODY,
       
   200 
       
   201 		/**
       
   202 		 * Calls a function to add function parameters
       
   203 		 */
       
   204 		TRACE_FUNCTION_PARAMETERS,
       
   205 
       
   206 		/**
       
   207 		 * Writes the fixedBufferSize member variable
       
   208 		 */
       
   209 		FIXED_BUFFER_SIZE,
       
   210 
       
   211 		/**
       
   212 		 * Writes the dynamicBufferSize member variable
       
   213 		 */
       
   214 		DYNAMIC_BUFFER_SIZE,
       
   215 
       
   216 		/**
       
   217 		 * Index of the parameter being processed
       
   218 		 */
       
   219 		PARAMETER_INDEX
       
   220 	}
       
   221 
       
   222 	/**
       
   223 	 * Group ID shift bits
       
   224 	 */
       
   225 	private static final int GROUP_SHIFT = 16; // CodForChk_Dis_Magic
       
   226 
       
   227 	/**
       
   228 	 * Number of bytes in parameter
       
   229 	 */
       
   230 	private static final int BYTES_IN_PARAMETER = 4; // CodForChk_Dis_Magic
       
   231 
       
   232 	/**
       
   233 	 * Indent
       
   234 	 */
       
   235 	private static final String INDENT = "    "; //$NON-NLS-1$
       
   236 
       
   237 	/**
       
   238 	 * The header file to be updated
       
   239 	 */
       
   240 	private TraceHeader header;
       
   241 
       
   242 	/**
       
   243 	 * Output stream for the header
       
   244 	 */
       
   245 	private OutputStream headerOutput;
       
   246 
       
   247 	/**
       
   248 	 * Temporary flag that specifies if a trace requires a trace buffer or it
       
   249 	 * can be represented by the default trace macros
       
   250 	 */
       
   251 	private boolean buildTraceBuffer;
       
   252 
       
   253 	/**
       
   254 	 * Temporary variable for fixed size
       
   255 	 */
       
   256 	private int fixedBufferSize;
       
   257 
       
   258 	/**
       
   259 	 * Dynamic size flag
       
   260 	 */
       
   261 	private boolean dynamicBufferSizeFlag;
       
   262 
       
   263 	/**
       
   264 	 * Flag which is set it trace needs #endif for __KERNEL_MODE__
       
   265 	 */
       
   266 	private boolean needsKernelEndif;
       
   267 
       
   268 	/**
       
   269 	 * Used via HeaderTemplateElementType.FORMATTED_TRACE
       
   270 	 */
       
   271 	private String currentTraceFormatted;
       
   272 
       
   273 	/**
       
   274 	 * Type of current parameter
       
   275 	 */
       
   276 	private String currentParameterType;
       
   277 
       
   278 	/**
       
   279 	 * Name of current parameter
       
   280 	 */
       
   281 	private String currentParameterName;
       
   282 
       
   283 	/**
       
   284 	 * Index of current parameter
       
   285 	 */
       
   286 	private int currentParameterIndex;
       
   287 
       
   288 	/**
       
   289 	 * Number of opened brackets
       
   290 	 */
       
   291 	private int openBraceCount;
       
   292 
       
   293 	/**
       
   294 	 * Trace being processed
       
   295 	 */
       
   296 	private Trace currentTrace;
       
   297 
       
   298 	/**
       
   299 	 * Parameter being processed
       
   300 	 */
       
   301 	private TraceParameter currentParameter;
       
   302 
       
   303 	/**
       
   304 	 * List of trace functions already in the header
       
   305 	 */
       
   306 	private ArrayList<String> traceDeclarations = new ArrayList<String>();
       
   307 
       
   308 	/**
       
   309 	 * Number of sequential new lines
       
   310 	 */
       
   311 	private int newLineCount;
       
   312 
       
   313 	/**
       
   314 	 * Number of allowed sequential new lines
       
   315 	 */
       
   316 	private int maxNewLines;
       
   317 
       
   318 	/**
       
   319 	 * Indicates that writing a function to the header file is going
       
   320 	 */
       
   321 	private boolean firstOpenBraceFound;
       
   322 	
       
   323 	/**
       
   324 	 * boolean indication that we are buffering a function text
       
   325 	 */
       
   326 	private boolean bufferingFunction;
       
   327 
       
   328 	/**
       
   329 	 * While writing a function to the header file, it's gathered to this
       
   330 	 * member. The member is then checked if the function parameters contain
       
   331 	 * TInt or TUint values. If so, the function is replicated so that TInt is
       
   332 	 * replaced by TInt32 and TUint with TUint32.
       
   333 	 */
       
   334 	private StringBuilder functionText = new StringBuilder();
       
   335 
       
   336 	/**
       
   337 	 * Number of brackets seen when writing a function. When it gets to 0, the
       
   338 	 * function in previousFunction variable is complete and can be written.
       
   339 	 */
       
   340 	private int numberOfBrackets;
       
   341 		
       
   342 	/**
       
   343 	 * string to hold the function guard
       
   344 	 */
       
   345 	private String ostTraceGenxFunGuard;
       
   346 
       
   347 	/**
       
   348 	 * Creates a new header writer
       
   349 	 * 
       
   350 	 * @param header
       
   351 	 *            the header to be written
       
   352 	 */
       
   353 	TraceHeaderWriter(TraceHeader header) {
       
   354 		this.header = header;
       
   355 	}
       
   356 
       
   357 	/**
       
   358 	 * Writes the header
       
   359 	 * 
       
   360 	 * @return true if header was written, false if it matched the existing
       
   361 	 *         header
       
   362 	 * @throws TraceCompilerException
       
   363 	 *             if writing fails
       
   364 	 */
       
   365 	boolean write() throws TraceCompilerException {
       
   366 		boolean headerWritten = false;
       
   367 		try {
       
   368 			openBraceCount = 0;
       
   369 			createHeader();
       
   370 			writeTemplate(HeaderTemplate.HEADER_TEMPLATE);
       
   371 			headerWritten = closeHeader();
       
   372 		} catch (IOException e) {
       
   373 			e.printStackTrace();
       
   374 			throw new TraceCompilerException(
       
   375 					TraceCompilerErrorCode.CANNOT_WRITE_PROJECT_FILE, e);
       
   376 		} finally {
       
   377 			traceDeclarations.clear();
       
   378 			if (headerOutput != null) {
       
   379 				try {
       
   380 					headerOutput.close();
       
   381 				} catch (IOException e) {
       
   382 				}
       
   383 			}
       
   384 			headerOutput = null;
       
   385 		}
       
   386 		return headerWritten;
       
   387 	}
       
   388 
       
   389 	/**
       
   390 	 * Creates the header file
       
   391 	 * 
       
   392 	 * @throws IOException
       
   393 	 *             if creation fails
       
   394 	 */
       
   395 	private void createHeader() throws IOException {
       
   396 		File file = new File(header.getAbsolutePath());
       
   397 		if (file.exists()) {
       
   398 			// If header exists, data is written to a byte array and compared
       
   399 			// with existing file. If they are the same, the file is not
       
   400 			// updated.
       
   401 			headerOutput = new FileCompareOutputStream(file);
       
   402 		} else {
       
   403 			// If header does not exist, the data is written directly to file
       
   404 			headerOutput = FileUtils.createOutputStream(file);
       
   405 		}
       
   406 	}
       
   407 
       
   408 	/**
       
   409 	 * Closes the header file. If data was written to a byte buffer this
       
   410 	 * compares the contents of the buffer with the existing file and re-writes
       
   411 	 * the file if contents do not match.
       
   412 	 * 
       
   413 	 * @return true if header was written, false if it matched the existing
       
   414 	 *         header
       
   415 	 * @throws IOException
       
   416 	 *             if closing fails
       
   417 	 */
       
   418 	private boolean closeHeader() throws IOException {
       
   419 		boolean headerWritten = true;
       
   420 		if (headerOutput instanceof FileCompareOutputStream) {
       
   421 			headerWritten = ((FileCompareOutputStream) headerOutput)
       
   422 					.writeFile();
       
   423 		}
       
   424 		headerOutput.close();
       
   425 		headerOutput = null;
       
   426 		return headerWritten;
       
   427 	}
       
   428 
       
   429 	/**
       
   430 	 * Writes a template to the stream
       
   431 	 * 
       
   432 	 * @param template
       
   433 	 *            the template
       
   434 	 * @throws IOException
       
   435 	 *             if writing fails
       
   436 	 */
       
   437 	void writeTemplate(Object[] template) throws IOException {
       
   438 		for (Object o : template) {
       
   439 			if (o instanceof String) {
       
   440 				write((String) o);
       
   441 			} else if (o instanceof TraceHeaderContributionType) {
       
   442 				writeHeaderContributions((TraceHeaderContributionType) o);
       
   443 			} else if (o instanceof HeaderTemplateElementType) {
       
   444 				writeTemplateElement((HeaderTemplateElementType) o);
       
   445 			} else if (o instanceof Object[]) {
       
   446 				// Template within template
       
   447 				writeTemplate((Object[]) o);
       
   448 			} else if (o instanceof TemplateChoice) {
       
   449 				TemplateChoice choice = (TemplateChoice) o;
       
   450 				// Gets the array index from template
       
   451 				Class<? extends TemplateCheckBase> c = choice.getChoiceClass();
       
   452 				try {
       
   453 					// Creates a switch-case object based on array index
       
   454 					TemplateCheckBase check = c.newInstance();
       
   455 					check.setWriter(this);
       
   456 					// Gets the case from the switch-case object and uses it to
       
   457 					// get the correct template
       
   458 					if (check.check()) {
       
   459 						writeTemplate(choice.getTrueTemplate());
       
   460 					} else {
       
   461 						writeTemplate(choice.getFalseTemplate());
       
   462 					}
       
   463 				} catch (InstantiationException e) {
       
   464 				} catch (IllegalAccessException e) {
       
   465 				}
       
   466 			} else if (o instanceof TemplateIterator) {
       
   467 				Class<? extends TemplateIteratorEntry> c = ((TemplateIterator) o)
       
   468 						.getIteratorClass();
       
   469 				try {
       
   470 					// Creates an iterator object based on array index
       
   471 					TemplateIteratorEntry itr = c.newInstance();
       
   472 					itr.setWriter(this);
       
   473 					itr.iterate(((TemplateIterator) o).getTemplate());
       
   474 				} catch (InstantiationException e) {
       
   475 				} catch (IllegalAccessException e) {
       
   476 				}
       
   477 			} else if (o instanceof SetNewLineCount) {
       
   478 				maxNewLines = ((SetNewLineCount) o).getLineCount();
       
   479 			} else if (o instanceof TraceFormatType) {
       
   480 				// Stores the formatted trace, but does not write anything
       
   481 				// HeaderTemplateElementType.FORMATTED_TRACE writes the trace
       
   482 				currentTraceFormatted = SourceFormatter.formatTrace(
       
   483 						currentTrace, (TraceFormatType) o);
       
   484 			}
       
   485 		}
       
   486 	}
       
   487 
       
   488 	/**
       
   489 	 * Writes an element from the HeaderTemplateElementType enumeration
       
   490 	 * 
       
   491 	 * @param type
       
   492 	 *            the element type
       
   493 	 * @throws IOException
       
   494 	 *             if writing fails
       
   495 	 */
       
   496 	private void writeTemplateElement(HeaderTemplateElementType type)
       
   497 			throws IOException { // CodForChk_Dis_ComplexFunc
       
   498 		switch (type) {
       
   499 		case NEW_LINE:
       
   500 			writeNewLine();
       
   501 			break;
       
   502 		case OPEN_BRACE:
       
   503 			writeOpenBrace();
       
   504 			break;
       
   505 		case CLOSE_BRACE:
       
   506 			writeCloseBrace();
       
   507 			break;
       
   508 		case PARAMETER_INDEX:
       
   509 			write(String.valueOf(currentParameterIndex));
       
   510 			break;
       
   511 		case PARAMETER_TYPE:
       
   512 			write(currentParameterType);
       
   513 			break;
       
   514 		case PARAMETER_NAME:
       
   515 			write(currentParameterName);
       
   516 			break;
       
   517 		case FORMATTED_TRACE:
       
   518 			writeFormattedTrace(currentTraceFormatted);
       
   519 			break;
       
   520 		case TRACE_NAME:
       
   521 			write(currentTrace.getName());
       
   522 			break;
       
   523 		case TRACE_ID_HEX:
       
   524 			writeTraceID();
       
   525 			break;
       
   526 		case FIXED_BUFFER_SIZE:
       
   527 			write(String.valueOf(fixedBufferSize));
       
   528 			break;
       
   529 		case TRACE_FUNCTION_BODY:
       
   530 			writeFunctionBody(currentTrace);
       
   531 			break;
       
   532 		case TRACE_FUNCTION_PARAMETERS:
       
   533 			writeParameter(currentParameter);
       
   534 			break;
       
   535 		case BUILD_TRACE_BUFFER_CHECK:
       
   536 			buildTraceBuffer = traceNeedsBuffer(currentTrace);
       
   537 			break;
       
   538 		case HEADER_GUARD:
       
   539 			write(SourceUtils.createHeaderGuard(header.getFileName()));
       
   540 			break;
       
   541 		case TRACE_COMPILER_VERSION:
       
   542 			write(TraceCompilerVersion.getVersion());
       
   543 			break;
       
   544 		case CLOSE_EXTRA_BRACES:
       
   545 			while (openBraceCount > 1) {
       
   546 				writeCloseBrace();
       
   547 			}
       
   548 			break;
       
   549 		case LICENCE_TEXT:
       
   550 		    writeLicence();
       
   551 		    break;
       
   552 		}
       
   553 	}
       
   554 
       
   555 	/**
       
   556 	 * Writes the trace ID to header
       
   557 	 * 
       
   558 	 * @throws IOException
       
   559 	 *             if writing fails
       
   560 	 */
       
   561 	private void writeTraceID() throws IOException {
       
   562 		int gid = currentTrace.getGroup().getID() << GROUP_SHIFT;
       
   563 		write(Integer.toHexString(gid | currentTrace.getID()));
       
   564 		ComplexHeaderRule rule = currentTrace
       
   565 				.getExtension(ComplexHeaderRule.class);
       
   566 		if (rule != null) {
       
   567 			String ext = rule.getTraceIDDefineExtension();
       
   568 			if (ext != null) {
       
   569 				write(ext);
       
   570 			}
       
   571 		}
       
   572 	}
       
   573 
       
   574 	/**
       
   575 	 * Writes the header contributions from plug-in's
       
   576 	 * 
       
   577 	 * @param type
       
   578 	 *            the contribution type
       
   579 	 * @throws IOException
       
   580 	 *             if writing fails
       
   581 	 */
       
   582 	private void writeHeaderContributions(TraceHeaderContributionType type)
       
   583 			throws IOException {
       
   584 		Iterator<String> contributions = getContributions(type);
       
   585 		boolean written = false;
       
   586 		while (contributions.hasNext()) {
       
   587 			writeContribution(contributions.next(), type);
       
   588 			written = true;
       
   589 		}
       
   590 		if (written) {
       
   591 			writeNewLine();
       
   592 		}
       
   593 	}
       
   594 
       
   595 	/**
       
   596 	 * Gets a list of contributions from plug-in's
       
   597 	 * 
       
   598 	 * @param type
       
   599 	 *            the contribution type
       
   600 	 * @return the contributions
       
   601 	 */
       
   602 	private Iterator<String> getContributions(TraceHeaderContributionType type) {
       
   603 		Iterator<TraceHeaderContribution> contributions = header.getOwner()
       
   604 				.getExtensions(TraceHeaderContribution.class);
       
   605 		ArrayList<String> list = new ArrayList<String>();
       
   606 		while (contributions.hasNext()) {
       
   607 			String[] s = contributions.next().getContribution(type);
       
   608 			if (s != null) {
       
   609 				for (String element : s) {
       
   610 					list.add(element);
       
   611 				}
       
   612 			}
       
   613 		}
       
   614 		return list.iterator();
       
   615 	}
       
   616 
       
   617 	/**
       
   618 	 * Writes a contribution to the stream
       
   619 	 * 
       
   620 	 * @param contribution
       
   621 	 *            the contribution
       
   622 	 * @param type
       
   623 	 *            the contribution type
       
   624 	 * @throws IOException
       
   625 	 *             if writing fails
       
   626 	 */
       
   627 	private void writeContribution(String contribution,
       
   628 			TraceHeaderContributionType type) throws IOException {
       
   629 		switch (type) {
       
   630 		case GLOBAL_DEFINES:
       
   631 			writeDefine(contribution);
       
   632 			break;
       
   633 		case GLOBAL_INCLUDES:
       
   634 			writeSystemInclude(contribution);
       
   635 			break;
       
   636 		case MAIN_HEADER_CONTENT:
       
   637 			// Handled by HeaderEngine
       
   638 			break;
       
   639 		}
       
   640 	}
       
   641 	
       
   642 	/**
       
   643 	 * write start of function guard
       
   644 	 * @throws IOException
       
   645 	 */
       
   646 	private void writeStartFunctionGuard() throws IOException {
       
   647 		Pattern p = Pattern.compile("inline\\s+TBool\\s+([^\\(]+)\\s*\\((.*)\\)\\s*\\{"); //$NON-NLS-1$
       
   648 		String guard = null;
       
   649 		String functionName = null;
       
   650 		
       
   651 		// Get the function definition line
       
   652 		int startIndex = functionText.indexOf(SourceConstants.OPENING_BRACE) + 1;
       
   653 		String funcDef = functionText.substring(0, startIndex);
       
   654 		
       
   655 		Matcher m = p.matcher(funcDef);
       
   656 		if (m.matches()) {
       
   657 			//get function name
       
   658 			functionName = m.group(1);
       
   659 			if (functionName == null || functionName.length() == 0) {
       
   660 				throw new IOException(Messages.getString("TraceHeader.internalError1")); //$NON-NLS-1$
       
   661 			}
       
   662 			//get raw parameters
       
   663 			String parameters = m.group(2);
       
   664 			if (parameters == null || parameters.length() == 0) {//there must be at least TraceID
       
   665 				throw new IOException(Messages.getString("TraceHeader.internalError2")); //$NON-NLS-1$
       
   666 			}
       
   667 			
       
   668 			functionName = functionName.trim();
       
   669 			parameters = parameters.trim();
       
   670 			//remove parameters names
       
   671 			guard = parameters.replaceAll("(\\S+,)|(\\S+\\s*$)", ""); //$NON-NLS-1$ //$NON-NLS-2$
       
   672 			//replace repeated spaces by one space
       
   673 			guard = guard.replaceAll("\\s+", SourceConstants.SPACE).trim(); //$NON-NLS-1$
       
   674 			//replace space by underscore
       
   675 			guard = guard.replace(SourceConstants.SPACE, SourceConstants.UNDERSCORE);
       
   676 			//replace ampersant by REF
       
   677 			guard = guard.replace(AMPERSANT, REF);
       
   678 			//replace ( by OBR
       
   679 			guard = guard.replace(OPEN_BRACKET, BEGINCAST);
       
   680 			//replace ) by CBR
       
   681 			guard = guard.replace(CLOSING_BRACKET, ENDCAST);
       
   682 		} else {
       
   683 			throw new IOException(Messages.getString("TraceHeader.internalError3")); //$NON-NLS-1$
       
   684 		}
       
   685 		
       
   686 		guard = SourceConstants.DOUBLE_UNDERSCORE 
       
   687 				+ functionName.toUpperCase()
       
   688 				+ SourceConstants.UNDERSCORE
       
   689 				+ guard.toUpperCase()
       
   690 				+ SourceConstants.DOUBLE_UNDERSCORE;
       
   691 		
       
   692 		ostTraceGenxFunGuard = guard;
       
   693 		write( SourceConstants.IFNDEF + SourceConstants.SPACE_CHAR + ostTraceGenxFunGuard);
       
   694 		write(SourceConstants.LINE_FEED);
       
   695 		write( SourceConstants.DEFINE +SourceConstants.SPACE_CHAR + ostTraceGenxFunGuard);
       
   696 		write(SourceConstants.LINE_FEED);
       
   697 		write(SourceConstants.LINE_FEED);
       
   698 	}
       
   699 
       
   700 	/**
       
   701 	 * write end of function guard
       
   702 	 * @throws IOException
       
   703 	 */
       
   704 	private void writeEndFunctionGuard() throws IOException {
       
   705 		if (ostTraceGenxFunGuard != null) {
       
   706 			write(SourceConstants.LINE_FEED);
       
   707 			write(SourceConstants.LINE_FEED);
       
   708 			write(SourceConstants.ENDIF 
       
   709 					+ SourceConstants.SPACE_CHAR
       
   710 					+ SourceConstants.FORWARD_SLASH_CHAR
       
   711 					+ SourceConstants.FORWARD_SLASH_CHAR
       
   712 					+ SourceConstants.SPACE_CHAR
       
   713 					+ ostTraceGenxFunGuard);
       
   714 			write(SourceConstants.LINE_FEED);
       
   715 		}
       
   716 	}
       
   717 	/**
       
   718 	 * Writes the function body to the stream
       
   719 	 * 
       
   720 	 * @param trace
       
   721 	 *            the trace to be written
       
   722 	 * @throws IOException
       
   723 	 *             if writing fails
       
   724 	 */
       
   725 	private void writeFunctionBody(Trace trace) throws IOException {
       
   726 		writeTraceBufferAllocation(trace);
       
   727 		writeTemplate(HeaderTemplate.PARAMETERS_TEMPLATE);
       
   728 		// If buffer is not used (single descriptor parameter), trace line is
       
   729 		// already written in template
       
   730 		if (isTraceBufferBuilt()) {
       
   731 			writeTraceLine(trace);
       
   732 		}
       
   733 	}
       
   734 
       
   735 	/**
       
   736 	 * Writes trace buffer allocation code to the function
       
   737 	 * 
       
   738 	 * @param trace
       
   739 	 *            the trace to be written
       
   740 	 * @throws IOException
       
   741 	 *             if writing fails
       
   742 	 */
       
   743 	private void writeTraceBufferAllocation(Trace trace) throws IOException {
       
   744 		// If buffer is not used (single descriptor parameter), this function
       
   745 		// does nothing
       
   746 		if (isTraceBufferBuilt()) {
       
   747 			Iterator<TraceParameter> parameters = trace.getParameters();
       
   748 			lenghtVariableDefined = false;
       
   749 			int fixedSizeParametersTotalSize = 0;
       
   750 			while (parameters.hasNext()) {
       
   751 				TraceParameter parameter = parameters.next();
       
   752 				TraceParameterFormattingRule sourceRule = parameter
       
   753 						.getExtension(TraceParameterFormattingRule.class);
       
   754 				if (sourceRule == null || sourceRule.isShownInSource()
       
   755 						|| sourceRule instanceof FillerParameterRule) {
       
   756 					// Fillers do not increment parameter index
       
   757 					if (!(sourceRule instanceof FillerParameterRule)) {
       
   758 						currentParameterIndex++;
       
   759 					}
       
   760 					int paramSize = SourceUtils
       
   761 							.mapParameterTypeToSize(parameter);
       
   762 					// calculateParameterSize returns 0 for dynamic parameters,
       
   763 					// but 4 extra bytes need to be reserved for the length
       
   764 					if (paramSize == 0) {
       
   765 						paramSize = BYTES_IN_PARAMETER;
       
   766 					}
       
   767 					fixedBufferSize += paramSize;
       
   768 					fixedSizeParametersTotalSize += paramSize;
       
   769 					if (SourceUtils.isParameterSizeDynamic(parameter)) {
       
   770 
       
   771 						// Define length variable only once
       
   772 						if (lenghtVariableDefined == false) {
       
   773 							writeTemplate(HeaderTemplate.LENGTH_VARIABLE_DEFINITION_TEMPLATE);
       
   774 							lenghtVariableDefined = true;
       
   775 						}
       
   776 
       
   777 						// Increase length variable if needed
       
   778 						// This is needed in case that there has been fixed size
       
   779 						// parameter
       
   780 						// before dynamic parameter
       
   781 						if (fixedSizeParametersTotalSize - paramSize > 0) {
       
   782 							fixedSizeParametersTotalSize -= paramSize;
       
   783 							writeTemplate(HeaderTemplate.LENGTH_VARIABLE_INCREASE_TEMPLATE_BEGIN);
       
   784 							write(String.valueOf(fixedSizeParametersTotalSize));
       
   785 							writeTemplate(HeaderTemplate.LENGTH_VARIABLE_INCREASE_TEMPLATE_END);
       
   786 						}
       
   787 
       
   788 						fixedSizeParametersTotalSize = 0;
       
   789 
       
   790 						writeTemplate(HeaderTemplate.DYNAMIC_PARAMETER_LENGTH_TEMPLATE);
       
   791 						dynamicBufferSizeFlag = true;
       
   792 					}
       
   793 				}
       
   794 			}
       
   795 			writeTemplate(HeaderTemplate.BUFFER_ALLOCATION_TEMPLATE);
       
   796 			currentParameterIndex = 0;
       
   797 		}
       
   798 	}
       
   799 
       
   800 	/**
       
   801 	 * Writes the given parameter to the header
       
   802 	 * 
       
   803 	 * @param parameter
       
   804 	 *            the parameter
       
   805 	 * @throws IOException
       
   806 	 *             if writing fails
       
   807 	 */
       
   808 	void writeParameter(TraceParameter parameter) throws IOException {
       
   809 		TraceParameterFormattingRule sourceRule = parameter
       
   810 				.getExtension(TraceParameterFormattingRule.class);
       
   811 		if (sourceRule == null || sourceRule.isShownInSource()
       
   812 				|| sourceRule instanceof FillerParameterRule) {
       
   813 			String paramType = SourceUtils
       
   814 					.mapParameterTypeToSymbianType(parameter);
       
   815 			if (SourceUtils.isParameterSizeDynamic(parameter)) {
       
   816 				currentParameterIndex++;
       
   817 				currentParameterName = SymbianConstants.PARAMETER_DECLARATION_PREFIX
       
   818 						+ currentParameterIndex;
       
   819 				writeTemplate(HeaderTemplate.DYNAMIC_PARAMETER_TEMPLATE);
       
   820 			} else {
       
   821 				currentParameterType = paramType;
       
   822 				if (sourceRule instanceof FillerParameterRule) {
       
   823 					currentParameterName = "0"; //$NON-NLS-1$
       
   824 					writeTemplate(HeaderTemplate.FIXED_PARAMETER_TEMPLATE);
       
   825 				} else {
       
   826 					currentParameterIndex++;
       
   827 					currentParameterName = SymbianConstants.PARAMETER_DECLARATION_PREFIX
       
   828 							+ currentParameterIndex;
       
   829 					if (lenghtVariableDefined == true) {
       
   830 						writeTemplate(HeaderTemplate.FIXED_PARAMETER_TEMPLATE_WITH_LENGTH_CHECK);
       
   831 					} else {
       
   832 						writeTemplate(HeaderTemplate.FIXED_PARAMETER_TEMPLATE);
       
   833 					}
       
   834 				}
       
   835 			}
       
   836 		}
       
   837 	}
       
   838 
       
   839 	/**
       
   840 	 * Writes the trace line to the function
       
   841 	 * 
       
   842 	 * @param trace
       
   843 	 *            the trace to be written
       
   844 	 * @throws IOException
       
   845 	 *             if writing fails
       
   846 	 */
       
   847 	private void writeTraceLine(Trace trace) throws IOException {
       
   848 		StringBuffer sb;
       
   849 		StringBuffer bufferData = new StringBuffer();
       
   850 		StringBuffer lengthData = new StringBuffer();
       
   851 		if (isBufferSizeDynamic()) {
       
   852 			sb = writeBufferedTraceLine(trace, bufferData, lengthData);
       
   853 		} else {
       
   854 			// If buffer size is 4, the buffer can be traced using the
       
   855 			// the 32-bit parameter trace macro instead of data macro
       
   856 			if (fixedBufferSize / BYTES_IN_PARAMETER == 1) {
       
   857 				sb = writePackedTraceLine(trace, bufferData);
       
   858 			} else {
       
   859 				sb = writeBufferedTraceLine(trace, bufferData, lengthData);
       
   860 			}
       
   861 		}
       
   862 		int index = sb.indexOf(TraceFormatConstants.DATA_BUFFER_FORMAT);
       
   863 		if (index >= 0) {
       
   864 			sb.replace(index, index
       
   865 					+ TraceFormatConstants.DATA_BUFFER_FORMAT.length(),
       
   866 					bufferData.toString());
       
   867 		}
       
   868 		index = sb.indexOf(TraceFormatConstants.DATA_LENGTH_FORMAT);
       
   869 		if (index >= 0) {
       
   870 			sb.replace(index, index
       
   871 					+ TraceFormatConstants.DATA_LENGTH_FORMAT.length(),
       
   872 					lengthData.toString());
       
   873 		}
       
   874 		String s = sb.toString();
       
   875 		write("retval = "); //$NON-NLS-1$
       
   876 		writeFormattedTrace(s);
       
   877 		writeNewLine();
       
   878 	}
       
   879 
       
   880 	/**
       
   881 	 * Writes a trace line when the parameters can be fitted into a direct API
       
   882 	 * call
       
   883 	 * 
       
   884 	 * @param trace
       
   885 	 *            the trace
       
   886 	 * @param bufferData
       
   887 	 *            the buffer
       
   888 	 * @return formatted trace
       
   889 	 */
       
   890 	private StringBuffer writePackedTraceLine(Trace trace,
       
   891 			StringBuffer bufferData) {
       
   892 		StringBuffer sb;
       
   893 		// The formatting rule is used to get the API macro
       
   894 		sb = new StringBuffer(SourceFormatter.formatTrace(trace,
       
   895 				TraceFormatType.TRACE_PACKED));
       
   896 		TraceFormattingRule rule = trace
       
   897 				.getExtension(TraceFormattingRule.class);
       
   898 		if (rule == null) {
       
   899 			rule = trace.getModel().getExtension(TraceFormattingRule.class);
       
   900 		}
       
   901 		int index = sb.indexOf(TraceFormatConstants.PARAM_COUNT_FORMAT);
       
   902 		if (index >= 0) {
       
   903 			// Single parameter is supported
       
   904 			sb.replace(index, index
       
   905 					+ TraceFormatConstants.PARAM_COUNT_FORMAT.length(), rule
       
   906 					.mapParameterCountToSource(trace, 1));
       
   907 		}
       
   908 		bufferData.append("*( ( TUint32* )ptr )"); //$NON-NLS-1$
       
   909 		return sb;
       
   910 	}
       
   911 
       
   912 	/**
       
   913 	 * Writes a trace line when the trace contains more data that the API
       
   914 	 * supports
       
   915 	 * 
       
   916 	 * @param trace
       
   917 	 *            the trace
       
   918 	 * @param bufferData
       
   919 	 *            the trace buffer
       
   920 	 * @param lengthData
       
   921 	 *            the trace length buffer
       
   922 	 * @return the formatted trace
       
   923 	 */
       
   924 	private StringBuffer writeBufferedTraceLine(Trace trace,
       
   925 			StringBuffer bufferData, StringBuffer lengthData) {
       
   926 		StringBuffer sb;
       
   927 		// Buffer parameter
       
   928 		// *( ( TUint32* )ptr ), *( ( TUint32* )( ptr + 4 ) ), ..., ptr + x
       
   929 		sb = new StringBuffer(SourceFormatter.formatTrace(trace,
       
   930 				TraceFormatType.TRACE_BUFFER));
       
   931 		if (isTraceBufferBuilt()) {
       
   932 			bufferData.append("ptr"); //$NON-NLS-1$
       
   933 			if (isBufferSizeDynamic()) {
       
   934 				// In case of dynamic buffer, the length has been calculated
       
   935 				// into length variable
       
   936 				lengthData.append("length"); //$NON-NLS-1$
       
   937 			} else {
       
   938 				// Fixed size case
       
   939 				lengthData.append(String.valueOf(fixedBufferSize));
       
   940 			}
       
   941 		} else {
       
   942 			// In case of no-buffer, the size variable contain the data size
       
   943 			bufferData.append("ptr"); //$NON-NLS-1$
       
   944 			lengthData.append("size"); //$NON-NLS-1$
       
   945 		}
       
   946 		return sb;
       
   947 	}
       
   948 
       
   949 	/**
       
   950 	 * Writes a formatted trace to the stream. This removes the newline from the
       
   951 	 * trace if it exists
       
   952 	 * 
       
   953 	 * @param trace
       
   954 	 *            the trace
       
   955 	 * @throws IOException
       
   956 	 *             if writing fails
       
   957 	 */
       
   958 	private void writeFormattedTrace(String trace) throws IOException {
       
   959 		if (trace.endsWith(SourceConstants.LINE_FEED)) {
       
   960 			write(trace.substring(0, trace.length()
       
   961 					- SourceConstants.LINE_FEED.length()));
       
   962 		} else {
       
   963 			write(trace);
       
   964 		}
       
   965 	}
       
   966 
       
   967 	/**
       
   968 	 * Increases indent and writes a new line, brace, new line combination
       
   969 	 * 
       
   970 	 * @throws IOException
       
   971 	 *             if writing fails
       
   972 	 */
       
   973 	private void writeOpenBrace() throws IOException {
       
   974 		openBraceCount++;
       
   975 		writeNewLine();
       
   976 		write(SourceConstants.OPENING_BRACE);
       
   977 		writeNewLine();
       
   978 	}
       
   979 
       
   980 	/**
       
   981 	 * Write brace, decreases indent and writes a new line
       
   982 	 * 
       
   983 	 * @throws IOException
       
   984 	 *             if writing fails
       
   985 	 */
       
   986 	private void writeCloseBrace() throws IOException {
       
   987 		write(SourceConstants.CLOSING_BRACE);
       
   988 		openBraceCount--;
       
   989 		writeNewLine();
       
   990 	}
       
   991 	
       
   992 	/**
       
   993 	 * write licence Text
       
   994 	 * @throws IOException if write fails
       
   995 	 */
       
   996 	private void writeLicence() throws IOException {
       
   997 		String licence = null;
       
   998 		SourceParser parser = null;
       
   999 		//first get any of the traces belonging to this header
       
  1000 		TraceModel model = header.getOwner().getModel();
       
  1001 		for (TraceGroup group : model) {
       
  1002 			for (Trace trace : group) {
       
  1003 				Iterator<LocationListBase> itr = trace.getExtensions(LocationListBase.class);
       
  1004 				// The trace must have at least one location that belong to this header
       
  1005 				while (itr.hasNext() && parser == null) {
       
  1006 					LocationListBase list = itr.next();
       
  1007 					for (LocationProperties loc : list) {
       
  1008 						if (isValidTraceForHeader(loc.getFileName())) {
       
  1009 								parser = ((TraceLocation)loc).getParser();
       
  1010 								break;
       
  1011 						}
       
  1012 					}
       
  1013 				}
       
  1014 				if (parser!= null)  {
       
  1015 					break;
       
  1016 				}
       
  1017 			}
       
  1018 			if (parser != null) {
       
  1019 				break;
       
  1020 			}
       
  1021 		}
       
  1022 		
       
  1023 		if (parser!= null) {
       
  1024 		List<SourceExcludedArea> excludedAreas = parser.getExcludedAreas();
       
  1025 		//try to find licence from the source
       
  1026 		if (!excludedAreas.isEmpty()) {
       
  1027 			SourceExcludedArea sourceExcludedArea = excludedAreas.get(0);
       
  1028 			int offset = sourceExcludedArea.getOffset();
       
  1029 			int type = sourceExcludedArea.getType();
       
  1030 			int length = sourceExcludedArea.getLength();
       
  1031 			if (offset == 0 && type == SourceExcludedArea.MULTILINE_COMMENT) {
       
  1032 				String data = sourceExcludedArea.getParser().getData(offset, length);
       
  1033 				if (data.contains("Copyright")) { //$NON-NLS-1$
       
  1034 					// licence found write it
       
  1035 					TraceCompilerLogger.printInfo("Add Licence text from: " + sourceExcludedArea.getFileName() + " to : " + header.getAbsolutePath()); //$NON-NLS-1$
       
  1036 					licence = data;
       
  1037 					write(licence);
       
  1038 				}
       
  1039 			}	
       
  1040 		}
       
  1041 		}
       
  1042 		
       
  1043 		if (licence == null) {
       
  1044 			//get default licence from the licence file
       
  1045 			licence = TraceCompilerEngineGlobals.getDefaultLicence(true);
       
  1046 			
       
  1047 			if(licence != null) {
       
  1048 				TraceCompilerLogger.printInfo("Add default EPL Licence to : " + header.getAbsolutePath()); //$NON-NLS-1$
       
  1049 				write(licence);
       
  1050 			}
       
  1051 		}
       
  1052 	}
       
  1053 
       
  1054 	/**
       
  1055 	 * Writes a new line and indent to the stream
       
  1056 	 * 
       
  1057 	 * @throws IOException
       
  1058 	 *             if writing fails
       
  1059 	 */
       
  1060 	private void writeNewLine() throws IOException {
       
  1061 		int newLines = newLineCount;
       
  1062 		while (newLines < maxNewLines) {
       
  1063 			write(SourceConstants.LINE_FEED);
       
  1064 			for (int i = 0; i < openBraceCount; i++) {
       
  1065 				write(INDENT);
       
  1066 			}
       
  1067 			newLines++;
       
  1068 		}
       
  1069 		newLineCount = maxNewLines;
       
  1070 	}
       
  1071 
       
  1072 	/**
       
  1073 	 * Writes a define to stream
       
  1074 	 * 
       
  1075 	 * @param name
       
  1076 	 *            the name for the define
       
  1077 	 * @throws IOException
       
  1078 	 *             if writing fails
       
  1079 	 */
       
  1080 	private void writeDefine(String name) throws IOException {
       
  1081 		write(SourceConstants.DEFINE);
       
  1082 		write(SourceConstants.SPACE);
       
  1083 		write(name);
       
  1084 		writeNewLine();
       
  1085 	}
       
  1086 
       
  1087 	/**
       
  1088 	 * Writes include to header
       
  1089 	 * 
       
  1090 	 * @param name
       
  1091 	 *            the header name
       
  1092 	 * @throws IOException
       
  1093 	 *             if writing fails
       
  1094 	 */
       
  1095 	private void writeSystemInclude(String name) throws IOException {
       
  1096 		write(SourceConstants.INCLUDE);
       
  1097 		write(SourceConstants.SPACE);
       
  1098 		write("<"); //$NON-NLS-1$
       
  1099 		write(name);
       
  1100 		write(">"); //$NON-NLS-1$
       
  1101 		writeNewLine();
       
  1102 	}
       
  1103 
       
  1104 	/**
       
  1105 	 * Writes data to a stream
       
  1106 	 * 
       
  1107 	 * @param data
       
  1108 	 *            the string of data
       
  1109 	 * @throws IOException
       
  1110 	 *             if writing fails
       
  1111 	 */
       
  1112 	private void write(String data) throws IOException {
       
  1113 		// Check if function starts
       
  1114 		if (data.contains(INLINE_TBOOL) || bufferingFunction) {
       
  1115 			bufferingFunction = true;
       
  1116 			functionText.append(data);
       
  1117 		} else {
       
  1118 			headerOutput.write(data.getBytes());
       
  1119 		}
       
  1120 			newLineCount = 0;
       
  1121 
       
  1122 		//try to duplicate function if the current function processing is complete and duplicate is needed.
       
  1123 		writeAndDuplicateFunction(data);
       
  1124 	}
       
  1125 
       
  1126 	/**
       
  1127 	 * Duplicates the function if needed
       
  1128 	 * 
       
  1129 	 * @param data
       
  1130 	 *            data String
       
  1131 	 * @throws IOException
       
  1132 	 *             if writing fails
       
  1133 	 */
       
  1134 	private void writeAndDuplicateFunction(String data) throws IOException {
       
  1135 			// This assumes there is only one start or end bracket in one line!
       
  1136 			if (data.contains(SourceConstants.OPENING_BRACE)) {
       
  1137 				firstOpenBraceFound = true;
       
  1138 				numberOfBrackets++;
       
  1139 			} else if (data.contains(SourceConstants.CLOSING_BRACE)) {
       
  1140 				numberOfBrackets--;
       
  1141 
       
  1142 				// Function ends
       
  1143 				if (numberOfBrackets == 0 && firstOpenBraceFound) {
       
  1144 					firstOpenBraceFound = false;
       
  1145 					bufferingFunction = false;
       
  1146 					//write start function guard
       
  1147 					writeStartFunctionGuard();
       
  1148 					//write the function
       
  1149 					headerOutput.write(functionText.toString().getBytes());
       
  1150 					//write end function guard
       
  1151 					writeEndFunctionGuard();
       
  1152 
       
  1153 					//process duplicate if needed
       
  1154 					// Get the function definition line
       
  1155 					int startIndex = functionText.indexOf(SourceConstants.OPENING_BRACE);
       
  1156 					String funcDef = functionText.substring(0, startIndex);
       
  1157 
       
  1158 					// Replace TInt with TInt32 and TUint with TUint32 from the
       
  1159 					// header and write the function back again
       
  1160 					if (funcDef.contains(TINT_DEF)
       
  1161 							|| funcDef.contains(TUINT_DEF)) {
       
  1162 						//replace and duplicate
       
  1163 						funcDef = funcDef.replace(TINT_DEF, TINT32_DEF);
       
  1164 						funcDef = funcDef.replace(TUINT_DEF, TUINT32_DEF);
       
  1165 						functionText.replace(0, startIndex, funcDef);
       
  1166 						
       
  1167 						//write start function guard for duplicate
       
  1168 						write(SourceConstants.LINE_FEED);
       
  1169 						write(SourceConstants.LINE_FEED);
       
  1170 						writeStartFunctionGuard();
       
  1171 						
       
  1172 						//write duplicate function
       
  1173 						headerOutput.write(functionText.toString().getBytes());
       
  1174 						
       
  1175 						//write end function guard for duplicate
       
  1176 						writeEndFunctionGuard();
       
  1177 					}
       
  1178 
       
  1179 					functionText.setLength(0);
       
  1180 				}
       
  1181 			}
       
  1182 	}
       
  1183 
       
  1184 	/**
       
  1185 	 * Checks if a trace needs a buffer or it can be represented with regular
       
  1186 	 * trace macros.
       
  1187 	 * 
       
  1188 	 * @param trace
       
  1189 	 *            the trace
       
  1190 	 * @return true if trace needs a buffer
       
  1191 	 */
       
  1192 	private boolean traceNeedsBuffer(Trace trace) {
       
  1193 		// A single dynamic parameter can be passed through the regular
       
  1194 		// API macros. In that case the parameter length is determined
       
  1195 		// by the trace message length
       
  1196 		Iterator<TraceParameter> parameters = trace.getParameters();
       
  1197 		boolean needsBuffer = false;
       
  1198 		boolean dynamicFound = false;
       
  1199 		while (parameters.hasNext() && !needsBuffer) {
       
  1200 			TraceParameter parameter = parameters.next();
       
  1201 			if (isParameterVisible(parameter)) {
       
  1202 				if (SourceUtils.isParameterSizeDynamic(parameter)) {
       
  1203 					if (dynamicFound) {
       
  1204 						needsBuffer = true;
       
  1205 					} else {
       
  1206 						dynamicFound = true;
       
  1207 					}
       
  1208 				} else {
       
  1209 					needsBuffer = true;
       
  1210 				}
       
  1211 			}
       
  1212 		}
       
  1213 		return needsBuffer;
       
  1214 	}
       
  1215 
       
  1216 	/**
       
  1217 	 * Checks if a parameter is visible
       
  1218 	 * 
       
  1219 	 * @param parameter
       
  1220 	 *            the parameter to be checked
       
  1221 	 * @return true if visible, false if not
       
  1222 	 */
       
  1223 	private boolean isParameterVisible(TraceParameter parameter) {
       
  1224 		boolean retval;
       
  1225 		TraceParameterFormattingRule sourceRule = parameter
       
  1226 				.getExtension(TraceParameterFormattingRule.class);
       
  1227 		if (sourceRule == null || sourceRule.isShownInSource()) {
       
  1228 			retval = true;
       
  1229 		} else {
       
  1230 			retval = false;
       
  1231 		}
       
  1232 		return retval;
       
  1233 	}
       
  1234 
       
  1235 	/**
       
  1236 	 * Gets the formatted trace
       
  1237 	 * 
       
  1238 	 * @return the trace
       
  1239 	 */
       
  1240 	String getCurrentTraceFormatted() {
       
  1241 		return currentTraceFormatted;
       
  1242 	}
       
  1243 
       
  1244 	/**
       
  1245 	 * Checks if trace is already formatted to header
       
  1246 	 * 
       
  1247 	 * @return true if formatted
       
  1248 	 */
       
  1249 	boolean isTraceFormatDuplicate() {
       
  1250 		boolean retval;
       
  1251 		if (traceDeclarations.contains(currentTraceFormatted)) {
       
  1252 			retval = true;
       
  1253 		} else {
       
  1254 			traceDeclarations.add(currentTraceFormatted);
       
  1255 			retval = false;
       
  1256 		}
       
  1257 		return retval;
       
  1258 	}
       
  1259 
       
  1260 	/**
       
  1261 	 * Checks if the buffer size for current trace is fixed
       
  1262 	 * 
       
  1263 	 * @return the flag
       
  1264 	 */
       
  1265 	boolean isTraceBufferFixed() {
       
  1266 		return fixedBufferSize != 0;
       
  1267 	}
       
  1268 
       
  1269 	/**
       
  1270 	 * Checks if the buffer is built
       
  1271 	 * 
       
  1272 	 * @return the flag
       
  1273 	 */
       
  1274 	boolean isTraceBufferBuilt() {
       
  1275 		return buildTraceBuffer;
       
  1276 	}
       
  1277 
       
  1278 	/**
       
  1279 	 * Gets the current trace
       
  1280 	 * 
       
  1281 	 * @return the trace
       
  1282 	 */
       
  1283 	Trace getCurrentTrace() {
       
  1284 		return currentTrace;
       
  1285 	}
       
  1286 
       
  1287 	/**
       
  1288 	 * Gets the header
       
  1289 	 * 
       
  1290 	 * @return the header
       
  1291 	 */
       
  1292 	TraceHeader getHeader() {
       
  1293 		return header;
       
  1294 	}
       
  1295 
       
  1296 	/**
       
  1297 	 * Starts writing a trace
       
  1298 	 * 
       
  1299 	 * @param trace
       
  1300 	 *            the trace
       
  1301 	 * @return true if trace can be written, false if not
       
  1302 	 */
       
  1303 	boolean startTrace(Trace trace) {
       
  1304 		boolean validTrace = false;
       
  1305 		Iterator<LocationListBase> itr = trace
       
  1306 				.getExtensions(LocationListBase.class);
       
  1307 		// The trace must have at least one location that belong to this header
       
  1308 		while (itr.hasNext() && !validTrace) {
       
  1309 			LocationListBase list = itr.next();
       
  1310 			for (LocationProperties loc : list) {
       
  1311 				validTrace = isValidTraceForHeader(loc.getFileName());
       
  1312 				if (validTrace) {
       
  1313 					break;
       
  1314 				}
       
  1315 			}
       
  1316 		}
       
  1317 		if (validTrace) {
       
  1318 			currentTrace = trace;
       
  1319 			fixedBufferSize = 0;
       
  1320 			dynamicBufferSizeFlag = false;
       
  1321 			buildTraceBuffer = false;
       
  1322 			currentTraceFormatted = null;
       
  1323 			currentParameterName = null;
       
  1324 			currentParameterType = null;
       
  1325 			currentParameterIndex = 0;
       
  1326 		}
       
  1327 		return validTrace;
       
  1328 	}
       
  1329 
       
  1330 	/**
       
  1331 	 * Checks if the location belongs to this header
       
  1332 	 * 
       
  1333 	 * @param locFileName
       
  1334 	 *            the location
       
  1335 	 * @return true if location belongs here
       
  1336 	 */
       
  1337 	private boolean isValidTraceForHeader(String locFileName) {
       
  1338 		boolean valid = false;
       
  1339 		if (locFileName != null) {
       
  1340 			int index = locFileName.lastIndexOf('.');
       
  1341 			if (index >= 0) {
       
  1342 				locFileName = locFileName.substring(0, index);
       
  1343 			}
       
  1344 			if (locFileName.equals(header.getProjectName())) {
       
  1345 				valid = true;
       
  1346 			}
       
  1347 		}
       
  1348 		return valid;
       
  1349 	}
       
  1350 
       
  1351 	/**
       
  1352 	 * Starts writing a parameter
       
  1353 	 * 
       
  1354 	 * @param parameter
       
  1355 	 *            the parameter
       
  1356 	 */
       
  1357 	void startParameter(TraceParameter parameter) {
       
  1358 		currentParameterName = null;
       
  1359 		currentParameterType = null;
       
  1360 		currentParameter = parameter;
       
  1361 	}
       
  1362 
       
  1363 	/**
       
  1364 	 * Sets the kernel mode #endif needed flag
       
  1365 	 * 
       
  1366 	 * @param flag
       
  1367 	 *            the flag
       
  1368 	 */
       
  1369 	void setKernelModeEndifNeeded(boolean flag) {
       
  1370 		needsKernelEndif = flag;
       
  1371 	}
       
  1372 
       
  1373 	/**
       
  1374 	 * Gets the kernel mode endif needed flag
       
  1375 	 * 
       
  1376 	 * @return the flag
       
  1377 	 */
       
  1378 	boolean isKernelModeEndifNeeded() {
       
  1379 		return needsKernelEndif;
       
  1380 	}
       
  1381 
       
  1382 	/**
       
  1383 	 * Returns the dynamic buffer size flag
       
  1384 	 * 
       
  1385 	 * @return true if buffer size is dynamic
       
  1386 	 */
       
  1387 	boolean isBufferSizeDynamic() {
       
  1388 		return dynamicBufferSizeFlag;
       
  1389 	}
       
  1390 
       
  1391 	/**
       
  1392 	 * Checks if current parameter needs alignment
       
  1393 	 * 
       
  1394 	 * @return true if needed
       
  1395 	 */
       
  1396 	boolean isParameterAlignmentNeeded() {
       
  1397 		return SourceUtils.isParameterAlignementNeeded(currentParameter
       
  1398 				.getType());
       
  1399 	}
       
  1400 
       
  1401 }