blob: 5949a616bd3830e2256c1f209c8ff07ea544b003 [file] [log] [blame]
package org.eclipse.cdt.core.parser.tests;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.cdt.core.parser.EndOfFileException;
import org.eclipse.cdt.core.parser.IMacroDescriptor;
import org.eclipse.cdt.core.parser.IProblem;
import org.eclipse.cdt.core.parser.ISourceElementRequestor;
import org.eclipse.cdt.core.parser.IToken;
import org.eclipse.cdt.core.parser.NullSourceElementRequestor;
import org.eclipse.cdt.core.parser.ParserFactoryException;
import org.eclipse.cdt.core.parser.ParserMode;
import org.eclipse.cdt.core.parser.ScannerException;
import org.eclipse.cdt.core.parser.ast.IASTInclusion;
import org.eclipse.cdt.internal.core.parser.Token;
/**
* @author jcamelon
*
* To change this generated comment edit the template variable "typecomment":
* Window>Preferences>Java>Templates.
* To enable and disable the creation of type comments go to
* Window>Preferences>Java>Code Generation.
*/
public class ScannerTestCase extends BaseScannerTest
{
public class TableRow
{
private int[] values;
private int length;
public TableRow(int[] v)
{
length= v.length;
values= new int[length];
System.arraycopy(v, 0, values, 0, length);
}
public String toString()
{
StringBuffer s= new StringBuffer();
for (int i= 0; i < length; ++i)
{
s.append("var").append(i).append("=").append(values[i]).append(" ");
}
return s.toString();
}
public String symbolName(int index)
{
return "DEFINITION" + index;
}
public int symbolValue(int index)
{
return new Long(Math.round(Math.pow(index, index))).intValue();
}
public String generateCode()
{
if (length < 2)
{
return "Array must have at least 2 elements";
}
int numberOfElsifs= length - 1;
StringBuffer buffer= new StringBuffer();
buffer.append("#if ").append(values[0]).append("\n#\tdefine ");
buffer.append(symbolName(0)).append(" ").append(symbolValue(0));
for (int i= 0; i < numberOfElsifs; ++i)
buffer
.append("\n#elif ")
.append(values[1 + i])
.append("\n#\tdefine ")
.append(symbolName(i + 1))
.append(" ")
.append(symbolValue(i + 1));
buffer
.append("\n#else \n#\tdefine ")
.append(symbolName(length))
.append(" ")
.append(symbolValue(length))
.append("\n#endif");
return buffer.toString();
}
public int selectWinner()
{
for (int i= 0; i < values.length; ++i)
{
if (values[i] != 0)
{
return i;
}
}
return length;
}
/**
* Returns the length.
* @return int
*/
public int getLength()
{
return length;
}
}
public class TruthTable
{
private int numberOfVariables;
private int numberOfRows;
public TableRow[] rows;
public TruthTable(int n)
{
numberOfVariables= n;
numberOfRows= new Long(Math.round(Math.pow(2, n))).intValue();
rows= new TableRow[numberOfRows];
for (int i= 0; i < numberOfRows; ++i)
{
String Z= Integer.toBinaryString(i);
int[] input= new int[numberOfVariables];
for (int j= 0; j < numberOfVariables; ++j)
{
int padding= numberOfVariables - Z.length();
int k= 0;
for (; k < padding; ++k)
{
input[k]= 0;
}
for (int l= 0; l < Z.length(); ++l)
{
char c= Z.charAt(l);
int value= Character.digit(c, 10);
input[k++]= value;
}
}
rows[i]= new TableRow(input);
}
}
/**
* Returns the numberOfRows.
* @return int
*/
public int getNumberOfRows()
{
return numberOfRows;
}
}
public final static boolean doIncludeStdio= false;
public final static boolean doIncludeWindowsH= false;
public final static boolean doIncludeWinUserH= false;
public final static int SIZEOF_TRUTHTABLE = 10;
public void testWeirdStrings() throws Exception
{
try
{
initializeScanner( "Living Life L\"LONG\"");
validateIdentifier( "Living" );
validateIdentifier( "Life" );
validateString("LONG", true);
validateEOF();
}
catch( ScannerException se )
{
fail(EXCEPTION_THROWN + se.toString());
}
}
public void testNumerics()throws Exception
{
try
{
initializeScanner("3.0 0.9 .5 3. 4E5 2.01E-03 ...");
validateFloatingPointLiteral( "3.0");
validateFloatingPointLiteral( "0.9");
validateFloatingPointLiteral( ".5");
validateFloatingPointLiteral( "3.");
validateFloatingPointLiteral( "4E5");
validateFloatingPointLiteral( "2.01E-03" );
validateToken( IToken.tELLIPSIS );
validateEOF();
}
catch( ScannerException se )
{
fail(EXCEPTION_THROWN + se.toString());
}
}
/**
* Constructor for ScannerTestCase.
* @param name
*/
public ScannerTestCase(String name)
{
super(name);
}
public void testPreprocessorDefines()throws Exception
{
try
{
initializeScanner("#define SIMPLE_NUMERIC 5\nint x = SIMPLE_NUMERIC");
validateToken(IToken.t_int);
validateDefinition("SIMPLE_NUMERIC", "5");
validateIdentifier("x");
validateToken(IToken.tASSIGN);
validateInteger("5");
validateEOF();
initializeScanner("#define SIMPLE_STRING \"This is a simple string.\"\n\nconst char * myVariable = SIMPLE_STRING;");
validateToken(IToken.t_const);
validateDefinition("SIMPLE_STRING", "\"This is a simple string.\"");
validateToken(IToken.t_char);
validateToken(IToken.tSTAR);
validateIdentifier("myVariable");
validateToken(IToken.tASSIGN);
validateString("This is a simple string.");
validateToken(IToken.tSEMI);
validateEOF();
initializeScanner("#define FOOL 5 \n int tryAFOOL = FOOL + FOOL;");
validateToken(IToken.t_int);
validateIdentifier("tryAFOOL");
validateToken(IToken.tASSIGN);
validateInteger("5");
validateToken(IToken.tPLUS);
validateInteger("5");
validateToken(IToken.tSEMI);
validateEOF();
initializeScanner("#define FOOL 5 \n int FOOLer = FOOL;");
validateToken(IToken.t_int);
validateIdentifier("FOOLer");
validateToken(IToken.tASSIGN);
validateInteger("5");
validateToken(IToken.tSEMI);
validateEOF();
// the case we were failing against in ctype.h
// this is a definition, not a macro!
initializeScanner("#define _ALPHA (0x0100|_UPPER|_LOWER)");
validateEOF();
validateDefinition("_ALPHA", "(0x0100|_UPPER|_LOWER)");
// test for comments after the macro
initializeScanner("#define NO_COMMENT// ignore me");
validateEOF();
validateDefinition("NO_COMMENT", "");
initializeScanner("#define NO_COMMENT/* ignore me*/");
validateEOF();
validateDefinition("NO_COMMENT", "");
initializeScanner("#define ANSWER 42 // i think");
validateEOF();
validateDefinition("ANSWER", "42");
initializeScanner("#define ANSWER 42 /* i think */");
validateEOF();
validateDefinition("ANSWER", "42");
initializeScanner("#define MULTILINE 3 /* comment \n that goes more than one line */");
validateEOF();
validateDefinition("MULTILINE", "3");
initializeScanner("#define MULTICOMMENT X /* comment1 */ + Y /* comment 2 */");
validateEOF();
validateDefinition("MULTICOMMENT", "X + Y");
for (int i= 0; i < 7; ++i)
{
switch (i)
{
case 0 :
initializeScanner("#define SIMPLE_STRING This is a simple string.\n");
break;
case 1 :
initializeScanner("# define SIMPLE_NUMERIC 5\n");
break;
case 2 :
initializeScanner("# define SIMPLE_NUMERIC 5\n");
break;
case 3 :
initializeScanner("#define SIMPLE_STRING \"This is a simple string.\"\n");
break;
case 4 :
initializeScanner("#define SIMPLE_STRING This is a simple string.\n");
break;
case 5 :
initializeScanner("#define FLAKE\n\nFLAKE");
break;
case 6 :
initializeScanner("#define SIMPLE_STRING This is a simple string.\\\n Continue please.");
break;
}
validateEOF();
switch (i)
{
case 0 :
validateDefinition(
"SIMPLE_STRING",
"This is a simple string.");
break;
case 1 :
validateDefinition("SIMPLE_NUMERIC", "5");
break;
case 2 :
validateDefinition("SIMPLE_NUMERIC", "5");
break;
case 3 :
validateDefinition(
"SIMPLE_STRING",
"\"This is a simple string.\"");
break;
case 4 :
validateDefinition(
"SIMPLE_STRING",
"This is a simple string.");
break;
case 5 :
validateDefinition("FLAKE", "");
break;
case 6 :
validateDefinition(
"SIMPLE_STRING",
"This is a simple string. Continue please.");
}
}
}
catch (Exception e)
{
fail(EXCEPTION_THROWN + e.toString());
}
}
public void prepareForWindowsRH()
{
scanner.addIncludePath(
"C:\\Program Files\\Microsoft Visual Studio\\VC98\\Include");
scanner.addDefinition("_WIN32_WINNT", "0x0300");
scanner.addDefinition("WINVER", "0x0400");
scanner.addDefinition("_WIN32_WINDOWS", "0x0300");
scanner.addDefinition("_MSC_VER", "1200");
}
public void prepareForWindowsH()
{
scanner.addIncludePath(
"C:\\Program Files\\Microsoft Visual Studio\\VC98\\Include");
scanner.addDefinition("_MSC_VER", "1200");
scanner.addDefinition("__cplusplus", "1");
scanner.addDefinition("__STDC__", "1");
scanner.addDefinition("_WIN32", "");
scanner.addDefinition( "__midl", "1000" );
scanner.addDefinition("_WIN32_WINNT", "0x0300");
scanner.addDefinition("WINVER", "0x0400");
scanner.addDefinition( "_M_IX86", "300");
scanner.addDefinition( "_INTEGRAL_MAX_BITS", "64");
}
public void prepareForStdio()
{
scanner.addIncludePath(
"C:\\Program Files\\Microsoft Visual Studio\\VC98\\Include");
scanner.addDefinition("_MSC_VER", "1100");
scanner.addDefinition("__STDC__", "1");
scanner.addDefinition("_INTEGRAL_MAX_BITS", "64");
scanner.addDefinition("_WIN32", "");
scanner.addDefinition( "_M_IX86", "300");
}
public void testConcatenation()
{
try
{
initializeScanner("#define F1 3\n#define F2 F1##F1\nint x=F2;");
validateToken(IToken.t_int);
validateDefinition("F1", "3");
validateDefinition( "F2", "F1##F1");
validateIdentifier("x");
validateToken(IToken.tASSIGN);
validateInteger("33");
validateToken(IToken.tSEMI);
validateEOF();
initializeScanner("#define PREFIX RT_\n#define RUN PREFIX##Run");
validateEOF();
validateDefinition( "PREFIX", "RT_" );
validateDefinition( "RUN", "PREFIX##Run" );
}
catch (Exception e)
{
fail(EXCEPTION_THROWN + e.toString());
}
try
{
initializeScanner( "#define DECLARE_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name\n DECLARE_HANDLE( joe )" );
validateToken( IToken.t_struct );
validateIdentifier( "joe__");
validateToken( IToken.tLBRACE);
validateToken( IToken.t_int );
validateIdentifier( "unused");
validateToken( IToken.tSEMI );
validateToken( IToken.tRBRACE );
validateToken( IToken.tSEMI );
validateToken( IToken.t_typedef );
validateToken( IToken.t_struct );
validateIdentifier( "joe__" );
validateToken( IToken.tSTAR );
validateIdentifier( "joe");
validateEOF();
}
catch( Exception e )
{
fail(EXCEPTION_THROWN + e.toString());
}
}
public void testSimpleIfdef()
{
try
{
initializeScanner("#define SYMBOL 5\n#ifdef SYMBOL\nint counter(SYMBOL);\n#endif");
validateToken(IToken.t_int);
validateIdentifier("counter");
validateToken(IToken.tLPAREN);
validateInteger("5");
validateToken(IToken.tRPAREN);
validateToken(IToken.tSEMI);
validateEOF();
initializeScanner("#define SYMBOL 5\n#ifndef SYMBOL\nint counter(SYMBOL);\n#endif");
validateEOF();
initializeScanner("#ifndef DEFINED\n#define DEFINED 100\n#endif\nint count = DEFINED;");
validateToken(IToken.t_int);
validateDefinition("DEFINED", "100");
validateIdentifier("count");
validateToken(IToken.tASSIGN);
validateInteger("100");
validateToken(IToken.tSEMI);
validateEOF();
initializeScanner("#ifndef DEFINED\n#define DEFINED 100\n#endif\nint count = DEFINED;");
scanner.addDefinition("DEFINED", "101");
validateDefinition("DEFINED", "101");
validateToken(IToken.t_int);
validateIdentifier("count");
validateToken(IToken.tASSIGN);
validateInteger("101");
validateToken(IToken.tSEMI);
validateEOF();
initializeScanner( "/* NB: This is #if 0'd out */");
validateEOF();
}
catch (Exception e)
{
fail(EXCEPTION_THROWN + e.toString());
}
}
public void testMultipleLines() throws Exception
{
Writer code = new StringWriter();
code.write( "#define COMPLEX_MACRO 33 \\\n");
code.write( " + 44\n\nCOMPLEX_MACRO");
initializeScanner( code.toString() );
validateInteger( "33" );
validateToken( IToken.tPLUS );
validateInteger( "44" );
}
public void testSlightlyComplexIfdefStructure()
{
try
{
initializeScanner("#ifndef BASE\n#define BASE 10\n#endif\n#ifndef BASE\n#error BASE is defined\n#endif");
validateEOF();
validateBalance();
}
catch (Exception e)
{
fail(EXCEPTION_THROWN + e.toString());
}
try
{
initializeScanner("#ifndef ONE\n#define ONE 1\n#ifdef TWO\n#define THREE ONE + TWO\n#endif\n#endif\nint three(THREE);");
validateToken(IToken.t_int);
validateDefinition("ONE", "1");
validateAsUndefined("TWO");
validateAsUndefined("THREE");
validateIdentifier("three");
validateToken(IToken.tLPAREN);
validateIdentifier("THREE");
validateToken(IToken.tRPAREN);
validateToken(IToken.tSEMI);
validateEOF();
validateBalance();
initializeScanner("#ifndef ONE\n#define ONE 1\n#ifdef TWO\n#define THREE ONE + TWO\n#endif\n#endif\nint three(THREE);");
scanner.addDefinition("TWO", "2");
validateToken(IToken.t_int);
validateDefinition("ONE", "1");
validateDefinition("TWO", "2");
validateDefinition("THREE", "ONE + TWO");
validateIdentifier("three");
validateToken(IToken.tLPAREN);
validateInteger("1");
validateToken(IToken.tPLUS);
validateInteger("2");
validateToken(IToken.tRPAREN);
validateToken(IToken.tSEMI);
validateEOF();
validateBalance();
initializeScanner("#ifndef FOO\n#define FOO 4\n#else\n#undef FOO\n#define FOO 6\n#endif");
validateEOF();
validateBalance();
validateDefinition("FOO", "4");
initializeScanner("#ifndef FOO\n#define FOO 4\n#else\n#undef FOO\n#define FOO 6\n#endif");
scanner.addDefinition("FOO", "2");
validateEOF();
validateBalance();
validateDefinition("FOO", "6");
initializeScanner("#ifndef ONE\n# define ONE 1\n# ifndef TWO\n# define TWO ONE + ONE \n# else\n# undef TWO\n# define TWO 2 \n# endif\n#else\n# ifndef TWO\n# define TWO ONE + ONE \n# else\n# undef TWO\n# define TWO 2 \n# endif\n#endif\n");
validateEOF();
validateBalance();
validateDefinition("ONE", "1");
validateDefinition("TWO", "ONE + ONE");
initializeScanner("#ifndef ONE\n# define ONE 1\n# ifndef TWO\n# define TWO ONE + ONE \n# else\n# undef TWO\n# define TWO 2 \n# endif\n#else\n# ifndef TWO\n# define TWO ONE + ONE \n# else\n# undef TWO\n# define TWO 2 \n# endif\n#endif\n");
scanner.addDefinition("ONE", "one");
validateEOF();
validateBalance();
validateDefinition("ONE", "one");
validateDefinition("TWO", "ONE + ONE");
initializeScanner("#ifndef ONE\n# define ONE 1\n# ifndef TWO\n# define TWO ONE + ONE \n# else\n# undef TWO\n# define TWO 2 \n# endif\n#else\n# ifndef TWO\n# define TWO ONE + ONE \n# else\n# undef TWO\n# define TWO 2 \n# endif\n#endif\n");
scanner.addDefinition("ONE", "one");
scanner.addDefinition("TWO", "two");
validateEOF();
validateBalance();
validateDefinition("ONE", "one");
validateDefinition("TWO", "2");
initializeScanner("#ifndef ONE\n# define ONE 1\n# ifndef TWO\n# define TWO ONE + ONE \n# else\n# undef TWO\n# define TWO 2 \n# endif\n#else\n# ifndef TWO\n# define TWO ONE + ONE \n# else\n# undef TWO\n# define TWO 2 \n# endif\n#endif\n");
scanner.addDefinition("TWO", "two");
validateEOF();
validateBalance();
validateDefinition("ONE", "1");
validateDefinition("TWO", "2");
}
catch (Exception e)
{
fail(EXCEPTION_THROWN + e.toString());
}
}
public void testIfs()
{
try
{
initializeScanner("#if 0\n#error NEVER\n#endif\n");
validateEOF();
validateBalance();
initializeScanner("#define X 5\n#define Y 7\n#if (X < Y)\n#define Z X + Y\n#endif");
validateEOF();
validateBalance();
validateDefinition("X", "5");
validateDefinition("Y", "7");
validateDefinition("Z", "X + Y");
initializeScanner("#if T < 20\n#define Z T + 1\n#endif");
scanner.addDefinition("X", "5");
scanner.addDefinition("Y", "7");
scanner.addDefinition("T", "X + Y");
validateEOF();
validateBalance();
validateDefinition("X", "5");
validateDefinition("Y", "7");
validateDefinition("T", "X + Y");
validateDefinition("Z", "T + 1");
}
catch (Exception e)
{
fail(EXCEPTION_THROWN + e.toString());
}
try
{
initializeScanner("#if ( 10 / 5 ) != 2\n#error 10/5 seems to not equal 2 anymore\n#endif\n");
validateEOF();
validateBalance();
}
catch (Exception e)
{
fail(EXCEPTION_THROWN + e.toString());
}
try
{
initializeScanner("#ifndef FIVE \n#define FIVE 5\n#endif \n#ifndef TEN\n#define TEN 2 * FIVE\n#endif\n#if TEN != 10\n#define MISTAKE 1\n#error Five does not equal 10\n#endif\n");
scanner.addDefinition("FIVE", "55");
validateEOF();
fail(EXPECTED_FAILURE);
}
catch (ScannerException se)
{
validateBalance(1);
validateDefinition("FIVE", "55");
validateDefinition("TEN", "2 * FIVE");
validateDefinition("MISTAKE", "1");
}
catch (Exception e)
{
fail(EXCEPTION_THROWN + e.toString());
}
try
{
initializeScanner("#if ((( FOUR / TWO ) * THREE )< FIVE )\n#error 6 is not less than 5 \n#endif\n#if ( ( FIVE * ONE ) != (( (FOUR) + ONE ) * ONE ) )\n#error 5 should equal 5\n#endif \n");
scanner.addDefinition("ONE", "1");
scanner.addDefinition("TWO", "(ONE + ONE)");
scanner.addDefinition("THREE", "(TWO + ONE)");
scanner.addDefinition("FOUR", "(TWO * TWO)");
scanner.addDefinition("FIVE", "(THREE + TWO)");
validateEOF();
validateBalance();
validateDefinition("ONE", "1");
validateDefinition("TWO", "(ONE + ONE)");
validateDefinition("THREE", "(TWO + ONE)");
validateDefinition("FOUR", "(TWO * TWO)");
validateDefinition("FIVE", "(THREE + TWO)");
TruthTable table= new TruthTable(SIZEOF_TRUTHTABLE);
int numberOfRows= table.getNumberOfRows();
TableRow[] rows= table.rows;
for (int i= 0; i < numberOfRows; ++i)
{
TableRow row= rows[i];
String code= row.generateCode();
if (verbose)
System.out.println("\n\nRow " + i + " has code\n" + code);
initializeScanner(code);
validateEOF();
validateBalance();
validateAllDefinitions(row);
}
}
catch (Exception e)
{
fail(EXCEPTION_THROWN + e.toString());
}
try
{
initializeScanner("#if ! 0\n#error Correct!\n#endif");
scanner.nextToken();
fail(EXPECTED_FAILURE);
}
catch (ScannerException se)
{
validateBalance(1);
assertEquals( se.getProblem().getID(), IProblem.PREPROCESSOR_POUND_ERROR);
}
catch (Exception e)
{
fail(EXCEPTION_THROWN + e.toString());
}
}
public void testPreprocessorMacros()
{
try
{
initializeScanner("#define GO(x) x+1\nint y(5);\ny = GO(y);");
validateToken(IToken.t_int);
validateIdentifier("y");
validateToken(IToken.tLPAREN);
validateInteger("5");
validateToken(IToken.tRPAREN);
validateToken(IToken.tSEMI);
IMacroDescriptor descriptor=
(IMacroDescriptor) scanner.getDefinition("GO");
List parms= descriptor.getParameters();
assertNotNull(parms);
assertTrue(parms.size() == 1);
String parm1= (String) parms.get(0);
assertTrue(parm1.equals("x"));
List expansion= descriptor.getTokenizedExpansion();
assertNotNull(parms);
assertTrue(expansion.size() == 3);
assertTrue(((Token) expansion.get(0)).type == IToken.tIDENTIFIER);
assertTrue(((Token) expansion.get(0)).getImage().equals("x"));
assertTrue(((Token) expansion.get(1)).type == IToken.tPLUS);
assertTrue(((Token) expansion.get(2)).type == IToken.tINTEGER);
assertTrue(((Token) expansion.get(2)).getImage().equals("1"));
validateIdentifier("y");
validateToken(IToken.tASSIGN);
validateIdentifier("y");
validateToken(IToken.tPLUS);
validateInteger("1");
validateToken(IToken.tSEMI);
validateEOF();
validateBalance();
initializeScanner(
"#define ONE 1\n"
+ "#define SUM(a,b,c,d,e,f,g) ( a + b + c + d + e + f + g )\n"
+ "int daSum = SUM(ONE,3,5,7,9,11,13);");
validateToken(IToken.t_int);
validateIdentifier("daSum");
validateToken(IToken.tASSIGN);
validateToken(IToken.tLPAREN);
validateInteger("1");
validateToken(IToken.tPLUS);
validateInteger("3");
validateToken(IToken.tPLUS);
validateInteger("5");
validateToken(IToken.tPLUS);
validateInteger("7");
validateToken(IToken.tPLUS);
validateInteger("9");
validateToken(IToken.tPLUS);
validateInteger("11");
validateToken(IToken.tPLUS);
validateInteger("13");
validateToken(IToken.tRPAREN);
validateToken(IToken.tSEMI);
validateEOF();
IMacroDescriptor macro= (IMacroDescriptor) scanner.getDefinition("SUM");
List params= macro.getParameters();
assertNotNull(params);
assertTrue(params.size() == 7);
List tokens= macro.getTokenizedExpansion();
assertNotNull(tokens);
assertTrue(tokens.size() == 15);
initializeScanner("#define LOG( format, var1) printf( format, var1 )\nLOG( \"My name is %s\", \"Bogdan\" );\n");
validateIdentifier("printf");
validateToken(IToken.tLPAREN);
validateString("My name is %s");
validateToken(IToken.tCOMMA);
validateString("Bogdan");
validateToken(IToken.tRPAREN);
validateToken(IToken.tSEMI);
validateEOF();
initializeScanner("#define INCR( x ) ++x\nint y(2);\nINCR(y);");
validateToken(IToken.t_int);
validateIdentifier("y");
validateToken(IToken.tLPAREN);
validateInteger("2");
validateToken(IToken.tRPAREN);
validateToken(IToken.tSEMI);
validateToken(IToken.tINCR);
validateIdentifier("y");
validateToken(IToken.tSEMI);
validateEOF();
initializeScanner("#define CHECK_AND_SET( x, y, z ) if( x ) { \\\n y = z; \\\n }\n\nCHECK_AND_SET( 1, balance, 5000 );\nCHECK_AND_SET( confused(), you, dumb );");
validateToken(IToken.t_if);
validateToken(IToken.tLPAREN);
validateInteger("1");
validateToken(IToken.tRPAREN);
validateToken(IToken.tLBRACE);
validateIdentifier("balance");
validateToken(IToken.tASSIGN);
validateInteger("5000");
validateToken(IToken.tSEMI);
validateToken(IToken.tRBRACE);
validateToken(IToken.tSEMI);
validateToken(IToken.t_if);
validateToken(IToken.tLPAREN);
validateIdentifier("confused");
validateToken(IToken.tLPAREN);
validateToken(IToken.tRPAREN);
validateToken(IToken.tRPAREN);
validateToken(IToken.tLBRACE);
validateIdentifier("you");
validateToken(IToken.tASSIGN);
validateIdentifier("dumb");
validateToken(IToken.tSEMI);
validateToken(IToken.tRBRACE);
validateToken(IToken.tSEMI);
validateEOF();
initializeScanner("#define ON 7\n#if defined(ON)\nint itsOn = ON;\n#endif");
validateToken(IToken.t_int);
validateBalance(1);
validateIdentifier("itsOn");
validateToken(IToken.tASSIGN);
validateInteger("7");
validateToken(IToken.tSEMI);
validateEOF();
validateBalance();
initializeScanner("#if defined( NOTHING ) \nint x = NOTHING;\n#endif");
validateEOF();
validateBalance();
}
catch (Exception e)
{
fail(EXCEPTION_THROWN + e.toString());
}
}
public void testQuickScan() throws EndOfFileException, ParserFactoryException
{
try
{
initializeScanner( "#if X + 5 < 7\n int found = 1;\n#endif", ParserMode.QUICK_PARSE );
validateToken( IToken.t_int );
validateIdentifier( "found" );
validateToken( IToken.tASSIGN );
validateInteger( "1");
validateToken( IToken.tSEMI );
validateEOF();
}
catch( ScannerException se )
{
fail( EXCEPTION_THROWN + se.getMessage() );
}
try
{
initializeScanner( "#if 0\n int error = 666;\n#endif" );
validateEOF();
}
catch( ScannerException se )
{
fail( EXCEPTION_THROWN + se.getMessage() );
}
}
public void testInclusions()
{
try
{
if (doIncludeStdio)
{
initializeScanner("#include <stdio.h>");
prepareForStdio();
int count= fullyTokenize();
if (verbose)
System.out.println(
"For stdio.h, Scanner produced " + count + " tokens");
validateBalance();
initializeScanner("#include \\\n<\\\nstdio.h \\\n>");
prepareForStdio();
count= fullyTokenize();
if (verbose)
System.out.println(
"For stdio.h, Scanner produced " + count + " tokens");
}
if (doIncludeWindowsH)
{
initializeScanner("#include <Windows.h>");
prepareForWindowsH();
int count= fullyTokenize();
validateBalance();
}
if (doIncludeWinUserH)
{
initializeScanner("#include <WinUser.rh>");
prepareForWindowsRH();
validateEOF();
validateBalance();
}
}
catch (Exception e)
{
fail(EXCEPTION_THROWN + e.toString());
}
}
public void testOtherPreprocessorCommands() throws ParserFactoryException
{
try
{
initializeScanner("#\n#\t\n#define MAX_SIZE 1024\n#\n# ");
validateEOF();
validateDefinition("MAX_SIZE", "1024");
}
catch (Exception e)
{
fail(EXCEPTION_THROWN + e.toString());
}
for (int i= 0; i < 4; ++i)
{
switch (i)
{
case 0 :
initializeScanner("# ape");
break;
case 1 :
initializeScanner("# #");
break;
case 2 :
initializeScanner("# 32");
break;
case 3 :
initializeScanner("# defines");
break;
}
try
{
validateEOF();
fail(EXPECTED_FAILURE);
}
catch (ScannerException se)
{
validateBalance();
}
catch (Exception e)
{
fail(EXCEPTION_THROWN + e.toString());
}
}
}
public void validateAllDefinitions(TableRow row)
{
int winner= row.selectWinner();
int rowLength= row.getLength();
for (int i= 0; i <= rowLength; ++i)
{
if (i == winner)
validateDefinition(row.symbolName(i), row.symbolValue(i));
else
validateAsUndefined(row.symbolName(i));
}
}
public void testBug36287() throws Exception
{
initializeScanner( "X::X( const X & rtg_arg ) : U( rtg_arg ) , Z( rtg_arg.Z ) , er( rtg_arg.er ){}" );
validateIdentifier("X");
validateToken( IToken.tCOLONCOLON);
validateIdentifier("X");
validateToken( IToken.tLPAREN );
validateToken( IToken.t_const );
validateIdentifier("X");
validateToken( IToken.tAMPER );
validateIdentifier( "rtg_arg");
validateToken( IToken.tRPAREN );
validateToken( IToken.tCOLON );
validateIdentifier( "U");
validateToken( IToken.tLPAREN );
validateIdentifier( "rtg_arg");
validateToken( IToken.tRPAREN );
validateToken( IToken.tCOMMA );
validateIdentifier( "Z");
validateToken( IToken.tLPAREN );
validateIdentifier( "rtg_arg");
validateToken( IToken.tDOT );
validateIdentifier( "Z");
validateToken( IToken.tRPAREN );
validateToken( IToken.tCOMMA );
validateIdentifier( "er");
validateToken( IToken.tLPAREN );
validateIdentifier( "rtg_arg");
validateToken( IToken.tDOT );
validateIdentifier( "er");
validateToken( IToken.tRPAREN );
validateToken( IToken.tLBRACE);
validateToken( IToken.tRBRACE);
validateEOF();
initializeScanner( "foo.*bar");
validateIdentifier("foo");
validateToken( IToken.tDOTSTAR );
validateIdentifier("bar");
validateEOF();
initializeScanner( "foo...bar");
validateIdentifier("foo");
validateToken( IToken.tELLIPSIS );
validateIdentifier("bar");
validateEOF();
}
public void testBug35892() throws ParserFactoryException
{
try
{
initializeScanner( "'c'" );
validateChar( 'c' );
validateEOF();
}
catch( ScannerException se )
{
fail( EXCEPTION_THROWN + se.getMessage() );
}
}
public void testBug36045() throws Exception
{
StringBuffer buffer = new StringBuffer();
buffer.append( '"' );
buffer.append( '\\');
buffer.append( '"');
buffer.append( '"');
buffer.append( '"');
buffer.append( '\\');
buffer.append( '\\');
buffer.append( '"');
buffer.append( "\n\n");
initializeScanner( buffer.toString());
validateString( "\\\"\\\\");
}
public void testConditionalWithBraces() throws ParserFactoryException
{
try
{
for( int i = 0; i < 4; ++i )
{
initializeScanner( "int foobar(int a) { if(a == 0) {\n#ifdef THIS\n} else {}\n#elif THAT\n} else {}\n#endif\nreturn 0;}" );
switch( i )
{
case 0:
scanner.addDefinition( "THIS", "1");
scanner.addDefinition( "THAT", "1" );
break;
case 1:
scanner.addDefinition( "THIS", "1");
scanner.addDefinition( "THAT", "0" );
break;
case 2:
scanner.addDefinition( "THAT", "1" );
break;
case 3:
scanner.addDefinition( "THAT", "0" );
break;
}
validateToken( IToken.t_int );
validateIdentifier( "foobar");
validateToken( IToken.tLPAREN );
validateToken( IToken.t_int );
validateIdentifier( "a" );
validateToken( IToken.tRPAREN );
validateToken( IToken.tLBRACE );
validateToken( IToken.t_if );
validateToken( IToken.tLPAREN );
validateIdentifier( "a" );
validateToken( IToken.tEQUAL );
validateInteger( "0" );
validateToken( IToken.tRPAREN );
validateToken( IToken.tLBRACE );
if( i <= 1 )
{
validateToken( IToken.tRBRACE );
validateToken( IToken.t_else );
validateToken( IToken.tLBRACE );
validateToken( IToken.tRBRACE );
}
if( i == 2 )
{
validateToken( IToken.tRBRACE );
validateToken( IToken.t_else );
validateToken( IToken.tLBRACE );
validateToken( IToken.tRBRACE );
}
validateToken( IToken.t_return );
validateInteger( "0");
validateToken( IToken.tSEMI );
validateToken( IToken.tRBRACE );
validateEOF();
}
} catch( ScannerException se )
{
fail(EXCEPTION_THROWN + se.toString());
}
}
public void testNestedRecursiveDefines() throws Exception
{
initializeScanner( "#define C B A\n#define B C C\n#define A B\nA" );
validateIdentifier("B");
validateDefinition("A", "B");
validateDefinition("B", "C C");
validateDefinition("C", "B A");
validateIdentifier("A");
validateIdentifier("B");
validateIdentifier("A");
validateEOF();
}
public void testBug36316() throws Exception
{
initializeScanner( "#define A B->A\nA" );
validateIdentifier("B");
validateDefinition("A", "B->A");
validateToken(IToken.tARROW);
validateIdentifier("A");
validateEOF();
}
public void testBug36434() throws Exception
{
initializeScanner( "#define X(Y)");
validateEOF();
IMacroDescriptor macro = (IMacroDescriptor)scanner.getDefinition( "X" );
assertNotNull( macro );
assertEquals( macro.getParameters().size(), 1 );
assertEquals( (String)macro.getParameters().get(0), "Y" );
assertEquals( macro.getTokenizedExpansion().size(), 0 );
}
public void testBug36047() throws Exception
{
StringWriter writer = new StringWriter();
writer.write( "# define MAD_VERSION_STRINGIZE(str) #str\n" );
writer.write( "# define MAD_VERSION_STRING(num) MAD_VERSION_STRINGIZE(num)\n" );
writer.write( "# define MAD_VERSION MAD_VERSION_STRING(MAD_VERSION_MAJOR) \".\" \\\n" );
writer.write( " MAD_VERSION_STRING(MAD_VERSION_MINOR) \".\" \\\n" );
writer.write( " MAD_VERSION_STRING(MAD_VERSION_PATCH) \".\" \\\n" );
writer.write( " MAD_VERSION_STRING(MAD_VERSION_EXTRA)\n" );
writer.write( "# define MAD_VERSION_MAJOR 2\n" );
writer.write( "# define MAD_VERSION_MINOR 1\n" );
writer.write( "# define MAD_VERSION_PATCH 3\n" );
writer.write( "# define MAD_VERSION_EXTRA boo\n" );
writer.write( "MAD_VERSION\n" );
initializeScanner( writer.toString() );
validateString( "2.1.3.boo" );
validateEOF();
}
public void testBug36475() throws Exception
{
StringWriter writer = new StringWriter();
writer.write( " \"A\" \"B\" \"C\" " );
initializeScanner( writer.toString() );
validateString( "ABC" );
validateEOF();
}
public void testBug36509() throws Exception
{
StringWriter writer = new StringWriter();
writer.write("#define debug(s, t) printf(\"x\" # s \"= %d, x\" # t \"= %s\", \\\n");
writer.write(" x ## s, x ## t) \n");
writer.write("debug(1, 2);");
initializeScanner( writer.toString() );
//printf("x1=%d, x2= %s", x1, x2);
validateIdentifier( "printf" );
validateToken( IToken.tLPAREN );
validateString("x1= %d, x2= %s");
validateToken(IToken.tCOMMA);
validateIdentifier("x1");
validateToken(IToken.tCOMMA);
validateIdentifier("x2");
validateToken(IToken.tRPAREN);
validateToken(IToken.tSEMI);
validateEOF();
}
public void testBug36695() throws Exception
{
StringWriter writer = new StringWriter();
writer.write("\'\\4\' \'\\n\'");
initializeScanner( writer.toString() );
validateChar( "\\4" );
validateChar( "\\n" );
validateEOF();
}
public void testBug36521() throws Exception
{
StringWriter writer = new StringWriter();
writer.write("#define str(s) # s\n");
writer.write("fputs(str(strncmp(\"abc\\0d\", \"abc\", \'\\4\')\n");
writer.write(" == 0), s);\n");
initializeScanner( writer.toString() );
validateIdentifier("fputs");
validateToken(IToken.tLPAREN);
validateString("strncmp(\\\"abc\\\\0d\\\", \\\"abc\\\", '\\\\4') == 0");
validateToken(IToken.tCOMMA);
validateIdentifier("s");
validateToken(IToken.tRPAREN);
validateToken(IToken.tSEMI);
}
public void testBug36770() throws Exception
{
StringWriter writer = new StringWriter();
writer.write( "#define A 0\n" );
writer.write( "#if ( A == 1 )\n");
writer.write( "# define foo 1\n");
writer.write( "#else\n");
writer.write( "# define foo 2\n");
writer.write( "#endif\n");
writer.write( "foo\n");
initializeScanner( writer.toString() );
validateInteger( "2" );
validateEOF();
}
public void testBug36816() throws Exception
{
initializeScanner( "#include \"foo.h" );
try{
validateEOF();
} catch ( ScannerException e ){
assertTrue( e.getProblem().getID() == IProblem.PREPROCESSOR_INVALID_DIRECTIVE );
}
initializeScanner( "#include <foo.h" );
try{
validateEOF();
} catch ( ScannerException e ){
assertTrue( e.getProblem().getID() == IProblem.PREPROCESSOR_INVALID_DIRECTIVE);
}
initializeScanner( "#define FOO(A" );
try{
validateEOF();
} catch( ScannerException e ){
assertTrue( e.getProblem().getID() == IProblem.PREPROCESSOR_INVALID_MACRO_DEFN );
}
initializeScanner( "#define FOO(A \\ B" );
try{
validateEOF();
} catch( ScannerException e ){
assertTrue( e.getProblem().getID() == IProblem.PREPROCESSOR_INVALID_MACRO_DEFN);
}
initializeScanner( "#define FOO(A,\\\nB) 1\n FOO(foo" );
try{
validateInteger("1");
} catch( ScannerException e ){
assertTrue( e.getProblem().getID() == IProblem.PREPROCESSOR_MACRO_USAGE_ERROR);
}
}
public void testBug36255() throws Exception
{
StringWriter writer = new StringWriter();
writer.write( "#if defined ( A ) \n" );
writer.write( " #if defined ( B ) && ( B != 0 ) \n" );
writer.write( " boo\n" );
writer.write( " #endif /*B*/\n" );
writer.write( "#endif /*A*/" );
initializeScanner( writer.toString() );
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");
}
public void testBug38065() throws Exception
{
initializeScanner( "Foo\\\nBar" );
validateIdentifier("FooBar");
validateEOF();
}
public void testBug36701A() throws Exception
{
StringWriter writer = new StringWriter();
writer.write("#define str(s) # s\n");
writer.write("str( @ \\n )\n");
initializeScanner(writer.toString());
validateString("@ \\\\n");
validateEOF();
}
public void testBug36701B() throws Exception
{
StringWriter writer = new StringWriter();
writer.write("#define str(s) # s\n");
writer.write("str( @ /*ff*/ \\n hh \"aa\" )\n");
initializeScanner(writer.toString());
validateString("@ \\\\n hh \\\"aa\\\"");
validateEOF();
}
public void testBug44305() throws Exception
{
StringWriter writer = new StringWriter();
writer.write( "#define WCHAR_MAX 0 \n");
writer.write( "#if WCHAR_MAX <= 0xff\n" );
writer.write( "bool\n");
writer.write( "#endif");
initializeScanner( writer.toString());
validateToken( IToken.t_bool );
validateEOF();
}
public void testBug45287() throws Exception
{
initializeScanner( "'abcdefg' L'hijklmnop'");
validateChar( "abcdefg" );
validateWideChar( "hijklmnop");
validateEOF();
}
public void testBug45476() throws Exception
{
StringBuffer buffer = new StringBuffer();
buffer.append( "#define X 5\n");
buffer.append( "#if defined X\n");
buffer.append( "#define Y 10\n");
buffer.append( "#endif");
initializeScanner( buffer.toString() );
validateEOF();
validateDefinition( "Y", "10");
}
public void testBug45477() throws Exception
{
StringBuffer buffer = new StringBuffer();
buffer.append( "#define D\n" );
buffer.append( "#define D\n" );
buffer.append( "#define sum(x,y) x+y\n" );
buffer.append( "#define E 3\n" );
buffer.append( "#define E 3\n" );
buffer.append( "#define sum(x,y) x+y\n");
buffer.append( "#if defined(D)\n" );
buffer.append( "printf\n" );
buffer.append( "#endif\n" );
buffer.append( "#if defined(sum)\n" );
buffer.append( "scanf\n" );
buffer.append( "#endif\n" );
buffer.append( "#if defined(E)\n" );
buffer.append( "sprintf\n" );
buffer.append( "#endif\n" );
initializeScanner( buffer.toString() );
validateIdentifier( "printf" );
validateIdentifier( "scanf");
validateIdentifier( "sprintf" );
validateEOF();
for( int i = 0; i < 5; ++i)
{
buffer = new StringBuffer();
buffer.append( "#define D blah\n" );
switch( i )
{
case 0:
buffer.append( "#define D\n");
break;
case 1:
buffer.append( "#define D( x ) echo\n");
break;
case 2:
buffer.append( "#define D ACDC\n");
break;
case 3:
buffer.append( "#define D defined( D )\n");
break;
case 4:
buffer.append( "#define D blahh\n");
break;
}
initializeScanner( buffer.toString() );
try
{
validateEOF();
fail( "Should not reach here");
}
catch( ScannerException se )
{
assertTrue( se.getProblem().getID() == IProblem.PREPROCESSOR_INVALID_MACRO_REDEFN);
}
}
buffer = new StringBuffer();
buffer.append( "#define X 5\n");
buffer.append( "#define Y 7\n");
buffer.append( "#define SUMXY X _+ Y");
buffer.append( "#define SUMXY X + Y");
initializeScanner(buffer.toString());
validateEOF();
}
protected static class Callback extends NullSourceElementRequestor implements ISourceElementRequestor
{
public List inclusions = new ArrayList();
public List problems = new ArrayList();
/* (non-Javadoc)
* @see org.eclipse.cdt.core.parser.ISourceElementRequestor#enterInclusion(org.eclipse.cdt.core.parser.ast.IASTInclusion)
*/
public void enterInclusion(IASTInclusion inclusion)
{
inclusions.add( inclusion.getName() );
}
public boolean acceptProblem( IProblem p )
{
problems.add( p );
return super.acceptProblem(p);
}
/**
* @param mode
*/
public Callback(ParserMode mode)
{
super( mode );
}
}
public void testBug45551() throws Exception
{
StringBuffer buffer = new StringBuffer();
buffer.append( "#define stdio someNonExistantIncludeFile\n" );
buffer.append( "#include <stdio.h>\n" );
Callback callback = new Callback( ParserMode.QUICK_PARSE );
initializeScanner( buffer.toString(), ParserMode.QUICK_PARSE, callback );
validateEOF();
assertEquals( callback.problems.size(), 0 );
assertEquals( callback.inclusions.size(), 1 );
assertEquals( callback.inclusions.get(0), "stdio.h");
}
}