diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java index 038ae573188..5898477ab65 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java @@ -29,13 +29,16 @@ import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; import org.eclipse.cdt.core.dom.ast.IASTIdExpression; import org.eclipse.cdt.core.dom.ast.IASTIfStatement; +import org.eclipse.cdt.core.dom.ast.IASTInitializer; import org.eclipse.cdt.core.dom.ast.IASTInitializerExpression; +import org.eclipse.cdt.core.dom.ast.IASTInitializerList; import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNamedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration; import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclSpecifier; import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTStatement; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression; import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression; @@ -57,7 +60,9 @@ import org.eclipse.cdt.core.dom.ast.ITypedef; import org.eclipse.cdt.core.dom.ast.IVariable; import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator; import org.eclipse.cdt.core.dom.ast.c.ICASTCompositeTypeSpecifier; +import org.eclipse.cdt.core.dom.ast.c.ICASTDesignatedInitializer; import org.eclipse.cdt.core.dom.ast.c.ICASTEnumerationSpecifier; +import org.eclipse.cdt.core.dom.ast.c.ICASTFieldDesignator; import org.eclipse.cdt.core.dom.ast.c.ICASTPointer; import org.eclipse.cdt.core.dom.ast.c.ICArrayType; import org.eclipse.cdt.core.dom.ast.c.ICFunctionScope; @@ -1129,5 +1134,37 @@ public class AST2Tests extends AST2BaseTest { assertEquals( h_ps.length, 1 ); assertTrue( h_ps[0] instanceof IBasicType ); } + + public void testDesignatedInitializers() throws ParserException + { + StringBuffer buffer = new StringBuffer( "typedef struct {\n" ); //$NON-NLS-1$ + buffer.append( " int x;\n" ); //$NON-NLS-1$ + buffer.append( " int y;\n" ); //$NON-NLS-1$ + buffer.append( "} Coord;\n" ); //$NON-NLS-1$ + buffer.append( "typedef struct {\n" ); //$NON-NLS-1$ + buffer.append( "Coord *pos;\n" ); //$NON-NLS-1$ + buffer.append( "int width;\n" ); //$NON-NLS-1$ + buffer.append( "} Point;\n" ); //$NON-NLS-1$ + buffer.append( "int main(int argc, char *argv[])\n" ); //$NON-NLS-1$ + buffer.append( "{\n" ); //$NON-NLS-1$ + buffer.append( "Coord xy = {.y = 10, .x = 11};\n" ); //$NON-NLS-1$ + buffer.append( "Point point = {.width = 100, .pos = &xy};\n" ); //$NON-NLS-1$ + buffer.append( "}\n" ); //$NON-NLS-1$ + IASTTranslationUnit tu = parse( buffer.toString(), ParserLanguage.C ); + assertNotNull( tu ); + IASTDeclaration []declarations = tu.getDeclarations(); + IASTFunctionDefinition main = (IASTFunctionDefinition) declarations[2]; + IASTStatement [] statements = ((IASTCompoundStatement)main.getBody()).getStatements(); + IASTSimpleDeclaration xy = (IASTSimpleDeclaration) ((IASTDeclarationStatement)statements[0]).getDeclaration(); + IASTDeclarator declarator_xy = xy.getDeclarators()[0]; + IASTInitializer [] initializers = ((IASTInitializerList) declarator_xy.getInitializer()).getInitializers(); + for( int i = 0; i < 2; ++i ) + { + ICASTDesignatedInitializer designatedInitializer = (ICASTDesignatedInitializer) initializers[i]; + assertEquals( designatedInitializer.getDesignators().length, 1 ); + ICASTFieldDesignator fieldDesignator = (ICASTFieldDesignator) designatedInitializer.getDesignators()[0]; + assertNotNull( fieldDesignator.getName().toString() ); + } + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/c/ICASTDesignatedInitializer.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/c/ICASTDesignatedInitializer.java new file mode 100644 index 00000000000..2d33d5361d6 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/c/ICASTDesignatedInitializer.java @@ -0,0 +1,30 @@ +/********************************************************************** + * Copyright (c) 2004 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 - Initial API and implementation + **********************************************************************/ +package org.eclipse.cdt.core.dom.ast.c; + +import org.eclipse.cdt.core.dom.ast.ASTNodeProperty; +import org.eclipse.cdt.core.dom.ast.IASTInitializer; + +/** + * @author jcamelon + */ +public interface ICASTDesignatedInitializer extends + IASTInitializer { + + public static final ICASTDesignator [] EMPTY_DESIGNATOR_ARRAY = new ICASTDesignator[0]; + public static final ASTNodeProperty DESIGNATOR = new ASTNodeProperty( "Designator"); //$NON-NLS-1$ + public void addDesignator( ICASTDesignator designator ); + public ICASTDesignator [] getDesignators(); + + public static final ASTNodeProperty RHS_INITIALIZER = new ASTNodeProperty( "RHS Initializer"); //$NON-NLS-1$ + public IASTInitializer getRHSInitializer(); + public void setRHSInitializer( IASTInitializer rhs ); +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTDesignatedInitializer.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTDesignatedInitializer.java new file mode 100644 index 00000000000..63a35bd445d --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTDesignatedInitializer.java @@ -0,0 +1,84 @@ +/********************************************************************** + * Copyright (c) 2004 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 - Initial API and implementation + **********************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.c; + +import org.eclipse.cdt.core.dom.ast.IASTInitializer; +import org.eclipse.cdt.core.dom.ast.c.ICASTDesignatedInitializer; +import org.eclipse.cdt.core.dom.ast.c.ICASTDesignator; + +/** + * @author jcamelon + */ +public class CASTDesignatedInitializer extends CASTNode implements + ICASTDesignatedInitializer { + + private IASTInitializer rhs; + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.dom.ast.c.ICASTDesignatedInitializer#addDesignator(org.eclipse.cdt.core.dom.ast.c.ICASTDesignator) + */ + public void addDesignator(ICASTDesignator designator) { + if( designators == null ) + { + designators = new ICASTDesignator[ DEFAULT_DESIGNATORS_LIST_SIZE ]; + currentIndex = 0; + } + if( designators.length == currentIndex ) + { + ICASTDesignator [] old = designators; + designators = new ICASTDesignator[ old.length * 2 ]; + for( int i = 0; i < old.length; ++i ) + designators[i] = old[i]; + } + designators[ currentIndex++ ] = designator; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.dom.ast.c.ICASTDesignatedInitializer#getDesignators() + */ + public ICASTDesignator[] getDesignators() { + if( designators == null ) return ICASTDesignatedInitializer.EMPTY_DESIGNATOR_ARRAY; + removeNullDesignators(); + return designators; + } + + private void removeNullDesignators() { + int nullCount = 0; + for( int i = 0; i < designators.length; ++i ) + if( designators[i] == null ) + ++nullCount; + if( nullCount == 0 ) return; + ICASTDesignator [] old = designators; + int newSize = old.length - nullCount; + designators = new ICASTDesignator[ newSize ]; + for( int i = 0; i < newSize; ++i ) + designators[i] = old[i]; + currentIndex = newSize; + } + + private int currentIndex = 0; + private ICASTDesignator [] designators = null; + private static final int DEFAULT_DESIGNATORS_LIST_SIZE = 2; + /* (non-Javadoc) + * @see org.eclipse.cdt.core.dom.ast.c.ICASTDesignatedInitializer#getRHSInitializer() + */ + public IASTInitializer getRHSInitializer() { + return rhs; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.dom.ast.c.ICASTDesignatedInitializer#setRHSInitializer(org.eclipse.cdt.core.dom.ast.IASTInitializer) + */ + public void setRHSInitializer(IASTInitializer rhs) { + this.rhs = rhs; + } + +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java index 9feaea26fd5..c1765a74435 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java @@ -70,6 +70,8 @@ import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator; import org.eclipse.cdt.core.dom.ast.c.ICASTArrayDesignator; import org.eclipse.cdt.core.dom.ast.c.ICASTArrayModifier; import org.eclipse.cdt.core.dom.ast.c.ICASTCompositeTypeSpecifier; +import org.eclipse.cdt.core.dom.ast.c.ICASTDesignatedInitializer; +import org.eclipse.cdt.core.dom.ast.c.ICASTDesignator; import org.eclipse.cdt.core.dom.ast.c.ICASTElaboratedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.c.ICASTFieldDesignator; import org.eclipse.cdt.core.dom.ast.c.ICASTPointer; @@ -145,7 +147,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { char[] fn = la.getFilename(); la = null; if (LT(1) == IToken.tLBRACE) { - consume(IToken.tLBRACE).getOffset(); + consume(IToken.tLBRACE); IASTInitializerList result = createInitializerList(); ((ASTNode)result).setOffset( startingOffset ); for (;;) { @@ -156,10 +158,33 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { if (newDesignators.size() != 0) if (LT(1) == IToken.tASSIGN) consume(IToken.tASSIGN); + IASTInitializer initializer = cInitializerClause(newDesignators); - result.addInitializer(initializer); - initializer.setParent( result ); - initializer.setPropertyInParent( IASTInitializerList.NESTED_INITIALIZER ); + + if( newDesignators.isEmpty() ) + { + result.addInitializer(initializer); + initializer.setParent( result ); + initializer.setPropertyInParent( IASTInitializerList.NESTED_INITIALIZER ); + } + else + { + ICASTDesignatedInitializer desigInitializer = createDesignatorInitializer(); + ((CASTNode)desigInitializer).setOffset( ((CASTNode)newDesignators.get(0)).getOffset()); + for( int i = 0; i < newDesignators.size(); ++i ) + { + ICASTDesignator d = (ICASTDesignator) newDesignators.get(i); + d.setParent( desigInitializer ); + d.setPropertyInParent( ICASTDesignatedInitializer.DESIGNATOR ); + desigInitializer.addDesignator( d ); + } + desigInitializer.setRHSInitializer(initializer); + initializer.setParent( desigInitializer ); + initializer.setPropertyInParent( ICASTDesignatedInitializer.RHS_INITIALIZER ); + result.addInitializer( desigInitializer ); + desigInitializer.setParent( result ); + desigInitializer.setPropertyInParent( IASTInitializerList.NESTED_INITIALIZER ); + } // can end with just a '}' if (LT(1) == IToken.tRBRACE) break; @@ -201,6 +226,13 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { return null; } + /** + * @return + */ + protected ICASTDesignatedInitializer createDesignatorInitializer() { + return new CASTDesignatedInitializer(); + } + /** * @return */ diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/BaseScanner.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/BaseScanner.java index f7a5bb4d3be..0a6df033bb9 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/BaseScanner.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/BaseScanner.java @@ -39,11 +39,7 @@ import org.eclipse.cdt.core.parser.util.CharArrayObjectMap; import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.internal.core.parser.ast.ASTCompletionNode; import org.eclipse.cdt.internal.core.parser.ast.EmptyIterator; -import org.eclipse.cdt.internal.core.parser.token.ImagedExpansionToken; -import org.eclipse.cdt.internal.core.parser.token.ImagedToken; import org.eclipse.cdt.internal.core.parser.token.KeywordSets; -import org.eclipse.cdt.internal.core.parser.token.SimpleExpansionToken; -import org.eclipse.cdt.internal.core.parser.token.SimpleToken; /** * @author Doug Schaefer @@ -1887,39 +1883,6 @@ abstract class BaseScanner implements IScanner { return null; } - /** - * @return - */ - protected IToken newToken( int signal ) { - if( bufferData[bufferStackPos] instanceof MacroData ) - { - int mostRelevant; - for( mostRelevant = bufferStackPos; mostRelevant >= 0; --mostRelevant ) - if( bufferData[mostRelevant] instanceof InclusionData || bufferData[mostRelevant] instanceof CodeReader ) - break; - MacroData data = (MacroData)bufferData[mostRelevant + 1]; - return new SimpleExpansionToken( signal, data.startOffset, data.endOffset - data.startOffset + 1, getCurrentFilename(), getLineNumber( bufferPos[mostRelevant] + 1)); - } - return new SimpleToken(signal, bufferPos[bufferStackPos] + 1 , getCurrentFilename(), getLineNumber( bufferPos[bufferStackPos] + 1) ); - } - - protected IToken newToken( int signal, char [] buffer ) - { - if( bufferData[bufferStackPos] instanceof MacroData ) - { - int mostRelevant; - for( mostRelevant = bufferStackPos; mostRelevant >= 0; --mostRelevant ) - if( bufferData[mostRelevant] instanceof InclusionData || bufferData[mostRelevant] instanceof CodeReader ) - break; - MacroData data = (MacroData)bufferData[mostRelevant + 1]; - return new ImagedExpansionToken( signal, buffer, data.startOffset, data.endOffset - data.startOffset + 1, getCurrentFilename(), getLineNumber( bufferPos[mostRelevant] + 1)); - } - IToken i = new ImagedToken(signal, buffer, bufferPos[bufferStackPos] + 1 , getCurrentFilename(), getLineNumber( bufferPos[bufferStackPos] + 1)); - if( buffer != null && buffer.length == 0 && signal != IToken.tSTRING && signal != IToken.tLSTRING ) - bufferPos[bufferStackPos] += 1; //TODO - remove this hack at some point - - return i; - } protected IToken scanIdentifier() { char[] buffer = bufferStack[bufferStackPos]; @@ -4431,4 +4394,8 @@ abstract class BaseScanner implements IScanner { buffer.append( getLineNumber( getCurrentOffset())); return buffer.toString(); } + + protected abstract IToken newToken( int signal ); + protected abstract IToken newToken( int signal, char [] buffer ); + } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/DOMScanner.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/DOMScanner.java index 4cb7505c0a2..a802752da2e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/DOMScanner.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/DOMScanner.java @@ -15,9 +15,14 @@ import org.eclipse.cdt.core.dom.ICodeReaderFactory; import org.eclipse.cdt.core.parser.CodeReader; import org.eclipse.cdt.core.parser.IParserLogService; import org.eclipse.cdt.core.parser.IScannerInfo; +import org.eclipse.cdt.core.parser.IToken; import org.eclipse.cdt.core.parser.ParserLanguage; import org.eclipse.cdt.core.parser.ParserMode; import org.eclipse.cdt.core.parser.ast.IASTFactory; +import org.eclipse.cdt.internal.core.parser.token.ImagedExpansionToken; +import org.eclipse.cdt.internal.core.parser.token.ImagedToken; +import org.eclipse.cdt.internal.core.parser.token.SimpleExpansionToken; +import org.eclipse.cdt.internal.core.parser.token.SimpleToken; /** * @author jcamelon @@ -25,6 +30,7 @@ import org.eclipse.cdt.core.parser.ast.IASTFactory; public class DOMScanner extends BaseScanner { private final ICodeReaderFactory codeReaderFactory; + private int overallOffset = 0; /** @@ -86,4 +92,38 @@ public class DOMScanner extends BaseScanner { } + /** + * @return + */ + protected IToken newToken( int signal ) { + if( bufferData[bufferStackPos] instanceof MacroData ) + { + int mostRelevant; + for( mostRelevant = bufferStackPos; mostRelevant >= 0; --mostRelevant ) + if( bufferData[mostRelevant] instanceof InclusionData || bufferData[mostRelevant] instanceof CodeReader ) + break; + MacroData data = (MacroData)bufferData[mostRelevant + 1]; + return new SimpleExpansionToken( signal, data.startOffset, data.endOffset - data.startOffset + 1, getCurrentFilename(), getLineNumber( bufferPos[mostRelevant] + 1)); + } + return new SimpleToken(signal, bufferPos[bufferStackPos] + 1 , getCurrentFilename(), getLineNumber( bufferPos[bufferStackPos] + 1) ); + } + + protected IToken newToken( int signal, char [] buffer ) + { + if( bufferData[bufferStackPos] instanceof MacroData ) + { + int mostRelevant; + for( mostRelevant = bufferStackPos; mostRelevant >= 0; --mostRelevant ) + if( bufferData[mostRelevant] instanceof InclusionData || bufferData[mostRelevant] instanceof CodeReader ) + break; + MacroData data = (MacroData)bufferData[mostRelevant + 1]; + return new ImagedExpansionToken( signal, buffer, data.startOffset, data.endOffset - data.startOffset + 1, getCurrentFilename(), getLineNumber( bufferPos[mostRelevant] + 1)); + } + IToken i = new ImagedToken(signal, buffer, bufferPos[bufferStackPos] + 1 , getCurrentFilename(), getLineNumber( bufferPos[bufferStackPos] + 1)); + if( buffer != null && buffer.length == 0 && signal != IToken.tSTRING && signal != IToken.tLSTRING ) + bufferPos[bufferStackPos] += 1; //TODO - remove this hack at some point + + return i; + } + } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/Scanner2.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/Scanner2.java index c8920873ab3..17f0843a5e0 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/Scanner2.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/Scanner2.java @@ -18,11 +18,16 @@ import org.eclipse.cdt.core.parser.IParserLogService; import org.eclipse.cdt.core.parser.IProblem; import org.eclipse.cdt.core.parser.IScannerInfo; import org.eclipse.cdt.core.parser.ISourceElementRequestor; +import org.eclipse.cdt.core.parser.IToken; import org.eclipse.cdt.core.parser.ParserFactory; import org.eclipse.cdt.core.parser.ParserLanguage; import org.eclipse.cdt.core.parser.ParserMode; import org.eclipse.cdt.core.parser.ast.IASTFactory; import org.eclipse.cdt.internal.core.parser.ast.EmptyIterator; +import org.eclipse.cdt.internal.core.parser.token.ImagedExpansionToken; +import org.eclipse.cdt.internal.core.parser.token.ImagedToken; +import org.eclipse.cdt.internal.core.parser.token.SimpleExpansionToken; +import org.eclipse.cdt.internal.core.parser.token.SimpleToken; /** * @author jcamelon @@ -161,5 +166,40 @@ public class Scanner2 extends BaseScanner { if( workingCopies == null ) return EmptyIterator.EMPTY_ITERATOR; return workingCopies.iterator(); } + + /** + * @return + */ + protected IToken newToken( int signal ) { + if( bufferData[bufferStackPos] instanceof MacroData ) + { + int mostRelevant; + for( mostRelevant = bufferStackPos; mostRelevant >= 0; --mostRelevant ) + if( bufferData[mostRelevant] instanceof InclusionData || bufferData[mostRelevant] instanceof CodeReader ) + break; + MacroData data = (MacroData)bufferData[mostRelevant + 1]; + return new SimpleExpansionToken( signal, data.startOffset, data.endOffset - data.startOffset + 1, getCurrentFilename(), getLineNumber( bufferPos[mostRelevant] + 1)); + } + return new SimpleToken(signal, bufferPos[bufferStackPos] + 1 , getCurrentFilename(), getLineNumber( bufferPos[bufferStackPos] + 1) ); + } + + protected IToken newToken( int signal, char [] buffer ) + { + if( bufferData[bufferStackPos] instanceof MacroData ) + { + int mostRelevant; + for( mostRelevant = bufferStackPos; mostRelevant >= 0; --mostRelevant ) + if( bufferData[mostRelevant] instanceof InclusionData || bufferData[mostRelevant] instanceof CodeReader ) + break; + MacroData data = (MacroData)bufferData[mostRelevant + 1]; + return new ImagedExpansionToken( signal, buffer, data.startOffset, data.endOffset - data.startOffset + 1, getCurrentFilename(), getLineNumber( bufferPos[mostRelevant] + 1)); + } + IToken i = new ImagedToken(signal, buffer, bufferPos[bufferStackPos] + 1 , getCurrentFilename(), getLineNumber( bufferPos[bufferStackPos] + 1)); + if( buffer != null && buffer.length == 0 && signal != IToken.tSTRING && signal != IToken.tLSTRING ) + bufferPos[bufferStackPos] += 1; //TODO - remove this hack at some point + + return i; + } + } \ No newline at end of file