1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-08-04 14:55:41 +02:00

Patch for Andrew Niefer.

core:
  Fixed Bug 36287 - Parser failure with new CDT 1.1 parser
  Fixed Bug 37011 - Scanner: #define A "//" not properly handled
 
UI.tests
  Updated FractionalAutomatedTest to use threads
  Modified ScannerTestCase::testBug36287
  Added ScannerTestCase::testBug37011
  Added ScannerTestCase::testOtherPreprocessorDefines
This commit is contained in:
John Camelon 2003-05-01 20:04:51 +00:00
parent 44ca9f0cc5
commit 805567f342
6 changed files with 250 additions and 113 deletions

View file

@ -1,3 +1,7 @@
2003-05-01 Andrew Niefer
Fixed Bug 36287 - Parser failure with new CDT 1.1 parser
Fixed Bug 37011 - Scanner: #define A "//" not properly handled
2003-04-30 John Camelon 2003-04-30 John Camelon
Added some Javadoc to IParser.java and Parser.java. Added some Javadoc to IParser.java and Parser.java.

View file

@ -120,17 +120,28 @@ public class Scanner implements IScanner {
StringBuffer buffer = new StringBuffer(); StringBuffer buffer = new StringBuffer();
skipOverWhitespace(); skipOverWhitespace();
int c = getChar(); int c = getChar();
boolean inString = false;
boolean inChar = false;
while (true) { while (true) {
while ((c != '\n') while ((c != '\n')
&& (c != '\r') && (c != '\r')
&& (c != '\\') && (c != '\\')
&& (c != '/') && (c != '/')
&& (c != '"' || ( c == '"' && inChar ) )
&& (c != '\'' || ( c == '\'' && inString ) )
&& (c != NOCHAR)) { && (c != NOCHAR)) {
buffer.append((char) c); buffer.append((char) c);
c = getChar(); c = getChar( true );
} }
if (c == '/') { if (c == '/') {
//only care about comments outside of a quote
if( inString || inChar ){
buffer.append( (char) c );
c = getChar( true );
continue;
}
// we need to peek ahead at the next character to see if // we need to peek ahead at the next character to see if
// this is a comment or not // this is a comment or not
int next = getChar(); int next = getChar();
@ -143,7 +154,7 @@ public class Scanner implements IScanner {
if (skipOverMultilineComment()) if (skipOverMultilineComment())
break; break;
else else
c = getChar(); c = getChar( true );
continue; continue;
} else { } else {
// we are not in a comment // we are not in a comment
@ -151,12 +162,35 @@ public class Scanner implements IScanner {
c = next; c = next;
continue; continue;
} }
} else { } else if( c == '"' ){
if (c != '\\') { inString = !inString;
ungetChar(c); buffer.append((char) c);
c = getChar( true );
continue;
} else if( c == '\'' ){
inChar = !inChar;
buffer.append((char) c);
c = getChar( true );
continue;
} else if( c == '\\' ){
c = getChar(true);
if( c == '\r' ){
c = getChar(true);
if( c == '\n' ){
c = getChar(true);
}
} else if( c == '\n' ){
c = getChar(true);
} else { } else {
c = getChar(); buffer.append('\\');
if( c == '"' || c == '\'' ){
buffer.append((char)c);
c = getChar( true );
}
} }
continue;
} else {
ungetChar(c);
break; break;
} }
} }
@ -645,13 +679,23 @@ public class Scanner implements IScanner {
c = getChar(); c = getChar();
if (c == 'x') { if( ! firstCharZero && floatingPoint && !(c >= '0' && c <= '9') ){
if( ! firstCharZero && floatingPoint ) //if pasting, there could actually be a float here instead of just a .
{ if( buff.toString().equals( "." ) ){
ungetChar( c ); if( c == '*' ){
return newToken( Token.tDOT, ".", contextStack.getCurrentContext() ); return newToken( Token.tDOTSTAR, ".*", contextStack.getCurrentContext() );
} else if( c == '.' ){
if( getChar() == '.' )
return newToken( Token.tELIPSE, "..." );
else
throw new ScannerException( "Invalid floating point @ offset " + contextStack.getCurrentContext().getOffset() );
} else {
ungetChar( c );
return newToken( Token.tDOT, ".", contextStack.getCurrentContext() );
}
} }
else if( ! firstCharZero ) } else if (c == 'x') {
if( ! firstCharZero )
throw new ScannerException( "Invalid Hexidecimal @ offset " + contextStack.getCurrentContext().getOffset() ); throw new ScannerException( "Invalid Hexidecimal @ offset " + contextStack.getCurrentContext().getOffset() );
hex = true; hex = true;
@ -668,11 +712,6 @@ public class Scanner implements IScanner {
if( c == '.' ) if( c == '.' )
{ {
buff.append( (char)c); buff.append( (char)c);
if( floatingPoint || hex ) {
if( buff.toString().equals( "..") && getChar() == '.' )
return newToken( Token.tELIPSE, "..." );
throw new ScannerException( "Invalid floating point @ offset " + contextStack.getCurrentContext().getOffset() );
}
floatingPoint = true; floatingPoint = true;
c= getChar(); c= getChar();

View file

@ -1,3 +1,9 @@
2003-05-01 Andrew Niefer
Updated FractionalAutomatedTest to use threads
Modified ScannerTestCase::testBug36287
Added ScannerTestCase::testBug37011
Added ScannerTestCase::testOtherPreprocessorDefines
2003-04-28 John Camelon 2003-04-28 John Camelon
Moved testBug36730() & testBug37019() from DOMFailedTests to DOMTests. Moved testBug36730() & testBug37019() from DOMFailedTests to DOMTests.

View file

@ -18,8 +18,6 @@ import junit.framework.Test;
import junit.framework.TestSuite; import junit.framework.TestSuite;
import org.eclipse.cdt.core.parser.tests.BaseScannerTest; import org.eclipse.cdt.core.parser.tests.BaseScannerTest;
import org.eclipse.cdt.internal.core.parser.ScannerException;
import org.eclipse.cdt.internal.core.parser.Token;
/** /**
* @author aniefer * @author aniefer
@ -38,7 +36,6 @@ public class ScannerFailedTest extends BaseScannerTest {
TestSuite suite = new TestSuite(); TestSuite suite = new TestSuite();
suite.addTest( new ScannerFailedTest( "testBug36701" ) ); suite.addTest( new ScannerFailedTest( "testBug36701" ) );
suite.addTest( new ScannerFailedTest( "testBug37011" ) );
return suite; return suite;
} }
@ -64,27 +61,4 @@ public class ScannerFailedTest extends BaseScannerTest {
fail( "The expected error did not occur." ); fail( "The expected error did not occur." );
} }
public void testBug37011() throws Exception
{
boolean testPassed = false;
try{
StringWriter writer = new StringWriter();
writer.write( "#define A \"//\"\n" );
writer.write( " { A };\n" );
initializeScanner( writer.toString() );
validateToken( Token.tLBRACE );
validateString( "//" );
validateToken( Token.tRBRACE );
validateToken( Token.tSEMI );
validateEOF();
testPassed = true;
} catch( ScannerException e ){
//expected failure
}
if( testPassed )
fail( "The expected error did not occur." );
}
} }

View file

@ -14,14 +14,13 @@ import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException;
import java.io.StringWriter; import java.io.StringWriter;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import junit.framework.AssertionFailedError;
import junit.framework.Test; import junit.framework.Test;
import org.eclipse.cdt.internal.core.parser.IParser;
import org.eclipse.cdt.internal.core.parser.Parser; import org.eclipse.cdt.internal.core.parser.Parser;
import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Path;
@ -57,8 +56,8 @@ public class FractionalAutomatedTest extends AutomatedFramework {
stepSize = Integer.parseInt( properties.getProperty( "stepSize", "50" ) ); stepSize = Integer.parseInt( properties.getProperty( "stepSize", "50" ) );
windowSize = Integer.parseInt( properties.getProperty( "windowSize", "200" ) ); windowSize = Integer.parseInt( properties.getProperty( "windowSize", "200" ) );
timeOut = Integer.parseInt( properties.getProperty( "timeOut", "5000" ));
tempFile = properties.getProperty( "tempFile", "" ); outputDir = properties.getProperty( "outDir", "" );
if( sourceInfo.equals("") ) if( sourceInfo.equals("") )
throw new FileNotFoundException(); throw new FileNotFoundException();
@ -91,95 +90,163 @@ public class FractionalAutomatedTest extends AutomatedFramework {
return frame.createSuite(); return frame.createSuite();
} }
static private void outputTempFile( String code ) { static private String outputFile( String code ) {
if( tempFile == null || tempFile.equals("") ) if( outputDir == null || outputDir.equals("") )
return; return "";
File output = new File( tempFile ); File output = new File( outputDir );
try{ try{
if( output.exists() ){ if( output.exists() ){
output.delete(); if( output.isFile() ){
output.delete();
output.createNewFile();
FileOutputStream stream = new FileOutputStream( output );
stream.write( code.getBytes() );
stream.flush();
stream.close();
return outputDir;
}
} else {
output.mkdir();
} }
File file = new File( outputDir + "/" + failures++ + ".tmp" );
output.createNewFile(); if( file.exists() )
FileOutputStream stream = new FileOutputStream( output ); file.delete();
file.createNewFile();
FileOutputStream stream = new FileOutputStream( file );
stream.write( code.getBytes() ); stream.write( code.getBytes() );
stream.flush(); stream.flush();
stream.close(); stream.close();
return file.getCanonicalPath();
} catch ( Exception e ) } catch ( Exception e )
{} {}
return "";
}
static private void reportHang( String code, String file ){
String output = outputFile( code.toString() );
if( output.equals("") )
output = "Parser hang while parsing " + file + "\n";
else
output = "Parser hang while parsing " + output + "\n";
if( report != null ){
try{
report.write( output.getBytes() );
} catch ( IOException e ) {}
}
fail( output );
}
static private void reportException( String code, String file, String exception ){
String output = outputFile( code.toString() );
if( output.equals("") )
output = exception.getClass().toString() + " encountered in " + file + "\n";
else
output = exception.getClass().toString() + " encountered in " + output + "\n";
if( report != null ){
try{
report.write( output.getBytes() );
} catch ( IOException e ) {}
}
fail( output );
} }
public void doFile() throws Throwable { public void doFile() throws Throwable {
assertNotNull( fileList ); assertNotNull( fileList );
File file = null; File file = (File)fileList.removeFirst();
IParser parser = null; FileInputStream stream = new FileInputStream( file );
String filePath = file.getCanonicalPath();
String nature = (String)natures.get( filePath );
boolean cppNature = nature.equalsIgnoreCase("cpp");
try{ StringWriter code = new StringWriter();
file = (File)fileList.removeFirst();
FileInputStream stream = new FileInputStream( file ); ParseThread thread = new ParseThread();
byte b[] = new byte[stepSize];
int n = stream.read( b );
while( n != -1 ){
code.write( new String( b ) );
String filePath = file.getCanonicalPath(); thread.code = code.toString();
String nature = (String)natures.get( filePath ); thread.cppNature = cppNature;
thread.start();
boolean cppNature = nature.equalsIgnoreCase("cpp"); thread.join( timeOut );
StringWriter code = new StringWriter(); if( thread.isAlive() ){
//Use deprecated Thread.stop() for now
byte b[] = new byte[stepSize]; //alternative is to create a callback which could stop the parse on a flag
int n = stream.read( b ); //by throwing something, but that has the disadvantage of being unable to
while( n != -1 ){ //stop any loops that don't involve callbacks.
code.write( new String( b ) ); thread.stop();
parser = new Parser( code.toString(), nullCallback, true); reportHang( code.toString(), filePath );
parser.setCppNature( cppNature ); } else if( thread.result != null ) {
parser.mapLineNumbers(true); reportException( code.toString(), filePath, thread.result );
outputTempFile( code.toString() );
parser.parse();
n = stream.read( b );
} }
String fullCode = code.toString(); n = stream.read( b );
String windowedCode = null; }
int length = fullCode.length();
int curPos = 0; String fullCode = code.toString();
String windowedCode = null;
int length = fullCode.length();
int curPos = 0;
while( curPos + windowSize < length){
windowedCode = fullCode.substring( 0, curPos );
windowedCode += "\n" + fullCode.substring( curPos + windowSize, length );
while( curPos + windowSize < length){ thread.code = windowedCode;
windowedCode = fullCode.substring( 0, curPos ); thread.cppNature = cppNature;
windowedCode += "\n" + fullCode.substring( curPos + windowSize, length ); thread.file = filePath;
thread.start();
parser = new Parser( windowedCode, nullCallback, true ); thread.join( timeOut );
parser.setCppNature( cppNature );
parser.mapLineNumbers(true);
outputTempFile( windowedCode ); if( thread.isAlive() )
parser.parse(); {
thread.stop();
curPos += stepSize; reportHang( windowedCode, filePath );
} } else if( thread.result != null ) {
} reportException( windowedCode, filePath, thread.result );
catch( Throwable e )
{
String output = null;
if( e instanceof AssertionFailedError ){
output = file.getCanonicalPath() + ": Parse failed on line ";
output += parser.getLineNumberForOffset(parser.getLastErrorOffset()) + "\n";
} else {
output = file.getCanonicalPath() + ": " + e.getClass().toString();
output += " on line " + parser.getLineNumberForOffset(parser.getLastErrorOffset()) + "\n";
}
if( report != null ){
report.write( output.getBytes() );
} }
fail( output ); curPos += stepSize;
} }
} }
static class ParseThread extends Thread{
public String code;
public boolean cppNature;
public String file;
public String result;
public void run(){
try{
result = null;
Parser parser = new Parser( code, nullCallback, true);
parser.setCppNature( cppNature );
parser.mapLineNumbers(true);
parser.parse();
} catch ( Exception e ){
result = e.getClass().toString();
}
}
}
static private int stepSize = 50; static private int stepSize = 50;
static private int windowSize = 200; static private int windowSize = 200;
static private String tempFile = null; static private int timeOut = 5000;
static private String outputDir = null;
static private int failures = 0;
} }

View file

@ -995,7 +995,7 @@ public class ScannerTestCase extends BaseScannerTest
public void testBug36287() throws Exception public void testBug36287() throws Exception
{ {
initializeScanner( "X::X( const X & rtg_arg ) : U( rtg_arg ) , Z( rtg_arg.Z ) , br( rtg_arg.br ){}" ); initializeScanner( "X::X( const X & rtg_arg ) : U( rtg_arg ) , Z( rtg_arg.Z ) , er( rtg_arg.er ){}" );
validateIdentifier("X"); validateIdentifier("X");
validateToken( Token.tCOLONCOLON); validateToken( Token.tCOLONCOLON);
validateIdentifier("X"); validateIdentifier("X");
@ -1018,15 +1018,27 @@ public class ScannerTestCase extends BaseScannerTest
validateIdentifier( "Z"); validateIdentifier( "Z");
validateToken( Token.tRPAREN ); validateToken( Token.tRPAREN );
validateToken( Token.tCOMMA ); validateToken( Token.tCOMMA );
validateIdentifier( "br"); validateIdentifier( "er");
validateToken( Token.tLPAREN ); validateToken( Token.tLPAREN );
validateIdentifier( "rtg_arg"); validateIdentifier( "rtg_arg");
validateToken( Token.tDOT ); validateToken( Token.tDOT );
validateIdentifier( "br"); validateIdentifier( "er");
validateToken( Token.tRPAREN ); validateToken( Token.tRPAREN );
validateToken( Token.tLBRACE); validateToken( Token.tLBRACE);
validateToken( Token.tRBRACE); validateToken( Token.tRBRACE);
validateEOF(); validateEOF();
initializeScanner( "foo.*bar");
validateIdentifier("foo");
validateToken( Token.tDOTSTAR );
validateIdentifier("bar");
validateEOF();
initializeScanner( "foo...bar");
validateIdentifier("foo");
validateToken( Token.tELIPSE );
validateIdentifier("bar");
validateEOF();
} }
public void testBug35892() public void testBug35892()
@ -1309,4 +1321,39 @@ public class ScannerTestCase extends BaseScannerTest
initializeScanner( writer.toString() ); initializeScanner( writer.toString() );
validateEOF(); validateEOF();
} }
public void testBug37011() throws Exception{
StringWriter writer = new StringWriter();
writer.write( "#define A \"//\"");
initializeScanner( writer.toString() );
validateEOF();
validateDefinition("A", "\"//\"");
}
public void testOtherPreprocessorDefines() throws Exception{
StringWriter writer = new StringWriter();
writer.write( "#define A a//boo\n" );
writer.write( "#define B a /*boo*/ a\n" );
writer.write( "#define C a \" //boo \"\n" );
writer.write( "#define D a \\\"//boo\n" );
writer.write( "#define E a \\n \"\\\"\"\n" );
writer.write( "#define F a\\\n b\n" );
writer.write( "#define G a '\"'//boo\n" );
writer.write( "#define H a '\\'//b'\"/*bo\\o*/\" b\n" );
initializeScanner( writer.toString() );
validateEOF();
validateDefinition("A", "a");
validateDefinition("B", "a a");
validateDefinition("C", "a \" //boo \"");
validateDefinition("D", "a \\\"");
validateDefinition("E", "a \\n \"\\\"\"");
validateDefinition("F", "a b");
validateDefinition("G", "a '\"'");
validateDefinition("H", "a '\\'//b'\"/*bo\\o*/\" b");
}
} }