From f71f0d74cadcd7380a8bb149525ad0da77c262e5 Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Thu, 30 Aug 2007 09:46:05 +0000 Subject: [PATCH] JUnit-tests: ported Scanner2Tests to DOMScannerTests. --- .../core/parser/tests/ast2/AST2BaseTest.java | 26 +- .../parser/tests/ast2/DOMParserTestSuite.java | 9 +- .../parser/tests/ast2/DOMScannerTests.java | 2510 ++++++++++++++++- .../core/testplugin/util/BaseTestCase.java | 9 +- .../core/parser/scanner2/BaseScanner.java | 28 +- 5 files changed, 2536 insertions(+), 46 deletions(-) diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2BaseTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2BaseTest.java index 4d0462f77d1..12bc13dd865 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2BaseTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2BaseTest.java @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ /* @@ -103,17 +104,8 @@ public class AST2BaseTest extends BaseTestCase { } protected IASTTranslationUnit parse( String code, ParserLanguage lang, boolean useGNUExtensions, boolean expectNoProblems , boolean parseComments) throws ParserException { - CodeReader codeReader = new CodeReader(code - .toCharArray()); - ScannerInfo scannerInfo = new ScannerInfo(); - IScannerExtensionConfiguration configuration = null; - if( lang == ParserLanguage.C ) - configuration = new GCCScannerExtensionConfiguration(); - else - configuration = new GPPScannerExtensionConfiguration(); - IScanner scanner = new DOMScanner( codeReader, scannerInfo, ParserMode.COMPLETE_PARSE, lang, NULL_LOG, configuration, FileCodeReaderFactory.getInstance() ); - scanner.setScanComments(parseComments); - + IScanner scanner = createScanner(new CodeReader(code.toCharArray()), lang, ParserMode.COMPLETE_PARSE, + new ScannerInfo(), parseComments); ISourceCodeParser parser2 = null; if( lang == ParserLanguage.CPP ) { @@ -158,6 +150,18 @@ public class AST2BaseTest extends BaseTestCase { return tu; } + public static IScanner createScanner(CodeReader codeReader, ParserLanguage lang, ParserMode mode, + ScannerInfo scannerInfo, boolean parseComments) { + IScannerExtensionConfiguration configuration = null; + if( lang == ParserLanguage.C ) + configuration = new GCCScannerExtensionConfiguration(); + else + configuration = new GPPScannerExtensionConfiguration(); + IScanner scanner = new DOMScanner( codeReader, scannerInfo, mode, lang, NULL_LOG, configuration, FileCodeReaderFactory.getInstance() ); + scanner.setScanComments(parseComments); + return scanner; + } + /** * @param string */ diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMParserTestSuite.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMParserTestSuite.java index d58155356ac..140baf93b41 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMParserTestSuite.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMParserTestSuite.java @@ -6,9 +6,9 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM - Initial API and implementation - * Markus Schorn (Wind River Systems) - * Emanuel Graf (IFS) + * IBM - Initial API and implementation + * Markus Schorn (Wind River Systems) + * Emanuel Graf (IFS) *******************************************************************************/ package org.eclipse.cdt.core.parser.tests.ast2; @@ -26,7 +26,8 @@ public class DOMParserTestSuite extends TestCase { public static Test suite() { TestSuite suite= new TestSuite(ParserTestSuite.class.getName()); - suite.addTest( AST2Tests.suite() ); + suite.addTest(DOMScannerTests.suite()); + suite.addTest(AST2Tests.suite()); suite.addTestSuite( GCCTests.class ); suite.addTestSuite( AST2CPPTests.class ); suite.addTest( AST2TemplateTests.suite() ); diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMScannerTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMScannerTests.java index 57d8f6237ea..d8f4623c997 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMScannerTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMScannerTests.java @@ -1,34 +1,2510 @@ /******************************************************************************* - * Copyright (c) 2004, 2005 IBM Corporation and others. + * Copyright (c) 2004, 2007 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM - Initial API and implementation + * IBM - Initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.core.parser.tests.ast2; -import junit.framework.TestCase; +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import junit.framework.ComparisonFailure; +import junit.framework.TestSuite; + +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement; +import org.eclipse.cdt.core.dom.ast.IASTProblem; +import org.eclipse.cdt.core.parser.CodeReader; +import org.eclipse.cdt.core.parser.EndOfFileException; +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.ParserLanguage; +import org.eclipse.cdt.core.parser.ParserMode; +import org.eclipse.cdt.core.parser.ScannerInfo; +import org.eclipse.cdt.core.parser.util.CharArrayUtils; +import org.eclipse.cdt.core.testplugin.util.BaseTestCase; +import org.eclipse.cdt.internal.core.parser.scanner2.DOMScanner; +import org.eclipse.cdt.internal.core.parser.scanner2.FunctionStyleMacro; +import org.eclipse.cdt.internal.core.parser.scanner2.ILocationResolver; +import org.eclipse.cdt.internal.core.parser.scanner2.ObjectStyleMacro; /** - * @author jcamelon + * Scanner2Tests ported to use the DOMScanner */ -public class DOMScannerTests extends TestCase { +public class DOMScannerTests extends BaseTestCase { - /** - * - */ - public DOMScannerTests() { - super(); - } + public static TestSuite suite() { + return suite(DOMScannerTests.class); + } - /** - * @param name - */ - public DOMScannerTests(String name) { - super(name); - } + private DOMScanner fScanner; + public DOMScannerTests() { + super(); + } + + public DOMScannerTests(String name) { + super(name); + } + + protected void initializeScanner(String input) throws IOException { + initializeScanner(input, ParserMode.COMPLETE_PARSE); + } + + protected void initializeScanner(String input, ParserLanguage lang) throws IOException { + fScanner= (DOMScanner) AST2BaseTest.createScanner(new CodeReader(input.toCharArray()), lang, + ParserMode.COMPLETE_PARSE, new ScannerInfo(), false); + } + + protected void initializeScanner(String input, ParserMode mode) throws IOException { + fScanner= (DOMScanner) AST2BaseTest.createScanner(new CodeReader(input.toCharArray()), ParserLanguage.CPP, + mode, new ScannerInfo(), false); + } + + protected int fullyTokenize() throws Exception { + try { + for(;;) { + IToken t= fScanner.nextToken(); + assertTrue(t.getType() <= IToken.tLAST); + } + } + catch ( EndOfFileException e){ + } + return fScanner.getCount(); + } + + + protected void validateToken(int tokenType) throws Exception { + IToken t= fScanner.nextToken(); + assertEquals(tokenType, t.getType()); + } + + protected void validateToken(int tokenType, String image) throws Exception { + IToken t= fScanner.nextToken(); + assertEquals(tokenType, t.getType()); + assertEquals(image, t.getImage()); + } + + protected void validateInteger(String expectedImage) throws Exception { + validateToken(IToken.tINTEGER, expectedImage); + } + + protected void validateIdentifier(String expectedImage) throws Exception { + validateToken(IToken.tIDENTIFIER, expectedImage); + } + + protected void validateString(String expectedImage) throws Exception { + validateToken(IToken.tSTRING, expectedImage); + } + + protected void validateChar(String expectedImage) throws Exception { + validateToken(IToken.tCHAR, "'" + expectedImage + "'"); + } + + protected void validateWideChar(String expectedImage) throws Exception { + validateToken(IToken.tLCHAR, "L'" + expectedImage + "'"); + } + + protected void validateLString(String expectedImage) throws Exception { + validateToken(IToken.tLSTRING, expectedImage); + } + + protected void validateFloatingPointLiteral(String expectedImage) throws Exception { + validateToken(IToken.tFLOATINGPT, expectedImage); + } + + protected void validateEOF() throws Exception { + try { + IToken t= fScanner.nextToken(); + fail("superfluous token " + t); + } + catch(EndOfFileException e) { + } + } + + private void assertCharArrayEquals(char[] expected, char[] actual) { + if (!CharArrayUtils.equals(expected, actual)) + throw new ComparisonFailure(null, new String(expected), new String(actual)); + } + + protected void validateDefinition(String name, String value) { + Object expObject = fScanner.getRealDefinitions().get(name.toCharArray()); + assertNotNull(expObject); + assertTrue(expObject instanceof ObjectStyleMacro); + assertCharArrayEquals(value.toCharArray(), ((ObjectStyleMacro)expObject).getExpansion()); + } + + protected void validateDefinition(String name, int value) { + validateDefinition(name, String.valueOf(value)); + } + + protected void validateAsUndefined(String name) { + assertNull(fScanner.getDefinitions().get(name.toCharArray())); + } + + protected void validateProblemCount(int count) throws Exception { + ILocationResolver lm= fScanner.getLocationResolver(); + assertEquals(count, lm.getScannerProblems().length); + } + + public void testBug102825_1() throws Exception { + StringBuffer buffer = new StringBuffer( + "#define CURLOPTTYPE_OBJECTPOINT 10000\n"); + buffer.append("#define CINIT = CURLOPTTYPE_##OBJECTPOINT + 1\n"); + buffer.append("CINIT\n"); + initializeScanner(buffer.toString()); + validateToken(IToken.tASSIGN); + validateInteger("10000"); + } + + public void testBug102825_2() throws Exception { + StringBuffer buffer = new StringBuffer( + "#define CURLOPTTYPE_OBJECTPOINT 10000\n"); + buffer + .append("#define CINIT(name,type,number) = CURLOPTTYPE_##type + number\n"); + buffer.append("CINIT(FILE, OBJECTPOINT, 1)\n"); + initializeScanner(buffer.toString()); + validateToken(IToken.tASSIGN); + validateInteger("10000"); + } + + public void testBug102825_3() throws Exception { + StringBuffer buffer = new StringBuffer( + "#define CURLOPTTYPE_OBJECTPOINT 10000\n"); + buffer + .append("#define CINIT(name,type,number) CURLOPT_ ## name = CURLOPTTYPE_ ## type + number\n"); + buffer.append("CINIT(FILE, OBJECTPOINT, 1)\n"); + initializeScanner(buffer.toString()); + validateIdentifier("CURLOPT_FILE"); + validateToken(IToken.tASSIGN); + validateInteger("10000"); + } + + public void testBug102825_4() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("#define glue( a, b ) a ## b\n"); + buffer.append("#define HIGHLOW \"hello\"\n"); + buffer.append("glue( HIGH, LOW )\n"); + + initializeScanner(buffer.toString(), ParserMode.QUICK_PARSE); + validateString("hello"); + validateProblemCount(0); + } + + public void testBug195610_1() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("#define glue(x, y, z) x ## y ## z\n"); + buffer.append("glue(, b, c)\n"); + + initializeScanner(buffer.toString(), ParserMode.QUICK_PARSE); + validateIdentifier("bc"); + validateProblemCount(0); + } + + public void testBug195610_2() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("#define glue(x, y, z) x ## y ## z\n"); + buffer.append("glue(a, , c)\n"); + + initializeScanner(buffer.toString(), ParserMode.QUICK_PARSE); + validateIdentifier("ac"); + validateProblemCount(0); + } + + public void testBug195610_3() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("#define glue(x, y, z) x ## y ## z\n"); + buffer.append("glue(a, b, )\n"); + + initializeScanner(buffer.toString(), ParserMode.QUICK_PARSE); + validateIdentifier("ab"); + validateProblemCount(0); + } + + 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(" "); //$NON-NLS-3$ + } + 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 int SIZEOF_TRUTHTABLE = 10; + + public void testWeirdStrings() throws Exception { + initializeScanner("Living Life L\"LONG\""); + validateIdentifier("Living"); + validateIdentifier("Life"); + validateLString("LONG"); + validateEOF(); + + } + + public void testNumerics() throws Exception { + 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(); + + } + + public void testPreprocessorDefines() throws Exception { + 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"); + + initializeScanner("#define SIMPLE_STRING This is a simple string.\n"); + validateEOF(); + validateDefinition("SIMPLE_STRING", + "This is a simple string."); + + initializeScanner("# define SIMPLE_NUMERIC 5\n"); + validateEOF(); + validateDefinition("SIMPLE_NUMERIC", "5"); + + initializeScanner("# define SIMPLE_NUMERIC 5\n"); + validateEOF(); + validateDefinition("SIMPLE_NUMERIC", "5"); + + initializeScanner("#define SIMPLE_STRING \"This is a simple string.\"\n"); + validateEOF(); + validateDefinition("SIMPLE_STRING", + "\"This is a simple string.\""); + + initializeScanner("#define SIMPLE_STRING This is a simple string.\n"); + validateEOF(); + validateDefinition("SIMPLE_STRING", + "This is a simple string."); + + initializeScanner("#define FLAKE\n\nFLAKE"); + validateEOF(); + validateDefinition("FLAKE", ""); + + initializeScanner("#define SIMPLE_STRING This is a simple string.\\\n Continue please."); + validateEOF(); + validateDefinition("SIMPLE_STRING", + "This is a simple string. Continue please."); + } + + public void testBug67834() throws Exception { + initializeScanner("#if ! BAR\n" + + "foo\n" + + "#else\n" + + "bar\n" + + "#endif\n" + ); + validateIdentifier("foo"); + validateEOF(); + initializeScanner("#if ! (BAR)\n" + + "foo\n" + + "#else\n" + + "bar\n" + + "#endif\n" + ); + validateIdentifier("foo"); + validateEOF(); + } + + public void testConcatenation() throws Exception { + 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"); + + 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(); + } + + public void testSimpleIfdef() throws Exception { + 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;"); + 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(); + } + + /** + * @param string + * @param string2 + */ + private void addDefinition(String string, String string2) { + fScanner.addDefinition(string.toCharArray(), string2.toCharArray()); + } + + 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() throws Exception { + initializeScanner("#ifndef BASE\n#define BASE 10\n#endif\n#ifndef BASE\n#error BASE is defined\n#endif"); + validateEOF(); + + 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(); + initializeScanner("#ifndef ONE\n#define ONE 1\n#ifdef TWO\n#define THREE ONE + TWO\n#endif\n#endif\nint three(THREE);"); + 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(); + initializeScanner("#ifndef FOO\n#define FOO 4\n#else\n#undef FOO\n#define FOO 6\n#endif"); + validateEOF(); + validateDefinition("FOO", "4"); + + initializeScanner("#ifndef FOO\n#define FOO 4\n#else\n#undef FOO\n#define FOO 6\n#endif"); + addDefinition("FOO", "2"); + validateEOF(); + 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(); + validateDefinition("ONE", "1"); + validateDefinition("TWO", "ONE + ONE"); + + initializeScanner("#ifndef ONE\r\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"); + + addDefinition("ONE", "one"); + validateEOF(); + 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"); + addDefinition("ONE", "one"); + addDefinition("TWO", "two"); + validateEOF(); + 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"); + addDefinition("TWO", "two"); + validateEOF(); + validateDefinition("ONE", "1"); + validateDefinition("TWO", "2"); + } + + public void testIfs() throws Exception { + initializeScanner("#if 0\n#error NEVER\n#endif\n"); + validateEOF(); + initializeScanner("#define X 5\n#define Y 7\n#if (X < Y)\n#define Z X + Y\n#endif"); + validateEOF(); + validateDefinition("X", "5"); + validateDefinition("Y", "7"); + validateDefinition("Z", "X + Y"); + + initializeScanner("#if T < 20\n#define Z T + 1\n#endif"); + addDefinition("X", "5"); + addDefinition("Y", "7"); + addDefinition("T", "X + Y"); + validateEOF(); + validateDefinition("X", "5"); + validateDefinition("Y", "7"); + validateDefinition("T", "X + Y"); + validateDefinition("Z", "T + 1"); + + initializeScanner("#if ( 10 / 5 ) != 2\n#error 10/5 seems to not equal 2 anymore\n#endif\n"); + validateEOF(); + + 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", ParserMode.QUICK_PARSE); + addDefinition("FIVE", "55"); + validateEOF(); + validateDefinition("FIVE", "55"); + validateDefinition("TEN", "2 * FIVE"); + validateDefinition("MISTAKE", "1"); + validateProblemCount(1); + + 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"); + + addDefinition("ONE", "1"); + addDefinition("TWO", "(ONE + ONE)"); + addDefinition("THREE", "(TWO + ONE)"); + addDefinition("FOUR", "(TWO * TWO)"); + addDefinition("FIVE", "(THREE + TWO)"); + + validateEOF(); + 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(); + initializeScanner(code); + validateEOF(); + validateAllDefinitions(row); + } + + initializeScanner("#if ! 0\n#error Correct!\n#endif"); + validateEOF(); + } + + public void testPreprocessorMacros() throws Exception { + 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); + + validateIdentifier("y"); + validateToken(IToken.tASSIGN); + validateIdentifier("y"); + validateToken(IToken.tPLUS); + validateInteger("1"); + validateToken(IToken.tSEMI); + validateEOF(); + 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(); + + 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); + validateIdentifier("itsOn"); + validateToken(IToken.tASSIGN); + validateInteger("7"); + validateToken(IToken.tSEMI); + validateEOF(); + initializeScanner("#if defined( NOTHING ) \nint x = NOTHING;\n#endif"); + validateEOF(); + } + + public void testQuickScan() throws Exception { + 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(); + + initializeScanner("#if 0\n int error = 666;\n#endif"); + validateEOF(); + + } + + public void testOtherPreprocessorCommands() throws Exception { + initializeScanner("#\n#\t\n#define MAX_SIZE 1024\n#\n# "); + validateEOF(); + validateDefinition("MAX_SIZE", "1024"); + + 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; + } + + validateEOF(); + // These are no longer fScanner exceptions, the are simply ignored. + } + } + + 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 Exception { + initializeScanner("'c'"); + validateChar("c"); + validateEOF(); + } + + 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 Exception { + 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: + addDefinition("THIS", "1"); + addDefinition("THAT", "1"); + break; + case 1: + addDefinition("THIS", "1"); + addDefinition("THAT", "0"); + break; + case 2: + addDefinition("THAT", "1"); + break; + case 3: + 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(); + } + + } + + 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)\nX(55)"); + validateEOF(); + /*IMacroDescriptor macro = fScanner.getDefinition( "X" ); + assertNotNull( macro ); + assertEquals( macro.getParameters().length, 1 ); + assertEquals( macro.getParameters()[0], "Y" ); + assertEquals( macro.getTokenizedExpansion().length, 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); + + //TODO as in 36701B, whitespace is not properly replaced inside the string, ok for now. + //validateString("strncmp(\\\"abc\\\\0d\\\", \\\"abc\\\", '\\\\4') == 0"); + 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", ParserMode.QUICK_PARSE); + validateEOF(); + validateProblemCount(1); + + initializeScanner("#include \n"); + + initializeScanner(buffer.toString()); + validateEOF(); + validateProblemCount(1); // file does not exist + IASTPreprocessorIncludeStatement[] includes= fScanner.getLocationResolver().getIncludeDirectives(); + assertEquals(1, includes.length); + assertEquals("stdio.h", includes[0].getName().toString()); + } + + public void testBug46402() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("#define X 5\n"); + buffer.append("#if defined( X )\n"); + buffer.append("// blah\n"); + buffer.append("#elif Y > 5 \n"); + buffer.append("// coo\n"); + buffer.append("#endif\n"); + initializeScanner(buffer.toString(), ParserMode.COMPLETE_PARSE); + validateEOF(); + } + + public void testBug50821() throws Exception { + initializeScanner("\'\n\n\n", ParserMode.QUICK_PARSE); + fScanner.nextToken(); + validateProblemCount(1); + } + + public void test54778() throws Exception { + initializeScanner("#if 1 || 0 < 3 \n printf \n #endif\n"); + validateIdentifier("printf"); + validateEOF(); + initializeScanner("#if !defined FOO || FOO > 3\nprintf\n#endif\n"); + validateIdentifier("printf"); + validateEOF(); + initializeScanner("#if !defined FOO || FOO < 3\nprintf\n#endif\n"); + validateIdentifier("printf"); + validateEOF(); + } + + public void test68229() throws Exception { + Writer writer = new StringWriter(); + writer.write("#define COUNT 0 \n"); + writer.write("1 \n"); + writer.write("#if COUNT \n"); + writer.write(" 2 \n"); + writer.write("#endif \n"); + writer.write("3 \n"); + + initializeScanner(writer.toString()); + + IToken t1 = fScanner.nextToken(); + IToken t3 = fScanner.nextToken(); + + assertEquals(t1.getImage(), "1"); + assertEquals(t3.getImage(), "3"); + assertEquals(t1.getNext(), t3); + validateEOF(); + + writer = new StringWriter(); + writer.write("#define FOO( x ) x \n"); + writer.write("1 FOO( 2 ) 3 \n"); + + initializeScanner(writer.toString()); + t1 = fScanner.nextToken(); + IToken t2 = fScanner.nextToken(); + t3 = fScanner.nextToken(); + validateEOF(); + + assertEquals(t1.getImage(), "1"); + assertEquals(t2.getImage(), "2"); + assertEquals(t3.getImage(), "3"); + + assertEquals(t1.getNext(), t2); + } + + public void testBug56517() throws Exception { + Writer writer = new StringWriter(); + writer.write("#if 0 \n"); + writer.write("char * x = \"#boo\";\n"); + writer.write("#endif\n"); + initializeScanner(writer.toString()); + validateEOF(); + } + + public void testBug36770B() throws Exception { + Writer writer = new StringWriter(); + writer.write("#define A 0\n"); + writer.write("#if ( A == 1 )\n"); + writer.write("# define foo\n"); + writer.write("#else\n"); + writer.write("# define bar\n"); + writer.write("#endif\n"); + initializeScanner(writer.toString(), ParserMode.QUICK_PARSE); + validateEOF(); + validateDefinition("A", 0); + validateDefinition("bar", ""); + + } + + public void testBug47797() throws Exception { + initializeScanner("\"\\uABCD\" \'\\uABCD\' \\uABCD_ident \\u001A01BC_ident ident\\U01AF ident\\u01bc00AF"); + validateString("\\uABCD"); + validateChar("\\uABCD"); + validateIdentifier("\\uABCD_ident"); + validateIdentifier("\\u001A01BC_ident"); + validateIdentifier("ident\\U01AF"); + validateIdentifier("ident\\u01bc00AF"); + validateEOF(); + } + + public void testBug59768() throws Exception { + initializeScanner("#define A A\nA"); + validateIdentifier("A"); + validateEOF(); + /*IMacroDescriptor d = fScanner.getDefinition( "A"); + assertTrue( d.isCircular() );*/ + } + + public void testBug60764() throws Exception { + Writer writer = new StringWriter(); + writer.write("#define P a,b\n"); + writer.write("#define M(x) M1(x)\n"); + writer.write("#define M1(x,y) #x #y\n"); + writer.write("M(P)\n"); + initializeScanner(writer.toString()); + validateString("ab"); + validateEOF(); + } + + public void testBug62042() throws Exception { + initializeScanner("0x", ParserMode.QUICK_PARSE); + validateInteger("0x"); // to me this is a valid number + validateEOF(); + } + + public void testBug61968() throws Exception { + Writer writer = new StringWriter(); + writer.write("unsigned int ui = 2172748163; //ok \n"); + writer.write("int big = 999999999999999;//ok \n"); + writer.write("void main() { \n"); + writer.write("caller(4); //ok\n"); + writer + .write("caller(2172748163);//causes java.lang.NumberFormatException \n"); + writer + .write("caller(999999999999999); //also causes NumberFormatException \n"); + writer.write("}\n"); + initializeScanner(writer.toString(), ParserMode.QUICK_PARSE); + fullyTokenize(); + validateProblemCount(0); + } + + public void testBug62378() throws Exception { + initializeScanner("\"\\?\\?<\""); + validateString("\\?\\?<"); + } + + public void testBug62384() throws Exception { + initializeScanner("18446744073709551615LL"); + validateInteger("18446744073709551615LL"); + } + + public void testBug62390() throws Exception { + Writer writer = new StringWriter(); + writer.write("#define f(x) x\n"); + writer.write("#if f(\n"); + writer.write("5) == 5\n"); + writer.write("true1\n"); + writer.write("#endif\n"); + writer.write("#if A\n"); + writer.write("#elif f(\n"); + writer.write("5) == 5\n"); + writer.write("true2\n"); + writer.write("#endif\n"); + writer.write("#undef f\n"); + writer.write("#define f(x) \"A0I70_001.h\"\n"); + writer.write("#include f(\n"); + writer.write("5\n"); + writer.write(")\n"); + writer.write("#undef f\n"); + writer.write("#define f(x) 1467\n"); + writer.write("#line f(\n"); + writer.write("5\n"); + writer.write(")\n"); + writer.write("#pragma f(\n"); + writer.write("5\n"); + writer.write(")\n"); + writer.write("}\n"); + initializeScanner(writer.toString(), ParserMode.QUICK_PARSE); + fullyTokenize(); + } + + public void testBug62009() throws Exception { + initializeScanner("#define def(x) (x#)\ndef(orange)\n", ParserMode.QUICK_PARSE); + fullyTokenize(); + validateProblemCount(1); + } + + public void testBug61972() throws Exception { + initializeScanner("#define DEF1(A1) A1\n#define DEF2 DEF1(DEF2)\nDEF2;"); + validateIdentifier("DEF2"); + validateToken(IToken.tSEMI); + validateEOF(); + } + + public void testBug64268() throws Exception { + Writer writer = new StringWriter(); + writer.write("#define BODY \\\n"); + writer.write(" { \\\n"); + writer.write(" /* this multi-line comment messes \\\n"); + writer.write(" up the parser. */ }\n"); + writer.write("BODY "); + initializeScanner(writer.toString()); + validateToken(IToken.tLBRACE); + validateToken(IToken.tRBRACE); + validateEOF(); + } + + public void testUndef() throws Exception { + initializeScanner("#define A 5\n" + + "#define B 10\n" + + "#undef A\n" + + "A B"); + validateIdentifier("A"); + validateInteger("10"); + validateEOF(); + } + + public void testWackyFunctionMacros() throws Exception { + initializeScanner("#define A(X) hi##X\n" + + "#define B(Y) A(Y)\n" + + "B(there)"); + validateIdentifier("hithere"); + validateEOF(); + } + + public void testSlashes() throws Exception { + initializeScanner("__q / __n"); + validateIdentifier("__q"); + validateToken(IToken.tDIV); + validateIdentifier("__n"); + validateEOF(); + } + + public void testStringify() throws Exception { + initializeScanner("#define xS(s) #s\n#define S(s) xS(s)\n#define X hi\nS(X)"); + validateString("hi"); + validateEOF(); + } + + public void testWideToNarrowConcatenation() throws Exception { + initializeScanner("\"ONE\" L\"TWO\""); + validateLString("ONETWO"); + validateEOF(); + } + + public void testEmptyIncludeDirective() throws Exception { + initializeScanner("#include \n#include \n"); + validateEOF(); + IASTPreprocessorIncludeStatement[] includes= fScanner.getLocationResolver().getIncludeDirectives(); + assertEquals(1, includes.length); + assertEquals("foo.h", includes[0].getName().toString()); + } + + public void testBug69412() throws Exception { + initializeScanner("\'\\\\\'", ParserMode.COMPLETE_PARSE); + validateChar("\\\\"); + validateEOF(); + validateProblemCount(0); + } + + public void testBug70072() throws Exception { + initializeScanner("#if 1/0\nint i;\n#elif 2/0\nint j;\n#endif\nint k;\n"); + fullyTokenize(); + } + + public void testBug70261() throws Exception { + initializeScanner("0X0"); + validateInteger("0X0"); + } + + public void testBug62571() throws Exception { + StringBuffer buffer = new StringBuffer("#define J(X,Y) X##Y\n"); + buffer.append("J(A,1Xxyz)\n"); + buffer.append("J(B,1X1X1Xxyz)\n"); + buffer.append("J(C,0Xxyz)\n"); + buffer.append("J(CC,0Xxyz)\n"); + buffer.append("J(D,0xxyz)\n"); + buffer.append("J(E,0x0x0xxyz)\n"); + initializeScanner(buffer.toString()); + validateIdentifier("A1Xxyz"); + validateIdentifier("B1X1X1Xxyz"); + validateIdentifier("C0Xxyz"); + validateIdentifier("CC0Xxyz"); + validateIdentifier("D0xxyz"); + validateIdentifier("E0x0x0xxyz"); + } + + public void testBug69134() throws Exception { + Writer writer = new StringWriter(); + writer.write("# ifdef YYDEBUG\n"); + writer.write("if (yyDebug) {\n"); + writer.write("(void) fprintf (yyTrace,\n"); + writer + .write("\" # |Position|State|Mod|Lev|Action |Terminal and Lookahead or Rule\n\");\n"); + writer.write("yyNl ();\n"); + writer.write("}\n"); + writer.write("# endif\n"); + initializeScanner(writer.toString()); + fullyTokenize(); + validateProblemCount(0); + } + + public void testBug70073() throws Exception { + StringBuffer buffer = new StringBuffer( + "#if CONST \n #endif \n #elif CONST \n int"); + final List problems = new ArrayList(); + ISourceElementRequestor requestor = new NullSourceElementRequestor() { + public boolean acceptProblem(IProblem problem) { + problems.add(problem); + return super.acceptProblem(problem); + } + }; + initializeScanner(buffer.toString()); + validateToken(IToken.t_int); + validateProblemCount(1); + } + + public void testBug73652() throws Exception { + StringWriter writer = new StringWriter(); + writer.write("#define DoSuperMethodA IDoSuperMethodA\n"); + writer + .write("#define IDoSuperMethodA(a,b,c) IIntuition->IDoSuperMethodA(a,b,c)\n"); + writer.write("DoSuperMethodA(0,0,0);\n"); + + initializeScanner(writer.toString()); + + validateIdentifier("IIntuition"); + validateToken(IToken.tARROW); + validateIdentifier("IDoSuperMethodA"); + validateToken(IToken.tLPAREN); + validateInteger("0"); + validateToken(IToken.tCOMMA); + validateInteger("0"); + validateToken(IToken.tCOMMA); + validateInteger("0"); + validateToken(IToken.tRPAREN); + validateToken(IToken.tSEMI); + validateEOF(); + } + + public void testBug73652_2() throws Exception { + StringWriter writer = new StringWriter(); + writer.write("#define DoSuperMethodA DoSuperMethodB //doobalie\n"); + writer.write("#define DoSuperMethodB DoSuperMethodC /*oogalie*/ \n"); + writer.write("#define DoSuperMethodC IDoSuperMethodA \\\n\n"); + writer + .write("#define IDoSuperMethodA(a,b,c) IIntuition->IDoSuperMethodA(a,b,c)\n"); + writer.write("DoSuperMethodA (0,0,0);\n"); + + initializeScanner(writer.toString()); + + validateIdentifier("IIntuition"); + validateToken(IToken.tARROW); + validateIdentifier("IDoSuperMethodA"); + validateToken(IToken.tLPAREN); + validateInteger("0"); + validateToken(IToken.tCOMMA); + validateInteger("0"); + validateToken(IToken.tCOMMA); + validateInteger("0"); + validateToken(IToken.tRPAREN); + validateToken(IToken.tSEMI); + validateEOF(); + + } + + public void testBug72997() throws Exception { + initializeScanner("'\\\\'"); + validateChar("\\\\"); + validateEOF(); + } + + public void testBug72725() throws Exception { + for (int i = 0; i < 2; ++i) { + StringBuffer buffer = new StringBuffer(); + buffer.append("#define a \\"); + if (i == 0) + buffer.append("\r"); + buffer.append("\n"); + buffer.append("long macro stuff"); + if (i == 0) + buffer.append("\r"); + buffer.append("\n"); + + initializeScanner(buffer.toString()); + validateEOF(); + validateProblemCount(0); + } + } + + public void testBug72506() throws Exception { + StringWriter writer = new StringWriter(); + writer.write("#define INCFILE(x) ver ## x\n"); + writer.write("#define xstr(x) str(x)\n"); + writer.write("#define str(x) #x\n"); + writer.write("xstr(INCFILE(2).h)\n"); + + initializeScanner(writer.toString()); + validateString("ver2.h"); + validateEOF(); + } + + public void testBug72506_2() throws Exception { + StringWriter writer = new StringWriter(); + writer.write("#define str(x) #x\n"); + writer.write("#define A B\n"); + writer.write("#define B A\n"); + writer.write("str(B)\n"); + + initializeScanner(writer.toString()); + validateString("B"); + validateEOF(); + } + + public void testMacroPastingError() throws Exception { + StringWriter writer = new StringWriter(); + writer.write("#define m(expr) \\\r\n"); + writer.write(" foo( #expr ) \r\n"); + + initializeScanner(writer.toString()); + validateEOF(); + validateProblemCount(0); + } + + public void testBug74176() throws Exception { + initializeScanner("#define MYSTRING \"X Y Z "); + validateEOF(); + + initializeScanner("#define m(b) #"); + validateEOF(); + + initializeScanner("#define m(foo,b) #b"); + validateEOF(); + } + + public void testBug74180() throws Exception { + initializeScanner("true false", ParserLanguage.C); + validateIdentifier("true"); + validateIdentifier("false"); + + initializeScanner("true false", ParserLanguage.CPP); + validateToken(IToken.t_true); + validateToken(IToken.t_false); + } + + public void testBug73492() throws Exception { + String code = "#define PTR void *\n" + + "PTR;\n"; + + int offset = code.indexOf("PTR;") + 3; + initializeScanner(code); + + IToken t = fScanner.nextToken(); + assertEquals(t.getType(), IToken.t_void); + assertEquals(offset, t.getOffset()); + + t = fScanner.nextToken(); + assertEquals(t.getType(), IToken.tSTAR); + assertEquals(offset + 5, t.getOffset()); + + t = fScanner.nextToken(); + assertEquals(t.getType(), IToken.tSEMI); + assertEquals(offset + 6, t.getOffset()); + } + + public void testBug74328() throws Exception { + initializeScanner("\"\";\n"); + validateString(""); + validateToken(IToken.tSEMI); + validateEOF(); + } + + public void testBug72537() throws Exception { + initializeScanner("FOO BAR(boo)"); + fScanner.addDefinition("FOO".toCharArray(), "foo".toCharArray()); + fScanner.addDefinition("BAR(x)".toCharArray(), "x".toCharArray()); + + validateIdentifier("foo"); + validateIdentifier("boo"); + validateEOF(); + } + + public void testBug75083() throws Exception { + String code = "#define blah() { extern foo\n blah()\n"; + initializeScanner(code); + + int idx = code.indexOf("\n blah()") + 2 + 6; + IToken t = fScanner.nextToken(); + assertEquals(t.getType(), IToken.tLBRACE); + assertEquals(idx, t.getOffset()); + assertEquals(idx + 1, t.getEndOffset()); + + t = fScanner.nextToken(); + assertEquals(t.getType(), IToken.t_extern); + assertEquals(idx + 2, t.getOffset()); + assertEquals(idx + 8, t.getEndOffset()); + + t = fScanner.nextToken(); + assertEquals(t.getType(), IToken.tIDENTIFIER); + assertEquals(idx + 9, t.getOffset()); + assertEquals(idx + 12, t.getEndOffset()); + } + + // when fixing 75532 several IProblems were added to ExpressionEvaluator and one to Scanner2, this is to test them + // the problems currently don't get reported when using the DOMScanner + public void _testBug75532IProblems() throws Exception { + Writer writer = new StringWriter(); + writer.write("#if 09 == 9\n#endif\n"); // malformed octal + writer.write("#if 1A == 0x1A\n#endif\n"); // malformed decimal + writer.write("#if 0x == 0x0\n#endif\n"); // malformed hex + writer.write("#if 0xAX == 0xA\n#endif\n"); // malformed hex + writer.write("#if 1/0 == 1\n#endif\n"); // division by zero + writer.write("#if defined ( sadf a\n#endif\n"); // missing ')' in defined + writer.write("#if defined ( sadf\n#endif\n"); // missing ')' in defined + writer.write("#if defined ( 2sadf )\n#endif\n"); // illegal identifier in defined + writer.write("#if ( 1 == 1 ? 1\n#endif\n"); // bad conditional expression + writer.write("#if ( \n#endif\n"); // expression syntax error + writer.write("#if @\n#endif\n"); // expression syntax error + writer.write("#if \n#endif\n"); // expression syntax error + writer.write("#if -\n#endif\n"); // expression syntax error + writer.write("#if ( 1 == 1\n#endif\n"); // missing ')' + writer.write("#if 1 = 1\n#endif\n"); // assignment not allowed + + writer.write("int main(int argc, char **argv) {\n"); + writer.write("if ( 09 == 9 )\n"); // added while fixing this bug, IProblem on invalid octal number + writer.write("return 1;\nreturn 0;\n}\n"); + + initializeScanner(writer.toString()); + fullyTokenize(); + IASTProblem[] problems= fScanner.getLocationResolver().getScannerProblems(); + assertEquals(16, problems.length); + assertTrue(problems[0].getID() == IProblem.SCANNER_BAD_OCTAL_FORMAT); + assertTrue(problems[1].getID() == IProblem.SCANNER_BAD_DECIMAL_FORMAT); + assertTrue(problems[2].getID() == IProblem.SCANNER_BAD_HEX_FORMAT); + assertTrue(problems[3].getID() == IProblem.SCANNER_BAD_HEX_FORMAT); + assertTrue(problems[4].getID() == IProblem.SCANNER_DIVIDE_BY_ZERO); + assertTrue(problems[5].getID() == IProblem.SCANNER_MISSING_R_PAREN); + assertTrue(problems[6].getID() == IProblem.SCANNER_MISSING_R_PAREN); + assertTrue(problems[7].getID() == IProblem.SCANNER_ILLEGAL_IDENTIFIER); + assertTrue(problems[8].getID() == IProblem.SCANNER_BAD_CONDITIONAL_EXPRESSION); + assertTrue(problems[9].getID() == IProblem.SCANNER_EXPRESSION_SYNTAX_ERROR); + assertTrue(problems[10].getID() == IProblem.SCANNER_EXPRESSION_SYNTAX_ERROR); + assertTrue(problems[11].getID() == IProblem.SCANNER_EXPRESSION_SYNTAX_ERROR); + assertTrue(problems[12].getID() == IProblem.SCANNER_EXPRESSION_SYNTAX_ERROR); + assertTrue(problems[13].getID() == IProblem.SCANNER_MISSING_R_PAREN); + assertTrue(problems[14].getID() == IProblem.SCANNER_ASSIGNMENT_NOT_ALLOWED); + assertTrue(problems[15].getID() == IProblem.SCANNER_BAD_OCTAL_FORMAT); + } + + public void testExpressionEvalProblems() throws Exception { + Writer writer = new StringWriter(); + writer.write(" #if 1 == 1L \n"); + writer.write(" #endif \n"); + + initializeScanner(writer.toString()); + validateEOF(); + validateProblemCount(0); + } + + public void testExpressionEvalProblems_2() throws Exception { + Writer writer = new StringWriter(); + writer.write("#define FOO( a, b ) a##b \n"); + writer.write("#if FOO ( 1, 0 ) == 10 \n"); + writer.write("1 \n"); + writer.write("#endif \n"); + + initializeScanner(writer.toString()); + validateInteger("1"); + validateEOF(); + validateProblemCount(0); + } + + public void testUnExpandedFunctionMacro() throws Exception { + Writer writer = new StringWriter(); + writer.write("#define foo( a ) #a \n"); + writer.write("foo( 1 ) foo \n"); + + initializeScanner(writer.toString()); + validateString("1"); + validateIdentifier("foo"); + validateEOF(); + } + + public void testBug39688A() throws Exception { // test valid IProblems + Writer writer = new StringWriter(); + writer.write("#define decl1(type, ... \\\n ) type var;\n"); + writer.write("decl1(int, x, y, z)\n"); + writer.write("#define decl2(type, args...) type args;"); + writer.write("decl2(int, a, b, c, x, y, z)\n"); + writer.write("#define decl3(type, args...) \\\n type args;"); + writer.write("decl3(int, a, b, c, x, y)\n"); + writer.write("#define decl4(type, args... \\\n ) type args;"); + writer.write("decl4(int, a, b, z)\n"); + writer.write("#define decl5(type, ...) type __VA_ARGS__;"); + writer.write("decl5(int, z)\n"); + writer.write("#define decl6(type, ... \\\n) type __VA_ARGS__;"); + writer.write("decl6(int, a, b, c, x)\n"); + writer.write("#define foo(a) a __VA_ARGS__;\n"); // C99: 6.10.3.5 this should produce an IProblem + writer.write("#define foo2(a) a #__VA_ARGS__;\n"); // C99: 6.10.3.5 this should produce an IProblem + + initializeScanner(writer.toString()); + fullyTokenize(); + IASTProblem[] problems= fScanner.getLocationResolver().getScannerProblems(); + assertEquals(2, problems.length); + assertTrue(problems[0].getID() == IProblem.PREPROCESSOR_INVALID_VA_ARGS); + assertTrue(problems[1].getID() == IProblem.PREPROCESSOR_MACRO_PASTING_ERROR); + } + + public void testBug39688B() throws Exception { // test C99 + Writer writer = new StringWriter(); + writer.write("#define debug(...) fprintf(stderr, __VA_ARGS__)\n"); + writer.write("#define showlist(...) puts(#__VA_ARGS__)\n"); + writer + .write("#define report(test, ...) ((test)?puts(#test):\\\n printf(__VA_ARGS__))\n"); + writer.write("int main() {\n"); + writer.write("debug(\"Flag\");\n"); + writer.write("debug(\"X = %d\\n\", x);\n"); + writer.write("showlist(The first, second, and third items.);\n"); + writer.write("report(x>y, \"x is %d but y is %d\", x, y);\n"); + writer.write("return 0; }\n"); + + initializeScanner(writer.toString()); + fullyTokenize(); + validateProblemCount(0); + + Map defs = fScanner.getDefinitions(); + assertTrue(defs.containsKey("debug")); + assertTrue(defs.containsKey("showlist")); + assertTrue(defs.containsKey("report")); + FunctionStyleMacro debug = (FunctionStyleMacro) defs.get("debug"); + assertTrue(new String(debug.arglist[0]).equals("__VA_ARGS__")); + assertTrue(debug.hasVarArgs()); + assertFalse(debug.hasGCCVarArgs()); + assertTrue(new String(debug.getExpansion()) + .equals("fprintf(stderr, __VA_ARGS__)")); + FunctionStyleMacro showlist = (FunctionStyleMacro) defs.get("showlist"); + assertTrue(new String(showlist.arglist[0]).equals("__VA_ARGS__")); + assertTrue(showlist.hasVarArgs()); + assertFalse(showlist.hasGCCVarArgs()); + assertTrue(new String(showlist.getExpansion()) + .equals("puts(#__VA_ARGS__)")); + FunctionStyleMacro report = (FunctionStyleMacro) defs.get("report"); + assertTrue(new String(report.arglist[0]).equals("test")); + assertTrue(new String(report.arglist[1]).equals("__VA_ARGS__")); + assertTrue(report.hasVarArgs()); + assertFalse(report.hasGCCVarArgs()); + assertTrue(new String(report.getExpansion()) + .equals("((test)?puts(#test): printf(__VA_ARGS__))")); + + check39688Tokens(writer); + } + + public void testBug39688C() throws Exception { // test GCC + Writer writer = new StringWriter(); + writer.write("#define debug(vars...) fprintf(stderr, vars)\n"); + writer.write("#define showlist(vars...) puts(#vars)\n"); + writer + .write("#define report(test, vars...) ((test)?puts(#test):\\\n printf(vars))\n"); + writer.write("int main() {\n"); + writer.write("debug(\"Flag\");\n"); + writer.write("debug(\"X = %d\\n\", x);\n"); + writer.write("showlist(The first, second, and third items.);\n"); + writer.write("report(x>y, \"x is %d but y is %d\", x, y);\n"); + writer.write("return 0; }\n"); + + initializeScanner(writer.toString()); + fullyTokenize(); + validateProblemCount(0); + + Map defs = fScanner.getDefinitions(); + assertTrue(defs.containsKey("debug")); + assertTrue(defs.containsKey("showlist")); + assertTrue(defs.containsKey("report")); + FunctionStyleMacro debug = (FunctionStyleMacro) defs.get("debug"); + assertTrue(new String(debug.arglist[0]).equals("vars")); + assertFalse(debug.hasVarArgs()); + assertTrue(debug.hasGCCVarArgs()); + assertTrue(new String(debug.getExpansion()) + .equals("fprintf(stderr, vars)")); + FunctionStyleMacro showlist = (FunctionStyleMacro) defs.get("showlist"); + assertTrue(new String(showlist.arglist[0]).equals("vars")); + assertFalse(showlist.hasVarArgs()); + assertTrue(showlist.hasGCCVarArgs()); + assertTrue(new String(showlist.getExpansion()).equals("puts(#vars)")); + FunctionStyleMacro report = (FunctionStyleMacro) defs.get("report"); + assertTrue(new String(report.arglist[0]).equals("test")); + assertTrue(new String(report.arglist[1]).equals("vars")); + assertFalse(report.hasVarArgs()); + assertTrue(report.hasGCCVarArgs()); + assertTrue(new String(report.getExpansion()) + .equals("((test)?puts(#test): printf(vars))")); + + check39688Tokens(writer); + } + + private void check39688Tokens(Writer writer) throws Exception { + initializeScanner(writer.toString()); + + validateToken(IToken.t_int); + validateIdentifier("main"); + validateToken(IToken.tLPAREN); + validateToken(IToken.tRPAREN); + validateToken(IToken.tLBRACE); + + validateIdentifier("fprintf"); + validateToken(IToken.tLPAREN); + validateIdentifier("stderr"); + validateToken(IToken.tCOMMA); + validateString("Flag"); + validateToken(IToken.tRPAREN); + validateToken(IToken.tSEMI); + + validateIdentifier("fprintf"); + validateToken(IToken.tLPAREN); + validateIdentifier("stderr"); + validateToken(IToken.tCOMMA); + validateString("X = %d\\n"); + validateToken(IToken.tCOMMA); + validateIdentifier("x"); + validateToken(IToken.tRPAREN); + validateToken(IToken.tSEMI); + + validateIdentifier("puts"); + validateToken(IToken.tLPAREN); + validateString("The first, second, and third items."); + validateToken(IToken.tRPAREN); + validateToken(IToken.tSEMI); + + validateToken(IToken.tLPAREN); + validateToken(IToken.tLPAREN); + validateIdentifier("x"); + validateToken(IToken.tGT); + validateIdentifier("y"); + validateToken(IToken.tRPAREN); + validateToken(IToken.tQUESTION); + validateIdentifier("puts"); + validateToken(IToken.tLPAREN); + validateString("x>y"); + validateToken(IToken.tRPAREN); + validateToken(IToken.tCOLON); + validateIdentifier("printf"); + validateToken(IToken.tLPAREN); + validateString("x is %d but y is %d"); + validateToken(IToken.tCOMMA); + validateIdentifier("x"); + validateToken(IToken.tCOMMA); + validateIdentifier("y"); + validateToken(IToken.tRPAREN); + validateToken(IToken.tRPAREN); + validateToken(IToken.tSEMI); + + validateToken(IToken.t_return); + validateInteger("0"); + validateToken(IToken.tSEMI); + validateToken(IToken.tRBRACE); + + validateEOF(); + } + + public void testMacroArgumentExpansion() throws Exception { + Writer writer = new StringWriter(); + writer + .write("#define g_return( expr ) ( expr ) \n"); + writer + .write("#define ETH( obj ) ( CHECK( (obj), boo ) ) \n"); + writer + .write("#define CHECK CHECK_INSTANCE \n"); + writer + .write("#define CHECK_INSTANCE( instance, type ) (foo((instance), (type))) \n"); + writer + .write("g_return( ETH(ooga) ) \n"); + + initializeScanner(writer.toString()); + + validateToken(IToken.tLPAREN); + validateToken(IToken.tLPAREN); + validateToken(IToken.tLPAREN); + validateIdentifier("foo"); + validateToken(IToken.tLPAREN); + validateToken(IToken.tLPAREN); + validateToken(IToken.tLPAREN); + validateIdentifier("ooga"); + validateToken(IToken.tRPAREN); + validateToken(IToken.tRPAREN); + validateToken(IToken.tCOMMA); + validateToken(IToken.tLPAREN); + validateIdentifier("boo"); + validateToken(IToken.tRPAREN); + validateToken(IToken.tRPAREN); + validateToken(IToken.tRPAREN); + validateToken(IToken.tRPAREN); + validateToken(IToken.tRPAREN); + } + + public void testBug75956() throws Exception { + Writer writer = new StringWriter(); + writer.write("#define ROPE( name ) name##Alloc\n"); + writer.write("#define _C 040 \n"); + writer.write("ROPE( _C ) \n"); + + initializeScanner(writer.toString()); + validateIdentifier("_CAlloc"); + validateEOF(); + + writer = new StringWriter(); + writer.write("#define ROPE( name ) Alloc ## name \n"); + writer.write("#define _C 040 \n"); + writer.write("ROPE( _C ) \n"); + + initializeScanner(writer.toString()); + validateIdentifier("Alloc_C"); + validateEOF(); + + writer = new StringWriter(); + writer.write("#define ROPE( name ) name##Alloc\n"); + writer.write("#define _C 040 \n"); + writer.write("#define _CAlloc ooga \n"); + writer.write("ROPE( _C ) \n"); + + initializeScanner(writer.toString()); + validateIdentifier("ooga"); + validateEOF(); + } + + public void testUnExpandedFunctionMacros() throws Exception { + Writer writer = new StringWriter(); + writer.write("#define ETH(x) x \n"); + writer.write("#define E ETH \n"); + writer.write("ETH( c ), ETH, E; \n"); + initializeScanner(writer.toString()); + validateIdentifier("c"); + validateToken(IToken.tCOMMA); + validateIdentifier("ETH"); + validateToken(IToken.tCOMMA); + validateIdentifier("ETH"); + validateToken(IToken.tSEMI); + validateEOF(); + } + + public void testBug79490A() throws Exception { + Writer writer = new StringWriter(); + writer.write("#define TEST 'n'\n"); + writer.write("#if TEST == 'y'\n"); + writer.write("#define TRUE 1\n"); + writer.write("#else\n"); + writer.write("#define FALSE 1\n"); + writer.write("#endif\n"); + initializeScanner(writer.toString()); + validateEOF(); + validateDefinition("TEST", "'n'"); + validateDefinition("FALSE", "1"); + } + + public void testBug79490B() throws Exception { + Writer writer = new StringWriter(); + writer.write("#define TEST 'y'\n"); + writer.write("#if TEST == 'y'\n"); + writer.write("#define TRUE 1\n"); + writer.write("#else\n"); + writer.write("#define FALSE 1\n"); + writer.write("#endif\n"); + initializeScanner(writer.toString()); + validateEOF(); + validateDefinition("TEST", "'y'"); + validateDefinition("TRUE", "1"); + } + + public void testBug102568A() throws Exception { + initializeScanner("///*\r\nint x;\r\n"); + validateToken(IToken.t_int); + validateIdentifier("x"); + validateToken(IToken.tSEMI); + validateEOF(); + } + + public void testBug102568B() throws Exception { + initializeScanner("// bla some thing /* ... \r\nint x;\r\n"); + validateToken(IToken.t_int); + validateIdentifier("x"); + validateToken(IToken.tSEMI); + validateEOF(); + } + + public void testbug84270() throws Exception { + Writer writer = new StringWriter(); + writer.write("#define h g( ~\n"); + writer.write("#define g f\n"); + writer.write("#define f(a) f(x * (a))\n"); + writer.write("h 5) \n"); + initializeScanner(writer.toString()); + fullyTokenize(); + } + + public void testBug107150() throws Exception { + Writer writer = new StringWriter(); + writer.write("#define FUNC_PROTOTYPE_PARAMS(list) list\r\n"); + writer.write("int func2 FUNC_PROTOTYPE_PARAMS\r\n"); + writer.write("((int arg1)){\r\n"); + writer.write(" return 0;\r\n"); + writer.write("}\r\n"); + initializeScanner(writer.toString()); + validateToken(IToken.t_int); + validateIdentifier("func2"); + validateToken(IToken.tLPAREN); + validateToken(IToken.t_int); + validateIdentifier("arg1"); + validateToken(IToken.tRPAREN); + validateToken(IToken.tLBRACE); + validateToken(IToken.t_return); + validateInteger("0"); + validateToken(IToken.tSEMI); + validateToken(IToken.tRBRACE); + validateEOF(); + + writer = new StringWriter(); + writer.write("#define FUNC_PROTOTYPE_PARAMS(list) list\n"); + writer.write("int func2 FUNC_PROTOTYPE_PARAMS\n"); + writer.write("((int arg1)){\n"); + writer.write(" return 0;\n"); + writer.write("}\n"); + initializeScanner(writer.toString()); + validateToken(IToken.t_int); + validateIdentifier("func2"); + validateToken(IToken.tLPAREN); + validateToken(IToken.t_int); + validateIdentifier("arg1"); + validateToken(IToken.tRPAREN); + validateToken(IToken.tLBRACE); + validateToken(IToken.t_return); + validateInteger("0"); + validateToken(IToken.tSEMI); + validateToken(IToken.tRBRACE); + validateEOF(); + } + + public void testBug126136() throws Exception { + StringBuffer buffer = new StringBuffer("#define C C\n"); + buffer.append("#if !C\n"); + buffer.append("true\n"); + buffer.append("#endif\n"); + initializeScanner(buffer.toString(), ParserLanguage.CPP); + fullyTokenize(); + } + + public void testBug156137() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("#if (3 % 2 == 1) \n"); + buffer.append("C \n"); + buffer.append("#endif \n"); + + initializeScanner(buffer.toString()); + validateIdentifier("C"); + validateEOF(); + } + + public void testBug162214() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("#ifdef xxx // is not defined \n"); + buffer.append("A \n"); + buffer.append("#endif \n"); + buffer.append("B \n"); + + initializeScanner(buffer.toString()); + validateIdentifier("B"); + validateEOF(); + + buffer.setLength(0); + buffer.append("#ifdef xxx //* is not defined \n"); + buffer.append("A \n"); + buffer.append("#endif \n"); + buffer.append("B \n"); + + initializeScanner(buffer.toString()); + validateIdentifier("B"); + validateEOF(); + } + + public void testBug156988() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("#define a \n"); + buffer.append("#define b \" \n"); + buffer.append("#define c < \n"); + buffer.append("#define d \"\" \n"); + buffer.append("#define e <> \n"); + buffer.append("#define f f \n"); + buffer.append("#define g gg \n"); + buffer.append("#include a \n"); + buffer.append("#include b \n"); + buffer.append("#include c \n"); + buffer.append("#include d \n"); + buffer.append("#include e \n"); + buffer.append("#include f \n"); + buffer.append("#include g \n"); + buffer.append("A \n"); + + initializeScanner(buffer.toString()); + validateIdentifier("A"); + validateEOF(); + } + + public void testBug156988_1() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("#define a(x) x \n"); + buffer.append("#define b \" \n"); + buffer.append("#define c < \n"); + buffer.append("#define d \"\" \n"); + buffer.append("#define e <> \n"); + buffer.append("#define f f \n"); + buffer.append("#define g gg \n"); + buffer.append("#include a() \n"); + buffer.append("#include a(<) \n"); + buffer.append("#include a(\"\") \n"); + buffer.append("#include a(<>) \n"); + buffer.append("#include a(f) \n"); + buffer.append("#include a(gg) \n"); + buffer.append("#include a(g\\\ng) \n"); + buffer.append("A \n"); + + initializeScanner(buffer.toString()); + validateIdentifier("A"); + validateEOF(); + } + + public void testBug162410() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("#pragma message (\"test\") \n"); + buffer.append("a \n"); + initializeScanner(buffer.toString()); + validateIdentifier("a"); + } + + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=180172 + public void testBug180172() throws Exception { + StringBuffer buffer = new StringBuffer(); + String value = "\"https://bugs.eclipse.org/bugs/show_bug.cgi?id=180172\""; + buffer.append("#define bug180172 ").append(value).append(" // bla \n"); + initializeScanner(buffer.toString()); + fullyTokenize(); + validateDefinition("bug180172", value); + } + + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=182180 + public void testBug182180_1() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("#ifdef _bug_182180_\n").append( + "printf(\"Hello World /*.ap\\n\");\n").append("#endif\n") + .append("bug182180\n"); + initializeScanner(buffer.toString()); + validateIdentifier("bug182180"); + } + + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=182180 + public void testBug182180_2() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("#ifdef _bug_182180_\n").append( + "char c='\"'; printf(\"Hello World /*.ap\\n\");\n").append( + "#endif\n").append("bug182180\n"); + initializeScanner(buffer.toString()); + validateIdentifier("bug182180"); + } + + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=182180 + public void testBug182180_3() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("#ifdef _bug_182180_\n").append( + "char c1='\\'',c2='\\\"'; printf(\"Hello World /*.ap\\n\");\n") + .append("#endif\n").append("bug182180\n"); + initializeScanner(buffer.toString()); + validateIdentifier("bug182180"); + } + + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=182180 + public void testBug182180_4() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("#ifdef _bug_182180_\n").append( + "printf(\"Hello '\"'World /*.ap\\n\");\n").append("#endif\n") + .append("bug182180\n"); + initializeScanner(buffer.toString()); + validateIdentifier("bug182180"); + } + + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=182180 + public void testBug182180_5() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("#ifdef _bug_182180_\n").append( + "printf(\"Hello \\\"World /*.ap\\n\");\n").append("#endif\n") + .append("bug182180\n"); + initializeScanner(buffer.toString()); + validateIdentifier("bug182180"); + } + + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=200830 + public void testBug200830_1() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("#define string BROKEN\r\n"); + buffer.append("#define macro(inst) (char*)inst\r\n"); + buffer.append("macro(\"string\");\r\n"); + initializeScanner(buffer.toString()); + validateToken(IToken.tLPAREN); + validateToken(IToken.t_char); + validateToken(IToken.tSTAR); + validateToken(IToken.tRPAREN); + validateString("string"); + } + + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=200830 + public void testBug200830_2() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("#define string BROKEN\r\n"); + buffer.append("#define macro(inst) (char*)inst\r\n"); + buffer.append("macro(\" string \");\r\n"); + initializeScanner(buffer.toString()); + validateToken(IToken.tLPAREN); + validateToken(IToken.t_char); + validateToken(IToken.tSTAR); + validateToken(IToken.tRPAREN); + validateString(" string "); + } + + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=200830 + public void testBug200830_3() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("#define string BROKEN\r\n"); + buffer.append("#define macro(inst) (char*)inst\r\n"); + buffer.append("macro(\"\\\"string \");\r\n"); + initializeScanner(buffer.toString()); + validateToken(IToken.tLPAREN); + validateToken(IToken.t_char); + validateToken(IToken.tSTAR); + validateToken(IToken.tRPAREN); + validateString("\\\"string "); + } + + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=200830 + public void testBug200830_4() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("#define s B\r\n"); + buffer.append("#define macro(inst) (char*)inst\r\n"); + buffer.append("macro('s');\r\n"); + initializeScanner(buffer.toString()); + validateToken(IToken.tLPAREN); + validateToken(IToken.t_char); + validateToken(IToken.tSTAR); + validateToken(IToken.tRPAREN); + validateChar("s"); + } + + public void testBug185120_1() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("#define TEST_DEFINE 1UL\n"); + buffer.append("#if TEST_DEFINE != 1UL\n"); + buffer.append("-\n"); + buffer.append("#else\n"); + buffer.append("+\n"); + buffer.append("#endif\n"); + initializeScanner(buffer.toString()); + validateToken(IToken.tPLUS); + } + + public void testBug185120_2() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("#define TEST_DEFINE 1LLU\n"); + buffer.append("#if TEST_DEFINE != 1ULL\n"); + buffer.append("-\n"); + buffer.append("#else\n"); + buffer.append("+\n"); + buffer.append("#endif\n"); + initializeScanner(buffer.toString()); + validateToken(IToken.tPLUS); + } } diff --git a/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/BaseTestCase.java b/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/BaseTestCase.java index 172f8af1eea..901d6b0a349 100644 --- a/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/BaseTestCase.java +++ b/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/BaseTestCase.java @@ -122,7 +122,10 @@ public class BaseTestCase extends TestCase { } } }; - CCorePlugin.getDefault().getLog().addLogListener(logListener); + final CCorePlugin corePlugin = CCorePlugin.getDefault(); + if (corePlugin != null) { // if we don't run a JUnit Plugin Test + corePlugin.getLog().addLogListener(logListener); + } Throwable testThrowable= null; try { @@ -151,7 +154,9 @@ public class BaseTestCase extends TestCase { throw afe; } } finally { - CCorePlugin.getDefault().getLog().removeLogListener(logListener); + if (corePlugin != null) { + corePlugin.getLog().removeLogListener(logListener); + } } if(testThrowable!=null) diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/BaseScanner.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/BaseScanner.java index a8acf224b6a..205e4ef8d63 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/BaseScanner.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/BaseScanner.java @@ -1832,21 +1832,20 @@ abstract class BaseScanner implements IScanner { start = bufferPos[bufferStackPos] + 1; length = 0; boolean escaped = false; - while (++bufferPos[bufferStackPos] < limit) { - ++length; + for (length=0; ++bufferPos[bufferStackPos] < limit; length++) { c = buffer[bufferPos[bufferStackPos]]; if (c == '"') { - if (!escaped) + if (!escaped) { + filename = new String(buffer, start, length); break; + } } else if (c == '\\') { escaped = !escaped; continue; } escaped = false; } - --length; - filename = new String(buffer, start, length); nameOffset = start; nameEndOffset = start + length; endOffset = start + length + 1; @@ -1855,16 +1854,16 @@ abstract class BaseScanner implements IScanner { nameLine = getLineNumber(bufferPos[bufferStackPos]); local = false; start = bufferPos[bufferStackPos] + 1; - length = 0; - while (++bufferPos[bufferStackPos] < limit - && buffer[bufferPos[bufferStackPos]] != '>') - ++length; + for (length=0; ++bufferPos[bufferStackPos] < limit; length++) { + if (buffer[bufferPos[bufferStackPos]] == '>') { + filename= new String(buffer, start, length); + break; + } + } endOffset = start + length + 1; nameOffset = start; nameEndOffset = start + length; - - filename = new String(buffer, start, length); break; default: // handle macro expansions @@ -2260,8 +2259,13 @@ abstract class BaseScanner implements IScanner { int currarg = -1; while (bufferPos[bufferStackPos] < limit) { skipOverWhiteSpace(); - if (++bufferPos[bufferStackPos] >= limit) + if (++bufferPos[bufferStackPos] >= limit) { + if (reportProblems) { + handleProblem(IProblem.PREPROCESSOR_INVALID_MACRO_DEFN, + idstart, name); + } return null; + } c = buffer[bufferPos[bufferStackPos]]; int argstart = bufferPos[bufferStackPos]; if (c == ')') {