/*******************************************************************************
 * Copyright (c) 2000, 2003 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/

package org.eclipse.cdt.internal.core.search.indexing;

import java.io.IOException;
import java.util.Iterator;

import org.eclipse.cdt.core.parser.ast.ASTClassKind;
import org.eclipse.cdt.core.parser.ast.IASTClassSpecifier;
import org.eclipse.cdt.core.parser.ast.IASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.parser.ast.IASTEnumerationSpecifier;
import org.eclipse.cdt.core.parser.ast.IASTEnumerator;
import org.eclipse.cdt.core.parser.ast.IASTField;
import org.eclipse.cdt.core.parser.ast.IASTFunction;
import org.eclipse.cdt.core.parser.ast.IASTInclusion;
import org.eclipse.cdt.core.parser.ast.IASTMacro;
import org.eclipse.cdt.core.parser.ast.IASTMethod;
import org.eclipse.cdt.core.parser.ast.IASTNamespaceDefinition;
import org.eclipse.cdt.core.parser.ast.IASTParameterDeclaration;
import org.eclipse.cdt.core.parser.ast.IASTTypeSpecifier;
import org.eclipse.cdt.core.parser.ast.IASTTypedefDeclaration;
import org.eclipse.cdt.core.parser.ast.IASTVariable;
import org.eclipse.cdt.core.search.ICSearchConstants;
import org.eclipse.cdt.internal.core.CharOperation;
import org.eclipse.cdt.internal.core.index.IDocument;
import org.eclipse.cdt.internal.core.index.IIndexer;
import org.eclipse.cdt.internal.core.index.IIndexerOutput;
import org.eclipse.core.resources.IFile;

public abstract class AbstractIndexer implements IIndexer, IIndexConstants, ICSearchConstants {
	
	IIndexerOutput output;
	final static int CLASS = 1;
	final static int STRUCT = 2;
	final static int UNION = 3;
	final static int ENUM = 4;
	final static int VAR = 5;
	final static int TYPEDEF = 6;
	
	public static boolean VERBOSE = false;
	
	public AbstractIndexer() {
		super();
	}
	
	public static void verbose(String log) {
	  System.out.println("(" + Thread.currentThread() + ") " + log); //$NON-NLS-1$//$NON-NLS-2$
	}
	
	public void addClassSpecifier(IASTClassSpecifier classSpecification){

		if (classSpecification.getClassKind().equals(ASTClassKind.CLASS))
		{
			this.output.addRef(encodeTypeEntry(classSpecification.getFullyQualifiedName(),CLASS, ICSearchConstants.DECLARATIONS));
		}		
		else if (classSpecification.getClassKind().equals(ASTClassKind.STRUCT))
		{
			this.output.addRef(encodeTypeEntry(classSpecification.getFullyQualifiedName(),STRUCT, ICSearchConstants.DECLARATIONS));
		}
		else if (classSpecification.getClassKind().equals(ASTClassKind.UNION))
		{
			this.output.addRef(encodeTypeEntry(classSpecification.getFullyQualifiedName(),UNION, ICSearchConstants.DECLARATIONS));			
		}
	}
	
	public void addEnumerationSpecifier(IASTEnumerationSpecifier enumeration) {
		this.output.addRef(encodeTypeEntry(enumeration.getFullyQualifiedName(), ENUM, ICSearchConstants.DECLARATIONS));
		
		Iterator i = enumeration.getEnumerators();
		while (i.hasNext())
		{
			IASTEnumerator en = (IASTEnumerator) i.next(); 	
			String[] enumeratorFullName =
				createEnumeratorFullyQualifiedName(en);
			
			this.output.addRef(encodeEntry( enumeratorFullName, FIELD_DECL, FIELD_DECL_LENGTH ));

		}
	}

	protected String[] createEnumeratorFullyQualifiedName(IASTEnumerator en) {
		String name = en.getName();
		IASTEnumerationSpecifier parent = en.getOwnerEnumerationSpecifier();
		String[] parentName = parent.getFullyQualifiedName();
		
		//See spec 7.2-10, the the scope of the enumerator is the same level as the enumeration
		String[] enumeratorFullName = new String[ parentName.length ];
		
		System.arraycopy( parentName, 0, enumeratorFullName, 0, parentName.length);
		enumeratorFullName[ parentName.length - 1 ] = name;
		return enumeratorFullName;
	}

	public void addEnumeratorReference(IASTEnumerator enumerator) {
		this.output.addRef(encodeEntry(createEnumeratorFullyQualifiedName(enumerator),FIELD_REF,FIELD_REF_LENGTH));	
	}
		
	public void addMacro(IASTMacro macro) {
		String[] macroName = new String[1];
		macroName[0] = macro.getName();
		this.output.addRef(encodeEntry(macroName,MACRO_DECL,MACRO_DECL_LENGTH));
	}
		
	public void addEnumerationReference(IASTEnumerationSpecifier enumeration) {
		this.output.addRef(encodeTypeEntry(enumeration.getFullyQualifiedName(), ENUM, ICSearchConstants.REFERENCES));
	}
	public void addVariable(IASTVariable variable) {
		this.output.addRef(encodeTypeEntry(variable.getFullyQualifiedName(), VAR, ICSearchConstants.DECLARATIONS));
	}
	
	public void addVariableReference(IASTVariable variable) {
		this.output.addRef(encodeTypeEntry(variable.getFullyQualifiedName(), VAR, ICSearchConstants.REFERENCES));
	}	
	
	public void addParameterReference( IASTParameterDeclaration parameter ){
		this.output.addRef( encodeTypeEntry( new String [] { parameter.getName() }, VAR, ICSearchConstants.REFERENCES));
	}
	
	public void addTypedefDeclaration(IASTTypedefDeclaration typedef) {
		this.output.addRef(encodeEntry(typedef.getFullyQualifiedName(), TYPEDEF_DECL, TYPEDEF_DECL_LENGTH));
	}
	
	public void addFieldDeclaration(IASTField field) {
		this.output.addRef(encodeEntry(field.getFullyQualifiedName(),FIELD_DECL,FIELD_DECL_LENGTH));
	}
	
	public void addFieldReference(IASTField field) {
		this.output.addRef(encodeEntry(field.getFullyQualifiedName(),FIELD_REF,FIELD_REF_LENGTH));
	}
	
	public void addMethodDeclaration(IASTMethod method) {
		this.output.addRef(encodeEntry(method.getFullyQualifiedName(),METHOD_DECL,METHOD_DECL_LENGTH));
	}
	
	public void addMethodReference(IASTMethod method) {
		this.output.addRef(encodeEntry(method.getFullyQualifiedName(),METHOD_REF,METHOD_REF_LENGTH));
	}

	public void addElaboratedForwardDeclaration(IASTElaboratedTypeSpecifier elaboratedType) {
		if (elaboratedType.getClassKind().equals(ASTClassKind.CLASS))
		{
			this.output.addRef(encodeTypeEntry(elaboratedType.getFullyQualifiedName(),CLASS, ICSearchConstants.DECLARATIONS));
		}		
		else if (elaboratedType.getClassKind().equals(ASTClassKind.STRUCT))
		{
			this.output.addRef(encodeTypeEntry(elaboratedType.getFullyQualifiedName(),STRUCT, ICSearchConstants.DECLARATIONS));
		}
		else if (elaboratedType.getClassKind().equals(ASTClassKind.UNION))
		{
			this.output.addRef(encodeTypeEntry(elaboratedType.getFullyQualifiedName(),UNION, ICSearchConstants.DECLARATIONS));			
		}
	}
	
	public void addConstructorDeclaration(){
		
	}
	public void addConstructorReference(){

	}
	
	public void addMemberDeclaration(){
	
	}
	public void addMemberReference(){
	
	}

	public void addFunctionDeclaration(IASTFunction function){
		this.output.addRef(encodeEntry(function.getFullyQualifiedName(),FUNCTION_DECL,FUNCTION_DECL_LENGTH));
	}
	
	public void addFunctionReference(IASTFunction function){
		this.output.addRef(encodeEntry(function.getFullyQualifiedName(),FUNCTION_REF,FUNCTION_REF_LENGTH));
	}
	
	public void addNameReference(){
		
	}
	
	public void addNamespaceDefinition(IASTNamespaceDefinition namespace){
		this.output.addRef(encodeEntry(namespace.getFullyQualifiedName(),NAMESPACE_DECL,NAMESPACE_DECL_LENGTH));
	}
	
	public void addNamespaceReference(IASTNamespaceDefinition namespace) {
		this.output.addRef(encodeEntry(namespace.getFullyQualifiedName(),NAMESPACE_REF,NAMESPACE_REF_LENGTH));
	}
	
	public void addTypedefReference( IASTTypedefDeclaration typedef ){
		this.output.addRef( encodeTypeEntry( typedef.getFullyQualifiedName(), TYPEDEF, ICSearchConstants.REFERENCES) );
	}

	private void addSuperTypeReference(int modifiers, char[] packageName, char[] typeName, char[][] enclosingTypeNames, char classOrInterface, char[] superTypeName, char superClassOrInterface){

	}
	
	public void addTypeReference(char[] typeName){
		//this.output.addRef(CharOperation.concat(TYPE_REF, CharOperation.lastSegment(typeName, '.')));
	}
	
	public void addClassReference(IASTTypeSpecifier reference){
		String[] fullyQualifiedName = null;
		ASTClassKind classKind = null;
		
		if (reference instanceof IASTClassSpecifier){
		  IASTClassSpecifier classRef = (IASTClassSpecifier) reference;
		  fullyQualifiedName = classRef.getFullyQualifiedName();
		  classKind = classRef.getClassKind();
		}
		else if (reference instanceof IASTElaboratedTypeSpecifier){
		  IASTElaboratedTypeSpecifier typeRef = (IASTElaboratedTypeSpecifier) reference;
		  fullyQualifiedName = typeRef.getFullyQualifiedName();
		  classKind = typeRef.getClassKind();
		}
	
		if (classKind.equals(ASTClassKind.CLASS))
		{  
			this.output.addRef(encodeTypeEntry(fullyQualifiedName,CLASS, ICSearchConstants.REFERENCES));
		}		
		else if (classKind.equals(ASTClassKind.STRUCT))
		{
			this.output.addRef(encodeTypeEntry(fullyQualifiedName,STRUCT,ICSearchConstants.REFERENCES));
		}
		else if (classKind.equals(ASTClassKind.UNION))
		{
			this.output.addRef(encodeTypeEntry(fullyQualifiedName,UNION,ICSearchConstants.REFERENCES));			
		}
	}
	/**
	 * Type entries are encoded as follow: 'typeDecl/' ('C' | 'S' | 'U' | 'E' ) '/'  TypeName ['/' Qualifier]* 
	 */
	 protected static final char[] encodeTypeEntry( String [] fullTypeName, int typeType, LimitTo encodeType){ 

		int pos = 0, nameLength = 0;
		for (int i=0; i<fullTypeName.length; i++){
			String namePart = fullTypeName[i];
			nameLength+= namePart.length();
		}
		
		char [] result = null;
		if( encodeType == REFERENCES ){
			//char[] has to be of size - [type decl length + length of the name + separators + letter]
			result = new char[TYPE_REF_LENGTH + nameLength + fullTypeName.length + 1 ];
			System.arraycopy(TYPE_REF, 0, result, 0, pos = TYPE_REF_LENGTH);
		
		} else if( encodeType == DECLARATIONS ){
			//char[] has to be of size - [type decl length + length of the name + separators + letter]
			result = new char[TYPE_DECL_LENGTH + nameLength + fullTypeName.length + 1 ];
			System.arraycopy(TYPE_DECL, 0, result, 0, pos = TYPE_DECL_LENGTH);
		}
		switch (typeType)
		{
			case(CLASS):
			result[pos++] = CLASS_SUFFIX;
			break;
			
			case(STRUCT):
			result[pos++] = STRUCT_SUFFIX;
			break;
			
			case(UNION):
			result[pos++] = UNION_SUFFIX;
			break;
			
			case(ENUM):
			result[pos++] = ENUM_SUFFIX;
			break;
			
			case (VAR):
			result[pos++] = VAR_SUFFIX;
			break;
			
			case (TYPEDEF):
			result[pos++] = TYPEDEF_SUFFIX;
			break;
		}
		result[pos++] = SEPARATOR;
		//Encode in the following manner
		//	[typeDecl info]/[typeName]/[qualifiers]
		if (fullTypeName.length > 0){
		//Extract the name first
			char [] tempName = fullTypeName[fullTypeName.length-1].toCharArray();
			System.arraycopy(tempName, 0, result, pos, tempName.length);
			pos += tempName.length;
		}
		//Extract the qualifiers
		for (int i=fullTypeName.length - 2; i >= 0; i--){
			result[pos++] = SEPARATOR;
			char [] tempName = fullTypeName[i].toCharArray();
			System.arraycopy(tempName, 0, result, pos, tempName.length);
			pos+=tempName.length;				
		}
		
		if (AbstractIndexer.VERBOSE)
			AbstractIndexer.verbose(new String(result));
			
		return result;
	}
	/**
	 * Namespace entries are encoded as follow: '[prefix]/' TypeName ['/' Qualifier]*
	 */
	protected static final char[] encodeEntry(String[] elementName, char[] prefix, int prefixSize){ 
		int pos, nameLength = 0;
		for (int i=0; i<elementName.length; i++){
			String namePart = elementName[i];
			nameLength+= namePart.length();
		}
		//char[] has to be of size - [type length + length of the name (including qualifiers) + 
		//separators (need one less than fully qualified name length)
		char[] result = new char[prefixSize + nameLength + elementName.length - 1 ];
		System.arraycopy(prefix, 0, result, 0, pos = prefix.length);
		if (elementName.length > 0){
		//Extract the name first
			char [] tempName = elementName[elementName.length-1].toCharArray();
			System.arraycopy(tempName, 0, result, pos, tempName.length);
			pos += tempName.length;
		}
		//Extract the qualifiers
		for (int i=elementName.length - 2; i>=0; i--){
			result[pos++] = SEPARATOR;
			char [] tempName = elementName[i].toCharArray();
			System.arraycopy(tempName, 0, result, pos, tempName.length);
			pos+=tempName.length;				
		}
		
		if (AbstractIndexer.VERBOSE)
			AbstractIndexer.verbose(new String(result));
			
		return result;
	}
	
	/**
	 * Returns the file types the <code>IIndexer</code> handles.
	 */
	public abstract String[] getFileTypes();
	/**
	 * Returns the file types being indexed.
	 */
	public abstract IFile getResourceFile();
	/**
	 * @see IIndexer#index(IDocument document, IIndexerOutput output)
	 */
	public void index(IDocument document, IIndexerOutput output) throws IOException {
		this.output = output;
		if (shouldIndex(document)) indexFile(document);
	}
	
	protected abstract void indexFile(IDocument document) throws IOException;
	/**
	 * @see IIndexer#shouldIndex(IDocument document)
	 */
	public boolean shouldIndex(IDocument document) {
		String type = document.getType();
		String[] supportedTypes = this.getFileTypes();
		for (int i = 0; i < supportedTypes.length; ++i) {
			if (supportedTypes[i].equals(type))
				return true;
		}
		return false;
	}
	/**
	 * Type entries are encoded as follow: 'typeDecl/' ('C' | 'S' | 'U' ) '/'  TypeName '/' 
	 * Current encoding is optimized for queries: all classes
	 */
	public static final char[] bestTypePrefix( SearchFor searchFor, LimitTo limitTo, char[] typeName, char[][] containingTypes, int matchMode, boolean isCaseSensitive) {
		char [] prefix = null;
		if( limitTo == DECLARATIONS ){
			prefix = TYPE_DECL;
		} else if( limitTo == REFERENCES ){
			prefix = TYPE_REF;
		} else {
			return TYPE_ALL;
		}
					
		char classType = 0;
		
		if( searchFor == ICSearchConstants.CLASS ){
			classType = CLASS_SUFFIX;
		} else if ( searchFor == ICSearchConstants.STRUCT ){
			classType = STRUCT_SUFFIX;
		} else if ( searchFor == ICSearchConstants.UNION ){
			classType = UNION_SUFFIX;
		} else if ( searchFor == ICSearchConstants.ENUM ){
			classType = ENUM_SUFFIX;
		} else if ( searchFor == ICSearchConstants.TYPEDEF ){
			classType = TYPEDEF_SUFFIX;
		} else {
			//could be TYPE or CLASS_STRUCT, best we can do for these is the prefix
			return prefix;
		}
		
		return bestPrefix( prefix, classType, typeName, containingTypes, matchMode, isCaseSensitive );
	}
	
	public static final char[] bestNamespacePrefix(LimitTo limitTo, char[] namespaceName, char[][] containingTypes, int matchMode, boolean isCaseSensitive) {
		char [] prefix = null;
		if( limitTo == REFERENCES ){
			prefix = NAMESPACE_REF;
		} else if ( limitTo == DECLARATIONS ) {
			prefix = NAMESPACE_DECL;
		} else {
			return NAMESPACE_ALL;
		}
		
		return bestPrefix( prefix, (char) 0, namespaceName, containingTypes, matchMode, isCaseSensitive );
	}	
		
	public static final char[] bestVariablePrefix( LimitTo limitTo, char[] varName, char[][] containingTypes, int matchMode, boolean isCaseSenstive ){
		char [] prefix = null;
		if( limitTo == REFERENCES ){
			prefix = TYPE_REF;
		} else if( limitTo == DECLARATIONS ){
			prefix = TYPE_DECL;
		} else {
			return TYPE_ALL;
		}
		
		return bestPrefix( prefix, VAR_SUFFIX, varName, containingTypes, matchMode, isCaseSenstive );	
	}

	public static final char[] bestFieldPrefix( LimitTo limitTo, char[] fieldName,char[][] containingTypes, int matchMode, boolean isCaseSensitive) {
		char [] prefix = null;
		if( limitTo == REFERENCES ){
			prefix = FIELD_REF;
		} else if( limitTo == DECLARATIONS ){
			prefix = FIELD_DECL;
		} else {
			return FIELD_ALL;
		}
		
		return bestPrefix( prefix, (char)0, fieldName, containingTypes, matchMode, isCaseSensitive );
	}  

	public static final char[] bestMethodPrefix( LimitTo limitTo, char[] methodName,char[][] containingTypes, int matchMode, boolean isCaseSensitive) {
		char [] prefix = null;
		if( limitTo == REFERENCES ){
			prefix = METHOD_REF;
		} else if( limitTo == DECLARATIONS ){
			prefix = METHOD_DECL;
		} else if( limitTo == DEFINITIONS ){
			//TODO prefix = METHOD_DEF;
			return METHOD_ALL;	
		} else {
			return METHOD_ALL;
		}
		
		return bestPrefix( prefix, (char)0, methodName, containingTypes, matchMode, isCaseSensitive );
	}  
	
	public static final char[] bestFunctionPrefix( LimitTo limitTo, char[] functionName, int matchMode, boolean isCaseSensitive) {
		char [] prefix = null;
		if( limitTo == REFERENCES ){
			prefix = FUNCTION_REF;
		} else if( limitTo == DECLARATIONS ){
			prefix = FUNCTION_DECL;
		} else if ( limitTo == DEFINITIONS ){
			//TODO prefix = FUNCTION_DEF;
			return FUNCTION_ALL;
		} else {
			return FUNCTION_ALL;
		}
		return bestPrefix( prefix, (char)0, functionName, null, matchMode, isCaseSensitive );
	}  
		
	public static final char[] bestPrefix( char [] prefix, char optionalType, char[] name, char[][] containingTypes, int matchMode, boolean isCaseSensitive) {
		char[] 	result = null;
		int 	pos    = 0;
		
		int wildPos, starPos = -1, questionPos;
		
		//length of prefix + separator
		int length = prefix.length;
		
		//add length for optional type + another separator
		if( optionalType != 0 )
			length += 2;
		
		if (!isCaseSensitive){
			//index is case sensitive, thus in case attempting case insensitive search, cannot consider
			//type name.
			name = null;
		} else if( matchMode == PATTERN_MATCH && name != null ){
			int start = 0;

			char [] temp = new char [ name.length ];
			boolean isEscaped = false;
			int tmpIdx = 0;
			for( int i = 0; i < name.length; i++ ){
				if( name[i] == '\\' ){
					if( !isEscaped ){
						isEscaped = true;
						continue;
					} 
					isEscaped = false;		
				} else if( name[i] == '*' && !isEscaped ){
					starPos = i;
					break;
				} 
				temp[ tmpIdx++ ] = name[i];
			}
			
			name = new char [ tmpIdx ];
			System.arraycopy( temp, 0, name, 0, tmpIdx );				
		
			//starPos = CharOperation.indexOf( '*', name );
			questionPos = CharOperation.indexOf( '?', name );

			if( starPos >= 0 ){
				if( questionPos >= 0 )
					wildPos = ( starPos < questionPos ) ? starPos : questionPos;
				else 
					wildPos = starPos;
			} else {
				wildPos = questionPos;
			}
			 
			switch( wildPos ){
				case -1 : break;
				case 0  : name = null;	break;
				default : name = CharOperation.subarray( name, 0, wildPos ); break;
			}
		}
		//add length for name
		if( name != null ){
			length += name.length;
		} else {
			//name is null, don't even consider qualifications.
			result = new char [ length ];
			System.arraycopy( prefix, 0, result, 0, pos = prefix.length );
			if( optionalType != 0){
				result[ pos++ ] = optionalType;
				result[ pos++ ] = SEPARATOR; 
			}
			return result;
		}
		 		
		//add the total length of the qualifiers
		//we don't want to mess with the contents of this array (treat it as constant)
		//so check for wild cards later.
		if( containingTypes != null ){
			for( int i = 0; i < containingTypes.length; i++ ){
				if( containingTypes[i].length > 0 ){
					length += containingTypes[ i ].length;
					length++; //separator
				}
			}
		}
		
		//because we haven't checked qualifier wild cards yet, this array might turn out
		//to be too long. So fill a temp array, then check the length after
		char [] temp = new char [ length ];
		
		System.arraycopy( prefix, 0, temp, 0, pos = prefix.length );
		
		if( optionalType != 0 ){
			temp[ pos++ ] = optionalType;
			temp[ pos++ ] = SEPARATOR;
		}
		
		System.arraycopy( name, 0, temp, pos, name.length );
		pos += name.length;
		
		if( containingTypes != null ){
			for( int i = containingTypes.length - 1; i >= 0; i-- ){
				if( matchMode == PATTERN_MATCH ){
					starPos     = CharOperation.indexOf( '*', containingTypes[i] );
					questionPos = CharOperation.indexOf( '?', containingTypes[i] );

					if( starPos >= 0 ){
						if( questionPos >= 0 )
							wildPos = ( starPos < questionPos ) ? starPos : questionPos;
						else 
							wildPos = starPos;
					} else {
						wildPos = questionPos;
					}
					
					if( wildPos >= 0 ){
						temp[ pos++ ] = SEPARATOR;
						System.arraycopy( containingTypes[i], 0, temp, pos, wildPos );
						pos += starPos;
						break;
					}
				}
				
				if( containingTypes[i].length > 0 ){
					temp[ pos++ ] = SEPARATOR;
					System.arraycopy( containingTypes[i], 0, temp, pos, containingTypes[i].length );
					pos += containingTypes[i].length;
				}
			}
		}
	
		if( pos < length ){
			result = new char[ pos ];
			System.arraycopy( temp, 0, result, 0, pos );	
		} else {
			result = temp;
		}
		
		return result;
	}

	/**
	 * @param _limitTo
	 * @param simpleName
	 * @param _matchMode
	 * @param _caseSensitive
	 * @return
	 */
	public static final char[] bestMacroPrefix( LimitTo limitTo, char[] macroName, int matchMode, boolean isCaseSenstive ){
		//since we only index macro declarations we already know the prefix
		char [] prefix = null;
		if( limitTo == DECLARATIONS ){
			prefix = MACRO_DECL;
		} else {
			return null;
		}
		
		return bestPrefix( prefix,  (char)0, macroName, null, matchMode, isCaseSenstive );	
	}
	
	/**
	 * @param _limitTo
	 * @param simpleName
	 * @param _matchMode
	 * @param _caseSensitive
	 * @return
	 */
	public static final char[] bestIncludePrefix( LimitTo limitTo, char[] incName, int matchMode, boolean isCaseSenstive ){
		//since we only index macro declarations we already know the prefix
		char [] prefix = null;
		if( limitTo == REFERENCES ){
			prefix = INCLUDE_REF;
		} else {
			return null;
		}
		
		return bestPrefix( prefix,  (char)0, incName, null, matchMode, isCaseSenstive );	
	}
	
	public void addInclude(IASTInclusion inclusion, IASTInclusion parent){
		this.output.addIncludeRef(inclusion.getFullFileName());
		this.output.addRelatives(inclusion.getFullFileName(),(parent != null ) ? parent.getFullFileName() : null);
		//Add Dep Table entry
		String[] incName = new String[1];
		incName[0] = inclusion.getFullFileName();
		this.output.addRef(encodeEntry(incName, INCLUDE_REF, INCLUDE_REF_LENGTH));
	}
}

