tracefw/tracecompiler/src/com.nokia.tracecompiler/src/com/nokia/tracecompiler/engine/rules/osttrace/OstTraceParserRule.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) 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  * OST trace parser rule
       
    17  *
       
    18  */
       
    19 package com.nokia.tracecompiler.engine.rules.osttrace;
       
    20 
       
    21 import java.util.ArrayList;
       
    22 import java.util.List;
       
    23 
       
    24 import com.nokia.tracecompiler.engine.TraceLocation;
       
    25 import com.nokia.tracecompiler.engine.TraceCompilerEngineErrorCodes.TraceCompilerErrorCode;
       
    26 import com.nokia.tracecompiler.engine.rules.AutoAddFunctionParametersRule;
       
    27 import com.nokia.tracecompiler.engine.rules.AutoAddReturnParameterRule;
       
    28 import com.nokia.tracecompiler.engine.rules.AutoAddThisPtrRule;
       
    29 import com.nokia.tracecompiler.engine.rules.AutoAddValueRule;
       
    30 import com.nokia.tracecompiler.engine.rules.AutomaticTraceTextRule;
       
    31 import com.nokia.tracecompiler.engine.rules.ComplexHeaderRuleImpl;
       
    32 import com.nokia.tracecompiler.engine.rules.EntryTraceRule;
       
    33 import com.nokia.tracecompiler.engine.rules.ExitTraceRule;
       
    34 import com.nokia.tracecompiler.engine.rules.PerformanceEventStartRule;
       
    35 import com.nokia.tracecompiler.engine.rules.PerformanceEventStopRule;
       
    36 import com.nokia.tracecompiler.engine.rules.ReadOnlyObjectRuleImpl;
       
    37 import com.nokia.tracecompiler.engine.rules.SourceParserRuleBase;
       
    38 import com.nokia.tracecompiler.engine.rules.StateTraceRule;
       
    39 import com.nokia.tracecompiler.engine.source.SourceParserResult;
       
    40 import com.nokia.tracecompiler.model.TraceCompilerException;
       
    41 import com.nokia.tracecompiler.model.TraceModelExtension;
       
    42 import com.nokia.tracecompiler.model.TraceParameter;
       
    43 import com.nokia.tracecompiler.source.FormatMapping;
       
    44 import com.nokia.tracecompiler.source.SourceContext;
       
    45 import com.nokia.tracecompiler.source.SourceParser;
       
    46 
       
    47 /**
       
    48  * OST trace parser rule
       
    49  * 
       
    50  */
       
    51 public final class OstTraceParserRule extends SourceParserRuleBase {
       
    52 
       
    53 	/**
       
    54 	 * PERFORMANCE group name
       
    55 	 */
       
    56 	private static final String PERFORMANCE_GROUP_NAME = "TRACE_PERFORMANCE"; //$NON-NLS-1$
       
    57 
       
    58 	/**
       
    59 	 * STATE group name
       
    60 	 */
       
    61 	private static final String STATE_GROUP_NAME = "TRACE_STATE"; //$NON-NLS-1$
       
    62 
       
    63 	/**
       
    64 	 * FLOW group name
       
    65 	 */
       
    66 	private static final String FLOW_GROUP_NAME = "TRACE_FLOW"; //$NON-NLS-1$
       
    67 
       
    68 	/**
       
    69 	 * Data trace parameter count
       
    70 	 */
       
    71 	private static final int DATA_PARAMETER_COUNT = 2; // CodForChk_Dis_Magic
       
    72 
       
    73 	/**
       
    74 	 * Entry Ext trace parameter count
       
    75 	 */
       
    76 	private static final int ENTRY_EXT_PARAMETER_COUNT = 1; // CodForChk_Dis_Magic
       
    77 
       
    78 	/**
       
    79 	 * Exit Ext trace parameter count
       
    80 	 */
       
    81 	private static final int EXIT_EXT_PARAMETER_COUNT = 2; // CodForChk_Dis_Magic
       
    82 
       
    83 	/**
       
    84 	 * Trace parameter index list
       
    85 	 */
       
    86 	class TraceParameterIndexList {
       
    87 
       
    88 		/**
       
    89 		 * Minimum number of parameters needed to decode traces
       
    90 		 */
       
    91 		int minParamCount;
       
    92 
       
    93 		/**
       
    94 		 * Preprocessor level index
       
    95 		 */
       
    96 		int levelIndex;
       
    97 
       
    98 		/**
       
    99 		 * Trace name index
       
   100 		 */
       
   101 		int nameIndex;
       
   102 
       
   103 		/**
       
   104 		 * Trace text index
       
   105 		 */
       
   106 		int textIndex;
       
   107 
       
   108 		/**
       
   109 		 * Trace group index in case group name is free-form
       
   110 		 */
       
   111 		int groupIndex;
       
   112 
       
   113 		/**
       
   114 		 * Trace group name in case group name is pre-determined by rules
       
   115 		 */
       
   116 		String groupName;
       
   117 	}
       
   118 
       
   119 	/**
       
   120 	 * List of flags related to OST API macro
       
   121 	 */
       
   122 	class TraceParameterFlagList {
       
   123 
       
   124 		/**
       
   125 		 * Data tag
       
   126 		 */
       
   127 		boolean hasDataTag;
       
   128 
       
   129 		/**
       
   130 		 * State tag
       
   131 		 */
       
   132 		boolean hasStateTag;
       
   133 
       
   134 		/**
       
   135 		 * Ext tag
       
   136 		 */
       
   137 		boolean hasExtTag;
       
   138 
       
   139 		/**
       
   140 		 * Event start tag
       
   141 		 */
       
   142 		boolean hasEventStartTag;
       
   143 
       
   144 		/**
       
   145 		 * Event stop
       
   146 		 */
       
   147 		boolean hasEventStopTag;
       
   148 
       
   149 		/**
       
   150 		 * Function entry
       
   151 		 */
       
   152 		boolean hasFunctionEntryTag;
       
   153 
       
   154 		/**
       
   155 		 * Function exit
       
   156 		 */
       
   157 		boolean hasFunctionExitTag;
       
   158 
       
   159 		/**
       
   160 		 * Constructor
       
   161 		 * 
       
   162 		 * @param tag
       
   163 		 *            the trace tag
       
   164 		 */
       
   165 		TraceParameterFlagList(String tag) {
       
   166 			hasDataTag = tag.indexOf(OstConstants.DATA_TRACE_TAG) > 0;
       
   167 			hasStateTag = tag.indexOf(OstConstants.STATE_TRACE_TAG) > 0;
       
   168 			hasExtTag = tag.indexOf(OstConstants.EXTENSION_TRACE_TAG) > 0;
       
   169 			hasEventStartTag = tag
       
   170 					.indexOf(OstConstants.PERFORMANCE_EVENT_START_TAG) > 0;
       
   171 			hasEventStopTag = tag
       
   172 					.indexOf(OstConstants.PERFORMANCE_EVENT_STOP_TAG) > 0;
       
   173 			hasFunctionEntryTag = tag.indexOf(OstConstants.FUNCTION_ENTRY_TAG) > 0;
       
   174 			hasFunctionExitTag = tag.indexOf(OstConstants.FUNCTION_EXIT_TAG) > 0;
       
   175 		}
       
   176 
       
   177 		/**
       
   178 		 * Checks if any of the flags is set
       
   179 		 * 
       
   180 		 * @return true if flag is set
       
   181 		 */
       
   182 		boolean hasFlags() {
       
   183 			return hasDataTag || hasStateTag || hasExtTag || hasEventStartTag
       
   184 					|| hasEventStopTag || hasFunctionEntryTag
       
   185 					|| hasFunctionExitTag;
       
   186 		}
       
   187 
       
   188 	}
       
   189 
       
   190 	/**
       
   191 	 * Offset to preprocessor level
       
   192 	 */
       
   193 	private static final int PREPROCESSOR_LEVEL_OFFSET = 0; // CodForChk_Dis_Magic
       
   194 
       
   195 	/**
       
   196 	 * Offset to group name if preprocessor level is not in use
       
   197 	 */
       
   198 	private static final int GROUP_NAME_OFFSET = 0; // CodForChk_Dis_Magic
       
   199 
       
   200 	/**
       
   201 	 * Offset to trace name if preprocessor level is not in use
       
   202 	 */
       
   203 	private static final int TRACE_NAME_OFFSET = 1; // CodForChk_Dis_Magic
       
   204 
       
   205 	/**
       
   206 	 * Offset to trace text if preprocessor level is not in use
       
   207 	 */
       
   208 	private static final int TRACE_TEXT_OFFSET = 2; // CodForChk_Dis_Magic
       
   209 
       
   210 	/**
       
   211 	 * Minimum number of parameters if preprocessor level is not in use
       
   212 	 */
       
   213 	private static final int MIN_PARAMETER_COUNT = 3; // CodForChk_Dis_Magic
       
   214 
       
   215 	/**
       
   216 	 * Parser tag
       
   217 	 */
       
   218 	private static final String OST_TRACE_PARSER_TAG = "OstTrace"; //$NON-NLS-1$
       
   219 
       
   220 	/**
       
   221 	 * OstTrace parser formats
       
   222 	 */
       
   223 	private final static String[] OST_TRACE_PARSER_FORMATS = { "0", //$NON-NLS-1$
       
   224 			"1", //$NON-NLS-1$
       
   225 			"Data", //$NON-NLS-1$
       
   226 			"Ext?", //$NON-NLS-1$
       
   227 			"FunctionEntry0", //$NON-NLS-1$
       
   228 			"FunctionEntry1", //$NON-NLS-1$
       
   229 			"FunctionEntryExt", //$NON-NLS-1$
       
   230 			"FunctionExit0", //$NON-NLS-1$
       
   231 			"FunctionExit1", //$NON-NLS-1$
       
   232 			"FunctionExitExt", //$NON-NLS-1$
       
   233 			"EventStart0", //$NON-NLS-1$
       
   234 			"EventStart1", //$NON-NLS-1$
       
   235 			"EventStop", //$NON-NLS-1$
       
   236 			"Def0", //$NON-NLS-1$
       
   237 			"Def1", //$NON-NLS-1$
       
   238 			"DefData", //$NON-NLS-1$
       
   239 			"DefExt?", //$NON-NLS-1$
       
   240 			"State0", //$NON-NLS-1$
       
   241 			"State1" //$NON-NLS-1$
       
   242 	};
       
   243 
       
   244 	/**
       
   245 	 * Creates a new OstTrace parser rule
       
   246 	 */
       
   247 	public OstTraceParserRule() {
       
   248 		super(OST_TRACE_PARSER_TAG, OST_TRACE_PARSER_FORMATS);
       
   249 	}
       
   250 
       
   251 	/*
       
   252 	 * (non-Javadoc)
       
   253 	 * 
       
   254 	 * @see com.nokia.tracecompiler.engine.source.SourceParserRule#getName()
       
   255 	 */
       
   256 	@Override
       
   257 	public String getName() {
       
   258 		return OstTraceFormatRule.STORAGE_NAME;
       
   259 	}
       
   260 
       
   261 	/* (non-Javadoc)
       
   262 	 * @see com.nokia.tracecompiler.engine.rules.SourceParserRuleBase#parseParameters(java.lang.String, java.util.List)
       
   263 	 */
       
   264 	@Override
       
   265 	public SourceParserResult parseParameters(String tag, List<String> list)
       
   266 			throws TraceCompilerException {
       
   267 		SourceParserResult result = new SourceParserResult();
       
   268 		TraceParameterIndexList indexList = getIndexList(tag);
       
   269 		if (list.size() >= indexList.minParamCount) {
       
   270 			// Name must exist
       
   271 			result.originalName = list.get(indexList.nameIndex);
       
   272 			result.convertedName = result.originalName;
       
   273 			// Text is optional
       
   274 			if (indexList.textIndex >= 0) {
       
   275 				result.traceText = trimTraceText(list.get(indexList.textIndex));
       
   276 			} else {
       
   277 				result.traceText = ""; //$NON-NLS-1$
       
   278 			}
       
   279 			// Group ID and preprocessor level are stored into the
       
   280 			// parser-specific data
       
   281 			result.parserData = new ArrayList<String>();
       
   282 			if (indexList.levelIndex >= 0) {
       
   283 				result.parserData.add(list.get(indexList.levelIndex));
       
   284 			}
       
   285 			if (indexList.groupIndex >= 0) {
       
   286 				result.parserData.add(list.get(indexList.groupIndex));
       
   287 			} else if (indexList.groupName != null) {
       
   288 				result.parserData.add(indexList.groupName);
       
   289 			}
       
   290 
       
   291 			// Extra parameters are converted to trace parameters
       
   292 			result.parameters = new ArrayList<String>();
       
   293 			for (int i = indexList.minParamCount; i < list.size(); i++) {
       
   294 				result.parameters.add(list.get(i));
       
   295 			}
       
   296 		} else {
       
   297 			throw new TraceCompilerException(
       
   298 					TraceCompilerErrorCode.NOT_ENOUGH_PARAMETERS);
       
   299 		}
       
   300 		return result;
       
   301 	}
       
   302 
       
   303 	/**
       
   304 	 * Gets the parameter index list based on trace tag
       
   305 	 * 
       
   306 	 * @param tag
       
   307 	 *            the trace tag
       
   308 	 * @return the index list
       
   309 	 */
       
   310 	private TraceParameterIndexList getIndexList(String tag) {
       
   311 		TraceParameterIndexList indexes = new TraceParameterIndexList();
       
   312 		indexes.levelIndex = -1;
       
   313 		if (tag.indexOf(OstConstants.FUNCTION_ENTRY_TAG) > 0
       
   314 				|| tag.indexOf(OstConstants.FUNCTION_EXIT_TAG) > 0) {
       
   315 			indexes.minParamCount = 1; // Name is mandatory
       
   316 			indexes.textIndex = -1; // No trace text
       
   317 			indexes.nameIndex = 0; // Trace name at index 0
       
   318 			indexes.groupIndex = -1; // Group is fixed to TRACE_FLOW
       
   319 			indexes.groupName = FLOW_GROUP_NAME;
       
   320 		} else if (tag.indexOf(OstConstants.STATE_TRACE_TAG) > 0) {
       
   321 			indexes.minParamCount = 1; // Name is mandatory
       
   322 			indexes.textIndex = -1; // No trace text
       
   323 			indexes.nameIndex = 0; // Trace name at index 0
       
   324 			indexes.groupIndex = -1; // Group is fixed to TRACE_STATE
       
   325 			indexes.groupName = STATE_GROUP_NAME;
       
   326 		} else if (tag.indexOf(OstConstants.PERFORMANCE_EVENT_START_TAG) > 0) {
       
   327 			// Name and event name are mandatory
       
   328 			indexes.minParamCount = 2; // CodForChk_Dis_Magic
       
   329 			indexes.textIndex = 1; // Trace text at index 1
       
   330 			indexes.nameIndex = 0; // Trace name at index 0
       
   331 			indexes.groupIndex = -1; // Group is fixed to TRACE_PERFORMANCE
       
   332 			indexes.groupName = PERFORMANCE_GROUP_NAME;
       
   333 		} else if (tag.indexOf(OstConstants.PERFORMANCE_EVENT_STOP_TAG) > 0) {
       
   334 			// Name and event name are mandatory
       
   335 			indexes.minParamCount = 2; // CodForChk_Dis_Magic
       
   336 			indexes.textIndex = 1; // Trace text at index 1
       
   337 			indexes.nameIndex = 0; // Trace name at index 0
       
   338 			indexes.groupIndex = -1; // Group is fixed to TRACE_PERFORMANCE
       
   339 			indexes.groupName = PERFORMANCE_GROUP_NAME;
       
   340 		} else {
       
   341 			indexes.minParamCount = MIN_PARAMETER_COUNT;
       
   342 			indexes.textIndex = TRACE_TEXT_OFFSET;
       
   343 			indexes.nameIndex = TRACE_NAME_OFFSET;
       
   344 			indexes.groupIndex = GROUP_NAME_OFFSET;
       
   345 		}
       
   346 		// If the trace macro contains preprocessor level, the offsets are
       
   347 		// incremented by one
       
   348 		if (tag.indexOf(OstConstants.PREPROCESSOR_LEVEL_TAG) > 0) {
       
   349 			indexes.minParamCount++;
       
   350 			if (indexes.textIndex >= 0) {
       
   351 				indexes.textIndex++;
       
   352 			}
       
   353 			if (indexes.nameIndex >= 0) {
       
   354 				indexes.nameIndex++;
       
   355 			}
       
   356 			if (indexes.groupIndex >= 0) {
       
   357 				indexes.groupIndex++;
       
   358 			}
       
   359 			indexes.levelIndex = PREPROCESSOR_LEVEL_OFFSET;
       
   360 		}
       
   361 		return indexes;
       
   362 	}
       
   363 
       
   364 	/*
       
   365 	 * (non-Javadoc)
       
   366 	 * 
       
   367 	 * @see com.nokia.tracecompiler.engine.source.SourceParserRule#
       
   368 	 *      convertLocation(com.nokia.tracecompiler.engine.TraceLocation)
       
   369 	 */
       
   370 	@Override
       
   371 	public TraceConversionResult convertLocation(TraceLocation location)
       
   372 			throws TraceCompilerException { // CodForChk_Dis_ComplexFunc
       
   373 		TraceParameterFlagList flags = checkParameterCount(location);
       
   374 
       
   375 		// Data tag does not have parameters
       
   376 		boolean checkParameters = !flags.hasDataTag;
       
   377 
       
   378 		List<FormatMapping> typeList;
       
   379 		if (flags.hasExtTag
       
   380 				&& (flags.hasFunctionEntryTag || flags.hasFunctionExitTag)) {
       
   381 			// Parameters are generated by AutoAdd rules
       
   382 			typeList = new ArrayList<FormatMapping>();
       
   383 			checkParameters = false;
       
   384 		} else if (!flags.hasFlags() || flags.hasDataTag || flags.hasExtTag) {
       
   385 			// If the Ext, Data or EventStart tag is present, all formats
       
   386 			// are supported. If no flags is set, only 32-bit formats are
       
   387 			// supported.
       
   388 			typeList = buildParameterTypeList(location.getTraceText(),
       
   389 					!flags.hasDataTag && !flags.hasExtTag);
       
   390 		} else if (flags.hasEventStartTag) {
       
   391 			// In case of Start1 tag value parameter is supported
       
   392 			typeList = new ArrayList<FormatMapping>();
       
   393 			// Check that does optional value exist
       
   394 			if (location.getParameterCount() == 1) {
       
   395 				FormatMapping mapping = new FormatMapping(TraceParameter.SDEC32);
       
   396 				mapping.isSimple = true;
       
   397 				typeList.add(mapping);
       
   398 			}
       
   399 			checkParameters = false;
       
   400 		} else if (flags.hasEventStopTag) {
       
   401 			// If the Event stop tag is presented, start event trace
       
   402 			// id parameter is supported
       
   403 			typeList = new ArrayList<FormatMapping>();
       
   404 			FormatMapping mapping = new FormatMapping(TraceParameter.UDEC32);
       
   405 			mapping.isSimple = true;
       
   406 			typeList.add(mapping);
       
   407 			checkParameters = false;
       
   408 
       
   409 		} else if (flags.hasStateTag) {
       
   410 			// If the State tag is presented, two ascii parameters are supported
       
   411 			// in case of State0 tag (parameter count = 2). In case of State1
       
   412 			// tag (parameter count = 3) two ascii and one 32-bit hex parameters
       
   413 			// are supported
       
   414 			typeList = new ArrayList<FormatMapping>();
       
   415 			FormatMapping mapping = new FormatMapping(TraceParameter.ASCII);
       
   416 			mapping.isSimple = true;
       
   417 			typeList.add(mapping);
       
   418 			mapping = new FormatMapping(TraceParameter.ASCII);
       
   419 			mapping.isSimple = true;
       
   420 			typeList.add(mapping);
       
   421 
       
   422 			// Check that does optional instance identifier exist
       
   423 			if (location.getParameterCount() == 3) { // CodForChk_Dis_Magic
       
   424 				mapping = new FormatMapping(TraceParameter.HEX32);
       
   425 				mapping.isSimple = true;
       
   426 				typeList.add(mapping);
       
   427 			}
       
   428 			checkParameters = false;
       
   429 		} else {
       
   430 			// If some other flag than Data, State, Ext or EventStart is set,
       
   431 			// only one 32-bit hex parameter is supported
       
   432 			typeList = new ArrayList<FormatMapping>();
       
   433 			if (location.getParameterCount() == 1) {
       
   434 				FormatMapping mapping = new FormatMapping(TraceParameter.HEX32);
       
   435 				mapping.isSimple = true;
       
   436 				typeList.add(mapping);
       
   437 			}
       
   438 		}
       
   439 		// If no flags or Ext flag is present, the parameter count needs to be
       
   440 		// verified
       
   441 		TraceConversionResult result = super.convertLocation(location,
       
   442 				checkParameters, typeList);
       
   443 		// If the extension or state tag is present, zero parameters or a single
       
   444 		// 32-bit parameter is not accepted because they do not need to generate
       
   445 		// a function into the header
       
   446 		if (((flags.hasExtTag && !flags.hasFunctionExitTag && !flags.hasFunctionEntryTag) || (flags.hasStateTag))
       
   447 				&& (typeList.size() == 0 || (typeList.size() == 1 && typeList
       
   448 						.get(0).isSimple))) {
       
   449 			throw new TraceCompilerException(
       
   450 					TraceCompilerErrorCode.PARAMETER_FORMAT_UNNECESSARY_EXT_MACRO);
       
   451 		}
       
   452 		// Ext-macros are tagged with the complex header rule, so the header
       
   453 		// gets written when traces are exported. Data-macros are tagged with
       
   454 		// read-only rule, so they are not updated via UI. Other special cases
       
   455 		// are flagged with corresponding rule.
       
   456 		// If trace text does not exist, it is created based on context
       
   457 		AutomaticTraceTextRule rule = null;
       
   458 		if (flags.hasDataTag) {
       
   459 			addRule(result, new ReadOnlyObjectRuleImpl());
       
   460 		} else if (flags.hasStateTag) {
       
   461 			addRule(result, new StateTraceRule());
       
   462 			addRule(result, new ComplexHeaderRuleImpl());
       
   463 		} else if (flags.hasEventStartTag) {
       
   464 			addRule(result, new PerformanceEventStartRule());
       
   465 			// If event value is not defined then event value 1 is automatically
       
   466 			// added to event start macros
       
   467 			if (location.getParameterCount() == 0) {
       
   468 				addRule(result, new AutoAddValueRule());
       
   469 			}
       
   470 		} else if (flags.hasEventStopTag) {
       
   471 			addRule(result, new PerformanceEventStopRule());
       
   472 			addRule(result, new ComplexHeaderRuleImpl());
       
   473 			// Event value 0 is automatically added to event stop macros
       
   474 			addRule(result, new AutoAddValueRule());
       
   475 		} else if (flags.hasFunctionEntryTag) {
       
   476 			if (flags.hasExtTag) {
       
   477 				// Entry trace may contain Ext tag. In that case the trace
       
   478 				// parameters are an instance variable and function parameters
       
   479 				// parsed from source. It is also flagged as complex, so the
       
   480 				// function gets generated to the trace header
       
   481 				addRule(result, new ComplexHeaderRuleImpl());
       
   482 				addRule(result, new AutoAddFunctionParametersRule());
       
   483 				addRule(result, new AutoAddThisPtrRule());
       
   484 			}
       
   485 			rule = new EntryTraceRule();
       
   486 			addRule(result, rule);
       
   487 		} else if (flags.hasFunctionExitTag) {
       
   488 			if (flags.hasExtTag) {
       
   489 				// Exit trace may contain Ext tag. In that case the trace has
       
   490 				// two parameters: instance variable and return statement
       
   491 				// It is also flagged as complex, so the function gets generated
       
   492 				// to the trace header
       
   493 				addRule(result, new ComplexHeaderRuleImpl());
       
   494 				addRule(result, new AutoAddThisPtrRule());
       
   495 				addRule(result, new AutoAddReturnParameterRule());
       
   496 			}
       
   497 			rule = new ExitTraceRule();
       
   498 			addRule(result, rule);
       
   499 		} else if (flags.hasExtTag) {
       
   500 			addRule(result, new ComplexHeaderRuleImpl());
       
   501 		}
       
   502 		if (rule != null) {
       
   503 			setAutoTextToTrace(location, result, rule);
       
   504 		}
       
   505 		List<String> parserData = location.getParserData();
       
   506 		result.group = parserData.get(parserData.size() - 1);
       
   507 		// The convert flag is reset to prevent further conversions
       
   508 		location.locationConverted();
       
   509 		return result;
       
   510 	}
       
   511 
       
   512 	/**
       
   513 	 * Uses the auto-text rule to create trace text
       
   514 	 * 
       
   515 	 * @param location
       
   516 	 *            the location
       
   517 	 * @param result
       
   518 	 *            the conversion result
       
   519 	 * @param rule
       
   520 	 *            the auto-text rule
       
   521 	 * @throws TraceCompilerException
       
   522 	 *             if update fails
       
   523 	 */
       
   524 	private void setAutoTextToTrace(TraceLocation location,
       
   525 			TraceConversionResult result, AutomaticTraceTextRule rule)
       
   526 			throws TraceCompilerException {
       
   527 		// The trace text comes from the auto-text rule
       
   528 		SourceParser parser = location.getParser();
       
   529 		SourceContext context = parser.getContext(location.getOffset());
       
   530 		if (context != null) {
       
   531 			result.text = rule.formatTrace(context);
       
   532 		} else {
       
   533 			throw new TraceCompilerException(
       
   534 					TraceCompilerErrorCode.NO_CONTEXT_FOR_LOCATION);
       
   535 		}
       
   536 	}
       
   537 
       
   538 	/**
       
   539 	 * Checks parameter count
       
   540 	 * 
       
   541 	 * @param location
       
   542 	 *            the location
       
   543 	 * @return the location tag flags
       
   544 	 * @throws TraceCompilerException
       
   545 	 *             if parameter count is not valid
       
   546 	 */
       
   547 	private TraceParameterFlagList checkParameterCount(TraceLocation location)
       
   548 			throws TraceCompilerException {
       
   549 		TraceParameterFlagList flags = new TraceParameterFlagList(location
       
   550 				.getTag());
       
   551 
       
   552 		// If the trace has some tag, the parameter count is fixed
       
   553 		// Data has 2 parameters
       
   554 		// State has 2 or 3 parameters
       
   555 		// Function entry-exit has 0 or 1 parameters
       
   556 		// Event start has 0 or 1 parameters
       
   557 		// Event stop has 1 parameters
       
   558 		int parameterCount = location.getParameterCount();
       
   559 
       
   560 		// Entry trace may have zero or one parameter
       
   561 		// In case of Ext, it must have one parameter
       
   562 		if (flags.hasFunctionEntryTag
       
   563 				&& ((parameterCount > 1) || (flags.hasExtTag && (parameterCount != ENTRY_EXT_PARAMETER_COUNT)))) {
       
   564 			throw new TraceCompilerException(
       
   565 					TraceCompilerErrorCode.PARAMETER_COUNT_DOES_NOT_MATCH_API);
       
   566 		}
       
   567 
       
   568 		// Exit trace may have zero or one parameter
       
   569 		// In case of Ext, it must have two parameters
       
   570 		if (flags.hasFunctionExitTag
       
   571 				&& ((!flags.hasExtTag && (parameterCount > 1)) || (flags.hasExtTag && parameterCount != EXIT_EXT_PARAMETER_COUNT))) { // CodForChk_Dis_LengthyLine
       
   572 			throw new TraceCompilerException(
       
   573 					TraceCompilerErrorCode.PARAMETER_COUNT_DOES_NOT_MATCH_API);
       
   574 		}
       
   575 
       
   576 		// Event start may have zero or one parameter
       
   577 		if (flags.hasEventStartTag && (parameterCount > 1)) {
       
   578 			throw new TraceCompilerException(
       
   579 					TraceCompilerErrorCode.PARAMETER_COUNT_DOES_NOT_MATCH_API);
       
   580 		}
       
   581 
       
   582 		// Event stop have one parameters
       
   583 		if (flags.hasEventStopTag && (parameterCount != 1)) {
       
   584 			throw new TraceCompilerException(
       
   585 					TraceCompilerErrorCode.PARAMETER_COUNT_DOES_NOT_MATCH_API);
       
   586 		}
       
   587 
       
   588 		// Data trace has two parameters
       
   589 		if ((flags.hasDataTag && (parameterCount != DATA_PARAMETER_COUNT))) {
       
   590 			throw new TraceCompilerException(
       
   591 					TraceCompilerErrorCode.PARAMETER_COUNT_DOES_NOT_MATCH_API);
       
   592 		}
       
   593 
       
   594 		// State trace may have two or three parameter
       
   595 		if (flags.hasStateTag && (parameterCount < 2 || parameterCount > 3)) { // CodForChk_Dis_Magic
       
   596 			throw new TraceCompilerException(
       
   597 					TraceCompilerErrorCode.PARAMETER_COUNT_DOES_NOT_MATCH_API);
       
   598 		}
       
   599 
       
   600 		return flags;
       
   601 	}
       
   602 
       
   603 	/**
       
   604 	 * Adds a rule to result
       
   605 	 * 
       
   606 	 * @param result
       
   607 	 *            the result
       
   608 	 * @param rule
       
   609 	 *            the rule
       
   610 	 */
       
   611 	private void addRule(TraceConversionResult result, TraceModelExtension rule) {
       
   612 		if (result.extensions == null) {
       
   613 			result.extensions = new ArrayList<TraceModelExtension>();
       
   614 		}
       
   615 		result.extensions.add(rule);
       
   616 	}
       
   617 
       
   618 	/*
       
   619 	 * (non-Javadoc)
       
   620 	 * 
       
   621 	 * @see com.nokia.tracecompiler.engine.rules.SourceParserRuleBase#
       
   622 	 * isLocationConverted(com.nokia.tracecompiler.engine.TraceLocation)
       
   623 	 */
       
   624 	@Override
       
   625 	public boolean isLocationConverted(TraceLocation location) {
       
   626 		boolean retval = location.hasChangedAfterConvert();
       
   627 		if (!retval) {
       
   628 			// Duplicate-location conversions need to be retried in case the
       
   629 			// location is no longer a duplicate
       
   630 			retval = (location.getValidityCode() == TraceCompilerErrorCode.TRACE_HAS_MULTIPLE_LOCATIONS);
       
   631 		}
       
   632 		return retval;
       
   633 	}
       
   634 
       
   635 	/*
       
   636 	 * (non-Javadoc)
       
   637 	 * 
       
   638 	 * @seecom.nokia.tracecompiler.engine.rules.printf.PrintfTraceParserRule#
       
   639 	 * getLocationGroup()
       
   640 	 */
       
   641 	@Override
       
   642 	public String getLocationGroup() {
       
   643 		return null;
       
   644 	}
       
   645 }