mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-23 22:52:11 +02:00
Patch for Devin Steffler.
Fixed 79339 - Selection search fails on SDL/SDL.h
This commit is contained in:
parent
bc84af8c5a
commit
29a1fcb59c
6 changed files with 85 additions and 13 deletions
|
@ -14,6 +14,8 @@
|
||||||
*/
|
*/
|
||||||
package org.eclipse.cdt.core.parser.tests;
|
package org.eclipse.cdt.core.parser.tests;
|
||||||
|
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.io.Writer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -21,6 +23,9 @@ import java.util.List;
|
||||||
import junit.framework.Test;
|
import junit.framework.Test;
|
||||||
import junit.framework.TestSuite;
|
import junit.framework.TestSuite;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.parser.ParserLanguage;
|
||||||
|
import org.eclipse.cdt.core.parser.ast.IASTFunction;
|
||||||
|
import org.eclipse.cdt.core.parser.ast.IASTNode;
|
||||||
import org.eclipse.cdt.core.parser.ast.IASTVariable;
|
import org.eclipse.cdt.core.parser.ast.IASTVariable;
|
||||||
import org.eclipse.core.resources.IFile;
|
import org.eclipse.core.resources.IFile;
|
||||||
|
|
||||||
|
@ -187,4 +192,34 @@ public class CompleteParsePluginTest extends FileBasePluginTest {
|
||||||
assertEquals( i.next(), CallbackTracker.EXIT_COMPILATION_UNIT );
|
assertEquals( i.next(), CallbackTracker.EXIT_COMPILATION_UNIT );
|
||||||
assertFalse( i.hasNext() );
|
assertFalse( i.hasNext() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testBug79339() throws Exception{
|
||||||
|
Writer writer = new StringWriter();
|
||||||
|
writer.write("#ifndef _HEADER_\n"); //$NON-NLS-1$
|
||||||
|
writer.write("#define _HEADER_\n"); //$NON-NLS-1$
|
||||||
|
writer.write("#define ONE 1\n"); //$NON-NLS-1$
|
||||||
|
writer.write("int foo(int);\n"); //$NON-NLS-1$
|
||||||
|
writer.write("#endif // _HEADER_\n"); //$NON-NLS-1$
|
||||||
|
String header = writer.toString();
|
||||||
|
importFile( "header.h", header ); //$NON-NLS-1$
|
||||||
|
|
||||||
|
writer = new StringWriter();
|
||||||
|
writer.write( "#include \"header.h\" \n"); //$NON-NLS-1$
|
||||||
|
writer.write( "int foo2(){\n"); //$NON-NLS-1$
|
||||||
|
writer.write( " return foo(ONE);\n"); //$NON-NLS-1$
|
||||||
|
writer.write( "}\n"); //$NON-NLS-1$
|
||||||
|
String source = writer.toString();
|
||||||
|
IFile cpp = importFile( "test.cpp", source ); //$NON-NLS-1$
|
||||||
|
|
||||||
|
int start = source.indexOf( "foo(ONE)" ); //$NON-NLS-1$
|
||||||
|
|
||||||
|
List calls = new ArrayList();
|
||||||
|
IASTNode node = parse( cpp, calls, start, start + 3 ); //$NON-NLS-1$
|
||||||
|
assertTrue(node instanceof IASTFunction);
|
||||||
|
IASTFunction foo = (IASTFunction)node;
|
||||||
|
assertEquals(foo.getStartingLine(), 4);
|
||||||
|
assertEquals(foo.getNameOffset(), 52);
|
||||||
|
assertEquals(foo.getName(), "foo"); //$NON-NLS-1$
|
||||||
|
assertTrue(new String(foo.getFilename()).indexOf("header.h") > 0); //$NON-NLS-1$
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ import java.io.ByteArrayInputStream;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -31,6 +32,7 @@ import org.eclipse.cdt.core.parser.IParser;
|
||||||
import org.eclipse.cdt.core.parser.IProblem;
|
import org.eclipse.cdt.core.parser.IProblem;
|
||||||
import org.eclipse.cdt.core.parser.ISourceElementRequestor;
|
import org.eclipse.cdt.core.parser.ISourceElementRequestor;
|
||||||
import org.eclipse.cdt.core.parser.NullLogService;
|
import org.eclipse.cdt.core.parser.NullLogService;
|
||||||
|
import org.eclipse.cdt.core.parser.NullSourceElementRequestor;
|
||||||
import org.eclipse.cdt.core.parser.ParserFactory;
|
import org.eclipse.cdt.core.parser.ParserFactory;
|
||||||
import org.eclipse.cdt.core.parser.ParserLanguage;
|
import org.eclipse.cdt.core.parser.ParserLanguage;
|
||||||
import org.eclipse.cdt.core.parser.ParserMode;
|
import org.eclipse.cdt.core.parser.ParserMode;
|
||||||
|
@ -58,6 +60,7 @@ import org.eclipse.cdt.core.parser.ast.IASTMethod;
|
||||||
import org.eclipse.cdt.core.parser.ast.IASTMethodReference;
|
import org.eclipse.cdt.core.parser.ast.IASTMethodReference;
|
||||||
import org.eclipse.cdt.core.parser.ast.IASTNamespaceDefinition;
|
import org.eclipse.cdt.core.parser.ast.IASTNamespaceDefinition;
|
||||||
import org.eclipse.cdt.core.parser.ast.IASTNamespaceReference;
|
import org.eclipse.cdt.core.parser.ast.IASTNamespaceReference;
|
||||||
|
import org.eclipse.cdt.core.parser.ast.IASTNode;
|
||||||
import org.eclipse.cdt.core.parser.ast.IASTParameterReference;
|
import org.eclipse.cdt.core.parser.ast.IASTParameterReference;
|
||||||
import org.eclipse.cdt.core.parser.ast.IASTScope;
|
import org.eclipse.cdt.core.parser.ast.IASTScope;
|
||||||
import org.eclipse.cdt.core.parser.ast.IASTTemplateDeclaration;
|
import org.eclipse.cdt.core.parser.ast.IASTTemplateDeclaration;
|
||||||
|
@ -332,5 +335,30 @@ public class FileBasePluginTest extends TestCase {
|
||||||
}
|
}
|
||||||
return callback.getCompilationUnit();
|
return callback.getCompilationUnit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected IASTNode parse(IFile code, List callbacks, int start, int end) throws Exception
|
||||||
|
{
|
||||||
|
return parse(code, callbacks, start, end, true, ParserLanguage.CPP);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IASTNode parse(IFile code, List callbacks, int offset1, int offset2, boolean expectedToPass, ParserLanguage language) throws Exception {
|
||||||
|
callback = new CallbackTracker( callbacks );
|
||||||
|
|
||||||
|
IParser parser = ParserFactory.createParser(
|
||||||
|
ParserFactory.createScanner( new CodeReader( code.getLocation().toOSString(), code.getCharset() ), new ScannerInfo(), //$NON-NLS-1$
|
||||||
|
ParserMode.SELECTION_PARSE, language, callback, new NullLogService(), null ), callback, ParserMode.SELECTION_PARSE, language, null
|
||||||
|
);
|
||||||
|
|
||||||
|
IParser.ISelectionParseResult result =parser.parse( offset1, offset2 );
|
||||||
|
if( expectedToPass )
|
||||||
|
{
|
||||||
|
assertNotNull( result );
|
||||||
|
String filename = result.getFilename();
|
||||||
|
assertNotNull( filename );
|
||||||
|
assertTrue( !filename.equals( "")); //$NON-NLS-1$
|
||||||
|
return (IASTNode) result.getOffsetableNamedElement();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,4 +37,5 @@ public interface IScanner {
|
||||||
public boolean isOnTopContext();
|
public boolean isOnTopContext();
|
||||||
public CharArrayObjectMap getRealDefinitions();
|
public CharArrayObjectMap getRealDefinitions();
|
||||||
public void cancel();
|
public void cancel();
|
||||||
|
public char[] getMainFilename();
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,6 +106,7 @@ public class Parser implements IParserData, IParser
|
||||||
protected int firstErrorLine = FIRST_ERROR_UNSET;
|
protected int firstErrorLine = FIRST_ERROR_UNSET;
|
||||||
private BacktrackException backtrack = new BacktrackException();
|
private BacktrackException backtrack = new BacktrackException();
|
||||||
private int backtrackCount = 0;
|
private int backtrackCount = 0;
|
||||||
|
private char[] parserStartFilename = null;
|
||||||
|
|
||||||
protected final void throwBacktrack( IProblem problem ) throws BacktrackException {
|
protected final void throwBacktrack( IProblem problem ) throws BacktrackException {
|
||||||
++backtrackCount;
|
++backtrackCount;
|
||||||
|
@ -2909,6 +2910,7 @@ public class Parser implements IParserData, IParser
|
||||||
ISourceElementRequestor callback,
|
ISourceElementRequestor callback,
|
||||||
ParserLanguage language, IParserLogService log, IParserExtension extension )
|
ParserLanguage language, IParserLogService log, IParserExtension extension )
|
||||||
{
|
{
|
||||||
|
this.parserStartFilename = scanner.getMainFilename();
|
||||||
this.scanner = scanner;
|
this.scanner = scanner;
|
||||||
this.language = language;
|
this.language = language;
|
||||||
this.log = log;
|
this.log = log;
|
||||||
|
@ -6576,7 +6578,7 @@ public class Parser implements IParserData, IParser
|
||||||
*/
|
*/
|
||||||
protected void handleNewToken(IToken value) {
|
protected void handleNewToken(IToken value) {
|
||||||
if( mode != ParserMode.SELECTION_PARSE ) return;
|
if( mode != ParserMode.SELECTION_PARSE ) return;
|
||||||
if( value != null && scanner.isOnTopContext() )
|
if( value != null && CharArrayUtils.equals(value.getFilename(), parserStartFilename))
|
||||||
{
|
{
|
||||||
TraceUtil.outputTrace(log, "IToken provided w/offsets ", null, value.getOffset(), " & ", value.getEndOffset() ); //$NON-NLS-1$ //$NON-NLS-2$
|
TraceUtil.outputTrace(log, "IToken provided w/offsets ", null, value.getOffset(), " & ", value.getEndOffset() ); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
boolean change = false;
|
boolean change = false;
|
||||||
|
@ -6749,7 +6751,7 @@ public class Parser implements IParserData, IParser
|
||||||
protected void setGreaterNameContext(ITokenDuple tokenDuple) {
|
protected void setGreaterNameContext(ITokenDuple tokenDuple) {
|
||||||
if( mode != ParserMode.SELECTION_PARSE ) return;
|
if( mode != ParserMode.SELECTION_PARSE ) return;
|
||||||
if( pastPointOfSelection ) return;
|
if( pastPointOfSelection ) return;
|
||||||
if( greaterContextDuple == null && scanner.isOnTopContext() && lastTokenOfDuple != null && firstTokenOfDuple != null )
|
if( greaterContextDuple == null && lastTokenOfDuple != null && firstTokenOfDuple != null && CharArrayUtils.equals(tokenDuple.getFilename(), parserStartFilename))
|
||||||
{
|
{
|
||||||
if( tokenDuple.getStartOffset() > lastTokenOfDuple.getEndOffset() )
|
if( tokenDuple.getStartOffset() > lastTokenOfDuple.getEndOffset() )
|
||||||
{
|
{
|
||||||
|
|
|
@ -1395,14 +1395,14 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto
|
||||||
// 5.6 Multiplicative Operators: The operands of * and / shall have arithmetic or enumeration type; the operands of % shall have integral or enumeration type.
|
// 5.6 Multiplicative Operators: The operands of * and / shall have arithmetic or enumeration type; the operands of % shall have integral or enumeration type.
|
||||||
if (kind == IASTExpression.Kind.MULTIPLICATIVE_MULTIPLY || kind == IASTExpression.Kind.MULTIPLICATIVE_DIVIDE) {
|
if (kind == IASTExpression.Kind.MULTIPLICATIVE_MULTIPLY || kind == IASTExpression.Kind.MULTIPLICATIVE_DIVIDE) {
|
||||||
if( !lhs.isType(ITypeInfo.t__Bool, ITypeInfo.t_enumerator ) )
|
if( !lhs.isType(ITypeInfo.t__Bool, ITypeInfo.t_enumerator ) )
|
||||||
handleProblem( scope, IProblem.SEMANTIC_INVALID_CONVERSION_TYPE, null, lhsExp.getStartingOffset(), lhsExp.getEndingOffset(), lhsExp.getStartingLine(), true ); // TODO Devin used to be true
|
handleProblem( scope, IProblem.SEMANTIC_INVALID_CONVERSION_TYPE, null, lhsExp.getStartingOffset(), lhsExp.getEndingOffset(), lhsExp.getStartingLine(), true );
|
||||||
if( !rhs.isType(ITypeInfo.t__Bool, ITypeInfo.t_enumerator ) )
|
if( !rhs.isType(ITypeInfo.t__Bool, ITypeInfo.t_enumerator ) )
|
||||||
handleProblem( scope, IProblem.SEMANTIC_INVALID_CONVERSION_TYPE, null, rhsExp.getStartingOffset(), rhsExp.getEndingOffset(), rhsExp.getStartingLine(), true ); // TODO Devin used to be true
|
handleProblem( scope, IProblem.SEMANTIC_INVALID_CONVERSION_TYPE, null, rhsExp.getStartingOffset(), rhsExp.getEndingOffset(), rhsExp.getStartingLine(), true );
|
||||||
} else if (kind == IASTExpression.Kind.MULTIPLICATIVE_MODULUS) {
|
} else if (kind == IASTExpression.Kind.MULTIPLICATIVE_MODULUS) {
|
||||||
if( !(isIntegralType(lhs, isLhsPointer) || lhs.isType(ITypeInfo.t__Bool, ITypeInfo.t_enumerator ) ))
|
if( !(isIntegralType(lhs, isLhsPointer) || lhs.isType(ITypeInfo.t__Bool, ITypeInfo.t_enumerator ) ))
|
||||||
handleProblem( scope, IProblem.SEMANTIC_INVALID_CONVERSION_TYPE, null, lhsExp.getStartingOffset(), lhsExp.getEndingOffset(), lhsExp.getStartingLine(), true ); // TODO Devin used to be true
|
handleProblem( scope, IProblem.SEMANTIC_INVALID_CONVERSION_TYPE, null, lhsExp.getStartingOffset(), lhsExp.getEndingOffset(), lhsExp.getStartingLine(), true );
|
||||||
if( !(isIntegralType(rhs, isRhsPointer) || rhs.isType(ITypeInfo.t__Bool, ITypeInfo.t_enumerator ) ))
|
if( !(isIntegralType(rhs, isRhsPointer) || rhs.isType(ITypeInfo.t__Bool, ITypeInfo.t_enumerator ) ))
|
||||||
handleProblem( scope, IProblem.SEMANTIC_INVALID_CONVERSION_TYPE, null, rhsExp.getStartingOffset(), rhsExp.getEndingOffset(), rhsExp.getStartingLine(), true ); // TODO Devin used to be true
|
handleProblem( scope, IProblem.SEMANTIC_INVALID_CONVERSION_TYPE, null, rhsExp.getStartingOffset(), rhsExp.getEndingOffset(), rhsExp.getStartingLine(), true );
|
||||||
|
|
||||||
// 5.7 Additive Operators:
|
// 5.7 Additive Operators:
|
||||||
// For addition, either both operands shall have arithmetic or enumeration type, or one operand shall be a
|
// For addition, either both operands shall have arithmetic or enumeration type, or one operand shall be a
|
||||||
|
@ -1416,24 +1416,24 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto
|
||||||
if (!((isLhsPointer && (isIntegralType(rhs, isRhsPointer) || rhs.isType(ITypeInfo.t__Bool, ITypeInfo.t_enumerator ))) ||
|
if (!((isLhsPointer && (isIntegralType(rhs, isRhsPointer) || rhs.isType(ITypeInfo.t__Bool, ITypeInfo.t_enumerator ))) ||
|
||||||
(isRhsPointer && (isIntegralType(lhs, isRhsPointer) || lhs.isType(ITypeInfo.t__Bool, ITypeInfo.t_enumerator ))))) {
|
(isRhsPointer && (isIntegralType(lhs, isRhsPointer) || lhs.isType(ITypeInfo.t__Bool, ITypeInfo.t_enumerator ))))) {
|
||||||
if( !(isIntegralType(lhs, isLhsPointer) || lhs.isType(ITypeInfo.t__Bool, ITypeInfo.t_enumerator )) )
|
if( !(isIntegralType(lhs, isLhsPointer) || lhs.isType(ITypeInfo.t__Bool, ITypeInfo.t_enumerator )) )
|
||||||
handleProblem( scope, IProblem.SEMANTIC_INVALID_CONVERSION_TYPE, null, lhsExp.getStartingOffset(), lhsExp.getEndingOffset(), lhsExp.getStartingLine(), true ); // TODO Devin used to be true
|
handleProblem( scope, IProblem.SEMANTIC_INVALID_CONVERSION_TYPE, null, lhsExp.getStartingOffset(), lhsExp.getEndingOffset(), lhsExp.getStartingLine(), true );
|
||||||
if( !(isIntegralType(rhs, isRhsPointer) || rhs.isType(ITypeInfo.t__Bool, ITypeInfo.t_enumerator )) )
|
if( !(isIntegralType(rhs, isRhsPointer) || rhs.isType(ITypeInfo.t__Bool, ITypeInfo.t_enumerator )) )
|
||||||
handleProblem( scope, IProblem.SEMANTIC_INVALID_CONVERSION_TYPE, null, rhsExp.getStartingOffset(), rhsExp.getEndingOffset(), rhsExp.getStartingLine(), true ); // TODO Devin used to be true
|
handleProblem( scope, IProblem.SEMANTIC_INVALID_CONVERSION_TYPE, null, rhsExp.getStartingOffset(), rhsExp.getEndingOffset(), rhsExp.getStartingLine(), true );
|
||||||
}
|
}
|
||||||
} else if (kind == IASTExpression.Kind.ADDITIVE_MINUS) {
|
} else if (kind == IASTExpression.Kind.ADDITIVE_MINUS) {
|
||||||
if (!(isLhsPointer && (isIntegralType(rhs, isRhsPointer) || rhs.isType(ITypeInfo.t__Bool, ITypeInfo.t_enumerator )))) {
|
if (!(isLhsPointer && (isIntegralType(rhs, isRhsPointer) || rhs.isType(ITypeInfo.t__Bool, ITypeInfo.t_enumerator )))) {
|
||||||
if( !(isIntegralType(lhs, isLhsPointer) || lhs.isType(ITypeInfo.t__Bool, ITypeInfo.t_enumerator )) )
|
if( !(isIntegralType(lhs, isLhsPointer) || lhs.isType(ITypeInfo.t__Bool, ITypeInfo.t_enumerator )) )
|
||||||
handleProblem( scope, IProblem.SEMANTIC_INVALID_CONVERSION_TYPE, null, lhsExp.getStartingOffset(), lhsExp.getEndingOffset(), lhsExp.getStartingLine(), true ); // TODO Devin used to be true
|
handleProblem( scope, IProblem.SEMANTIC_INVALID_CONVERSION_TYPE, null, lhsExp.getStartingOffset(), lhsExp.getEndingOffset(), lhsExp.getStartingLine(), true );
|
||||||
if( !(isIntegralType(rhs, isRhsPointer) || rhs.isType(ITypeInfo.t__Bool, ITypeInfo.t_enumerator )) )
|
if( !(isIntegralType(rhs, isRhsPointer) || rhs.isType(ITypeInfo.t__Bool, ITypeInfo.t_enumerator )) )
|
||||||
handleProblem( scope, IProblem.SEMANTIC_INVALID_CONVERSION_TYPE, null, rhsExp.getStartingOffset(), rhsExp.getEndingOffset(), rhsExp.getStartingLine(), true ); // TODO Devin used to be true
|
handleProblem( scope, IProblem.SEMANTIC_INVALID_CONVERSION_TYPE, null, rhsExp.getStartingOffset(), rhsExp.getEndingOffset(), rhsExp.getStartingLine(), true );
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5.11, 5.12, 5.13: The operator applies only to integral or enumeration operands.
|
// 5.11, 5.12, 5.13: The operator applies only to integral or enumeration operands.
|
||||||
} else if (kind == IASTExpression.Kind.ANDEXPRESSION || kind == IASTExpression.Kind.EXCLUSIVEOREXPRESSION || kind == IASTExpression.Kind.INCLUSIVEOREXPRESSION) {
|
} else if (kind == IASTExpression.Kind.ANDEXPRESSION || kind == IASTExpression.Kind.EXCLUSIVEOREXPRESSION || kind == IASTExpression.Kind.INCLUSIVEOREXPRESSION) {
|
||||||
if( !(isIntegralType(lhs, isLhsPointer) || lhs.isType(ITypeInfo.t__Bool, ITypeInfo.t_enumerator )) )
|
if( !(isIntegralType(lhs, isLhsPointer) || lhs.isType(ITypeInfo.t__Bool, ITypeInfo.t_enumerator )) )
|
||||||
handleProblem( scope, IProblem.SEMANTIC_INVALID_CONVERSION_TYPE, null, lhsExp.getStartingOffset(), lhsExp.getEndingOffset(), lhsExp.getStartingLine(), true ); // TODO Devin used to be true
|
handleProblem( scope, IProblem.SEMANTIC_INVALID_CONVERSION_TYPE, null, lhsExp.getStartingOffset(), lhsExp.getEndingOffset(), lhsExp.getStartingLine(), true );
|
||||||
if( !(isIntegralType(rhs, isRhsPointer) || rhs.isType(ITypeInfo.t__Bool, ITypeInfo.t_enumerator )) )
|
if( !(isIntegralType(rhs, isRhsPointer) || rhs.isType(ITypeInfo.t__Bool, ITypeInfo.t_enumerator )) )
|
||||||
handleProblem( scope, IProblem.SEMANTIC_INVALID_CONVERSION_TYPE, null, rhsExp.getStartingOffset(), rhsExp.getEndingOffset(), rhsExp.getStartingLine(), true ); // TODO Devin used to be true
|
handleProblem( scope, IProblem.SEMANTIC_INVALID_CONVERSION_TYPE, null, rhsExp.getStartingOffset(), rhsExp.getEndingOffset(), rhsExp.getStartingLine(), true );
|
||||||
}
|
}
|
||||||
|
|
||||||
ITypeInfo info = TypeInfoProvider.newTypeInfo( );
|
ITypeInfo info = TypeInfoProvider.newTypeInfo( );
|
||||||
|
|
|
@ -3228,6 +3228,12 @@ public class Scanner2 implements IScanner, IScannerData {
|
||||||
return workingCopies.iterator();
|
return workingCopies.iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public char[] getMainFilename() {
|
||||||
|
if( bufferData != null && bufferData[0] != null && bufferData[0] instanceof CodeReader )
|
||||||
|
return ((CodeReader)bufferData[0]).filename;
|
||||||
|
|
||||||
|
return emptyCharArray;
|
||||||
|
}
|
||||||
|
|
||||||
public final char[] getCurrentFilename() {
|
public final char[] getCurrentFilename() {
|
||||||
for( int i = bufferStackPos; i >= 0; --i )
|
for( int i = bufferStackPos; i >= 0; --i )
|
||||||
|
|
Loading…
Add table
Reference in a new issue