diff options
Diffstat (limited to 'core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ScannerTestCase.java')
-rw-r--r-- | core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ScannerTestCase.java | 1404 |
1 files changed, 1404 insertions, 0 deletions
diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ScannerTestCase.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ScannerTestCase.java new file mode 100644 index 00000000000..1cbbd467746 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ScannerTestCase.java @@ -0,0 +1,1404 @@ +package org.eclipse.cdt.core.parser.tests; + +import java.io.StringWriter; +import java.io.Writer; +import java.util.List; + +import org.eclipse.cdt.core.parser.IMacroDescriptor; +import org.eclipse.cdt.core.parser.IToken; +import org.eclipse.cdt.core.parser.ScannerException; +import org.eclipse.cdt.internal.core.parser.Parser; +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() + { + 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() + { + 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.tELIPSE ); + validateEOF(); + } + catch( ScannerException se ) + { + fail(EXCEPTION_THROWN + se.toString()); + } + + } + + + /** + * Constructor for ScannerTestCase. + * @param name + */ + public ScannerTestCase(String name) + { + super(name); + } + + public void testPreprocessorDefines() + { + 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"); + IToken t= scanner.nextToken(); + fail(EXPECTED_FAILURE); + } + catch (ScannerException se) + { + validateBalance(1); + assertTrue(se.getMessage().equals("#error Correct!")); + } + 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)).image.equals("x")); + assertTrue(((Token) expansion.get(1)).type == IToken.tPLUS); + assertTrue(((Token) expansion.get(2)).type == IToken.tINTEGER); + assertTrue(((Token) expansion.get(2)).image.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 Parser.EndOfFile + { + try + { + initializeScanner( "#if X + 5 < 7\n int found = 1;\n#endif" ); + scanner.setQuickScan( true ); + 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" ); + scanner.setQuickScan( true ); + 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(); + if (verbose) + System.out.println( + "For Windows.h, Scanner produced " + + scanner.getCount() + + " tokens"); + validateBalance(); + } + + if (doIncludeWinUserH) + { + initializeScanner("#include <WinUser.rh>"); + prepareForWindowsRH(); + validateEOF(); + validateBalance(); + if (verbose) + System.out.println( + "For WinUser.rh, Scanner produced " + + scanner.getCount() + + " tokens"); + } + } + catch (Exception e) + { + fail(EXCEPTION_THROWN + e.toString()); + } + + } + + public void testOtherPreprocessorCommands() + { + 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.tELIPSE ); + validateIdentifier("bar"); + validateEOF(); + } + + public void testBug35892() + { + 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() + { + 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.getMessage().equals( "Ill-formed #include: reached end of line before \"" )); + } + + initializeScanner( "#include <foo.h" ); + try{ + validateEOF(); + } catch ( ScannerException e ){ + assertTrue( e.getMessage().equals( "Ill-formed #include: reached end of line before >" )); + } + initializeScanner( "#define FOO(A" ); + try{ + validateEOF(); + } catch( ScannerException e ){ + assertTrue( e.getMessage().equals( "Unexpected newline in macro formal parameter list.")); + } + initializeScanner( "#define FOO(A \\ B" ); + try{ + validateEOF(); + } catch( ScannerException e ){ + assertTrue( e.getMessage().equals( "Unexpected '\\' in macro formal parameter list.")); + } + + initializeScanner( "#define FOO(A,\\\nB) 1\n FOO(foo" ); + try{ + validateInteger("1"); + } catch( ScannerException e ){ + assertTrue( e.getMessage().equals( "Improper use of macro FOO" ) ); + } + } + + 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(); + + try { + initializeScanner( "Foo\\Bar" ); + + validateIdentifier("Foo"); + validateIdentifier("Bar"); + validateEOF(); + + } catch (ScannerException se) { + // if Scanner.throwExceptionOnBadCharacterRead == true + // we might end up with valid ScannerException "Invalid character ..." + // for '\' + assertTrue(se.getMessage().equals("Invalid character '\\' read @ offset 5 of file TEXT")); + } + } + + 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(); + } +} |