mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-08 18:26:01 +02:00
Scanner2 - lots of little things trying to properly scan windows/stdio/iostream.
This commit is contained in:
parent
e6e0527c96
commit
8a05f34b0b
3 changed files with 112 additions and 46 deletions
|
@ -1659,4 +1659,13 @@ public class Scanner2Test extends BaseScanner2Test
|
||||||
validateInteger("10");
|
validateInteger("10");
|
||||||
validateEOF();
|
validateEOF();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testWackyFunctionMacros() throws Exception {
|
||||||
|
initializeScanner(
|
||||||
|
"#define A(X) hi##X\n" +
|
||||||
|
"#define B(Y) A(Y)\n" +
|
||||||
|
"B(there)");
|
||||||
|
validateIdentifier("hithere");
|
||||||
|
validateEOF();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -199,16 +199,16 @@ public class ExpressionEvaluator {
|
||||||
switch (LA()) {
|
switch (LA()) {
|
||||||
case tPLUS:
|
case tPLUS:
|
||||||
consume();
|
consume();
|
||||||
return expression();
|
return unaryExpression();
|
||||||
case tMINUS:
|
case tMINUS:
|
||||||
consume();
|
consume();
|
||||||
return - expression();
|
return - unaryExpression();
|
||||||
case tNOT:
|
case tNOT:
|
||||||
consume();
|
consume();
|
||||||
return expression() == 0 ? 1 : 0;
|
return unaryExpression() == 0 ? 1 : 0;
|
||||||
case tCOMPL:
|
case tCOMPL:
|
||||||
consume();
|
consume();
|
||||||
return ~ expression();
|
return ~ unaryExpression();
|
||||||
case tNUMBER:
|
case tNUMBER:
|
||||||
return consume();
|
return consume();
|
||||||
case t_defined:
|
case t_defined:
|
||||||
|
@ -228,20 +228,26 @@ public class ExpressionEvaluator {
|
||||||
}
|
}
|
||||||
|
|
||||||
private long handleDefined() throws EvalException {
|
private long handleDefined() throws EvalException {
|
||||||
consume(); // the defined keyword
|
// We need to do some special handline to get the identifier without it being
|
||||||
|
|
||||||
if (LA() != tLPAREN)
|
|
||||||
throw new EvalException("missing ( after defined");
|
|
||||||
|
|
||||||
// Now we need to do some special handline to get the identifier without it being
|
|
||||||
// expanded by macro expansion
|
// expanded by macro expansion
|
||||||
skipWhiteSpace();
|
skipWhiteSpace();
|
||||||
|
|
||||||
char[] buffer = bufferStack[bufferStackPos];
|
char[] buffer = bufferStack[bufferStackPos];
|
||||||
int limit = bufferLimit[bufferStackPos];
|
int limit = bufferLimit[bufferStackPos];
|
||||||
|
if (++bufferPos[bufferStackPos] >= limit)
|
||||||
|
return 0;
|
||||||
|
|
||||||
// check first character
|
// check first character
|
||||||
char c = buffer[++bufferPos[bufferStackPos]];
|
char c = buffer[bufferPos[bufferStackPos]];
|
||||||
|
boolean inParens = false;
|
||||||
|
if (c == '(') {
|
||||||
|
inParens = true;
|
||||||
|
skipWhiteSpace();
|
||||||
|
if (++bufferPos[bufferStackPos] >= limit)
|
||||||
|
return 0;
|
||||||
|
c = buffer[bufferPos[bufferStackPos]];
|
||||||
|
}
|
||||||
|
|
||||||
if (!((c >= 'A' && c <= 'Z') || c == '_' || (c >= 'a' && c <= 'z'))) {
|
if (!((c >= 'A' && c <= 'Z') || c == '_' || (c >= 'a' && c <= 'z'))) {
|
||||||
throw new EvalException("illegal identifier in defined()");
|
throw new EvalException("illegal identifier in defined()");
|
||||||
}
|
}
|
||||||
|
@ -260,14 +266,16 @@ public class ExpressionEvaluator {
|
||||||
--bufferPos[bufferStackPos];
|
--bufferPos[bufferStackPos];
|
||||||
|
|
||||||
// consume to the closing paren;
|
// consume to the closing paren;
|
||||||
while (true) {
|
if (inParens) {
|
||||||
skipWhiteSpace();
|
skipWhiteSpace();
|
||||||
if (++bufferPos[bufferStackPos] >= limit)
|
if (++bufferPos[bufferStackPos] < limit
|
||||||
|
&& buffer[bufferPos[bufferStackPos]] != ')')
|
||||||
throw new EvalException("missing ) on defined");
|
throw new EvalException("missing ) on defined");
|
||||||
if (buffer[bufferPos[bufferStackPos]] == ')')
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set up the lookahead to whatever comes next
|
||||||
|
nextToken();
|
||||||
|
|
||||||
return definitions.get(buffer, idstart, idlen) != null ? 1 : 0;
|
return definitions.get(buffer, idstart, idlen) != null ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,8 +388,7 @@ public class ExpressionEvaluator {
|
||||||
|
|
||||||
// Check for defined(
|
// Check for defined(
|
||||||
pos = bufferPos[bufferStackPos];
|
pos = bufferPos[bufferStackPos];
|
||||||
if (pos + 1 < limit && buffer[pos + 1] == '('
|
if (CharArrayUtils.equals(buffer, start, len, _defined)) {
|
||||||
&& CharArrayUtils.equals(buffer, start, len, _defined)) {
|
|
||||||
tokenType = t_defined;
|
tokenType = t_defined;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -443,23 +450,34 @@ public class ExpressionEvaluator {
|
||||||
}
|
}
|
||||||
|
|
||||||
while (++bufferPos[bufferStackPos] < limit) {
|
while (++bufferPos[bufferStackPos] < limit) {
|
||||||
int c = buffer[bufferPos[bufferStackPos]];
|
char c = buffer[bufferPos[bufferStackPos]];
|
||||||
if (c >= '0' && c <= '9') {
|
if (c >= '0' && c <= '9') {
|
||||||
tokenValue *= (isHex ? 16 : 10);
|
tokenValue *= (isHex ? 16 : 10);
|
||||||
tokenValue += c - '0';
|
tokenValue += c - '0';
|
||||||
|
continue;
|
||||||
} else if (isHex) {
|
} else if (isHex) {
|
||||||
if (c >= 'a' && c <= 'f') {
|
if (c >= 'a' && c <= 'f') {
|
||||||
tokenValue *= 16;
|
tokenValue *= 16;
|
||||||
tokenValue += c - 'a';
|
tokenValue += c - 'a';
|
||||||
|
continue;
|
||||||
} else if (c >= 'A' && c <= 'F') {
|
} else if (c >= 'A' && c <= 'F') {
|
||||||
tokenValue *= 16;
|
tokenValue *= 16;
|
||||||
tokenValue += c - 'A';
|
tokenValue += c - 'A';
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// end of number
|
||||||
|
if (c == 'L') {
|
||||||
|
// eat the long
|
||||||
|
++bufferPos[bufferStackPos];
|
||||||
|
}
|
||||||
|
|
||||||
|
// done
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
--bufferPos[bufferStackPos];
|
--bufferPos[bufferStackPos];
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case '(':
|
case '(':
|
||||||
tokenType = tLPAREN;
|
tokenType = tLPAREN;
|
||||||
return;
|
return;
|
||||||
|
@ -501,10 +519,20 @@ public class ExpressionEvaluator {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case '&':
|
case '&':
|
||||||
|
if (pos + 1 < limit && buffer[pos + 1] == '&') {
|
||||||
|
++bufferPos[bufferStackPos];
|
||||||
|
tokenType = tAND;
|
||||||
|
return;
|
||||||
|
}
|
||||||
tokenType = tBITAND;
|
tokenType = tBITAND;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case '|':
|
case '|':
|
||||||
|
if (pos + 1 < limit && buffer[pos + 1] == '|') {
|
||||||
|
++bufferPos[bufferStackPos];
|
||||||
|
tokenType = tOR;
|
||||||
|
return;
|
||||||
|
}
|
||||||
tokenType = tBITOR;
|
tokenType = tBITOR;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -517,11 +545,11 @@ public class ExpressionEvaluator {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case '=':
|
case '=':
|
||||||
if (pos + 1 < limit)
|
if (pos + 1 < limit && buffer[pos + 1] == '=') {
|
||||||
if (buffer[pos + 1] == '=') {
|
++bufferPos[bufferStackPos];
|
||||||
tokenType = tEQUAL;
|
tokenType = tEQUAL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
throw new EvalException("assignment not allowed");
|
throw new EvalException("assignment not allowed");
|
||||||
|
|
||||||
case '<':
|
case '<':
|
||||||
|
@ -712,9 +740,10 @@ public class ExpressionEvaluator {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
continue;
|
break;
|
||||||
case '\\':
|
case '\\':
|
||||||
if (pos + 1 < limit && buffer[pos + 1] == '\n') {
|
if (pos + 1 < limit && buffer[pos + 1] == '\n') {
|
||||||
// \n is a whitespace
|
// \n is a whitespace
|
||||||
|
|
|
@ -628,11 +628,16 @@ public class Scanner2 implements IScanner, IScannerData {
|
||||||
--bufferPos[bufferStackPos];
|
--bufferPos[bufferStackPos];
|
||||||
|
|
||||||
// Check for macro expansion
|
// Check for macro expansion
|
||||||
|
|
||||||
|
// First look up the stack at the function style macro expansion args
|
||||||
Object expObject = null;
|
Object expObject = null;
|
||||||
if (bufferData[bufferStackPos] instanceof FunctionStyleMacro.Expansion) {
|
int tmpPos = bufferStackPos + 1;
|
||||||
// first check if name is a macro arg
|
while (--tmpPos >= 0
|
||||||
expObject = ((FunctionStyleMacro.Expansion)bufferData[bufferStackPos])
|
&& bufferData[tmpPos] instanceof FunctionStyleMacro.Expansion) {
|
||||||
|
expObject = ((FunctionStyleMacro.Expansion)bufferData[tmpPos])
|
||||||
.definitions.get(buffer, start, len);
|
.definitions.get(buffer, start, len);
|
||||||
|
if (expObject != null)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expObject == null) {
|
if (expObject == null) {
|
||||||
|
@ -964,8 +969,11 @@ public class Scanner2 implements IScanner, IScannerData {
|
||||||
start = bufferPos[bufferStackPos];
|
start = bufferPos[bufferStackPos];
|
||||||
skipToNewLine();
|
skipToNewLine();
|
||||||
len = bufferPos[bufferStackPos] - start;
|
len = bufferPos[bufferStackPos] - start;
|
||||||
if (expressionEvaluator.evaluate(buffer, start, len, definitions) == 0)
|
if (expressionEvaluator.evaluate(buffer, start, len, definitions) == 0) {
|
||||||
|
//System.out.println("#if <FALSE> " + new String(buffer,start+1,len-1));
|
||||||
skipOverConditionalCode(true);
|
skipOverConditionalCode(true);
|
||||||
|
} //else
|
||||||
|
//System.out.println("#if <TRUE> " + new String(buffer,start+1,len-1));
|
||||||
return;
|
return;
|
||||||
case ppElse:
|
case ppElse:
|
||||||
case ppElif:
|
case ppElif:
|
||||||
|
@ -1101,6 +1109,7 @@ public class Scanner2 implements IScanner, IScannerData {
|
||||||
--bufferPos[bufferStackPos];
|
--bufferPos[bufferStackPos];
|
||||||
char[] name = new char[idlen];
|
char[] name = new char[idlen];
|
||||||
System.arraycopy(buffer, idstart, name, 0, idlen);
|
System.arraycopy(buffer, idstart, name, 0, idlen);
|
||||||
|
//System.out.println("#define " + new String(buffer, idstart, idlen));
|
||||||
|
|
||||||
// Now check for function style macro to store the arguments
|
// Now check for function style macro to store the arguments
|
||||||
char[][] arglist = null;
|
char[][] arglist = null;
|
||||||
|
@ -1230,10 +1239,15 @@ public class Scanner2 implements IScanner, IScannerData {
|
||||||
|
|
||||||
skipToNewLine();
|
skipToNewLine();
|
||||||
|
|
||||||
if ((definitions.get(buffer, idstart, idlen) != null) == positive)
|
if ((definitions.get(buffer, idstart, idlen) != null) == positive) {
|
||||||
|
//System.out.println((positive ? "#ifdef" : "#ifndef")
|
||||||
|
// + " <TRUE> " + new String(buffer, idstart, idlen));
|
||||||
// continue on
|
// continue on
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//System.out.println((positive ? "#ifdef" : "#ifndef")
|
||||||
|
// + " <FALSE> " + new String(buffer, idstart, idlen));
|
||||||
// skip over this group
|
// skip over this group
|
||||||
skipOverConditionalCode(true);
|
skipOverConditionalCode(true);
|
||||||
}
|
}
|
||||||
|
@ -1273,6 +1287,7 @@ public class Scanner2 implements IScanner, IScannerData {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ppIfdef:
|
case ppIfdef:
|
||||||
case ppIfndef:
|
case ppIfndef:
|
||||||
|
case ppIf:
|
||||||
++nesting;
|
++nesting;
|
||||||
break;
|
break;
|
||||||
case ppElse:
|
case ppElse:
|
||||||
|
@ -1510,6 +1525,8 @@ public class Scanner2 implements IScanner, IScannerData {
|
||||||
char[] buffer = bufferStack[bufferStackPos];
|
char[] buffer = bufferStack[bufferStackPos];
|
||||||
int limit = bufferLimit[bufferStackPos];
|
int limit = bufferLimit[bufferStackPos];
|
||||||
|
|
||||||
|
skipOverWhiteSpace();
|
||||||
|
|
||||||
if (++bufferPos[bufferStackPos] >= limit
|
if (++bufferPos[bufferStackPos] >= limit
|
||||||
|| buffer[bufferPos[bufferStackPos]] != '(')
|
|| buffer[bufferPos[bufferStackPos]] != '(')
|
||||||
return;
|
return;
|
||||||
|
@ -1578,31 +1595,43 @@ public class Scanner2 implements IScanner, IScannerData {
|
||||||
pushContext(expText, exp);
|
pushContext(expText, exp);
|
||||||
}
|
}
|
||||||
|
|
||||||
// gcc built-ins
|
// standard built-ins
|
||||||
private static final ObjectStyleMacro __cplusplus
|
private static final ObjectStyleMacro __cplusplus
|
||||||
= new ObjectStyleMacro("__cplusplus".toCharArray(), "1".toCharArray());
|
= new ObjectStyleMacro("__cplusplus".toCharArray(), "1".toCharArray());
|
||||||
private static final ObjectStyleMacro __STDC_HOSTED__
|
private static final ObjectStyleMacro __STDC__
|
||||||
= new ObjectStyleMacro("__STDC_HOSTED__".toCharArray(), "0".toCharArray());
|
= new ObjectStyleMacro("__STDC__".toCharArray(), "1".toCharArray());
|
||||||
private static final ObjectStyleMacro __STDC_VERSION__
|
|
||||||
= new ObjectStyleMacro("__STDC_VERSION__".toCharArray(), "199001L".toCharArray());
|
// gcc built-ins
|
||||||
|
private static final ObjectStyleMacro __inline__
|
||||||
|
= new ObjectStyleMacro("__inline__".toCharArray(), "inline".toCharArray());
|
||||||
|
private static final ObjectStyleMacro __extension__
|
||||||
|
= new ObjectStyleMacro("__extension__".toCharArray(), emptyCharArray);
|
||||||
|
private static final ObjectStyleMacro __asm__
|
||||||
|
= new ObjectStyleMacro("__asm__".toCharArray(), "asm".toCharArray());
|
||||||
|
private static final ObjectStyleMacro __restrict__
|
||||||
|
= new ObjectStyleMacro("__restrict__".toCharArray(), "restrict".toCharArray());
|
||||||
|
private static final ObjectStyleMacro __restrict
|
||||||
|
= new ObjectStyleMacro("__restrict".toCharArray(), "restrict".toCharArray());
|
||||||
private static final FunctionStyleMacro __attribute__
|
private static final FunctionStyleMacro __attribute__
|
||||||
= new FunctionStyleMacro(
|
= new FunctionStyleMacro(
|
||||||
"__attribute__".toCharArray(),
|
"__attribute__".toCharArray(),
|
||||||
emptyCharArray,
|
emptyCharArray,
|
||||||
new char[][] { "arg".toCharArray() });
|
new char[][] { "arg".toCharArray() });
|
||||||
|
|
||||||
// standard built-ins
|
|
||||||
private static final ObjectStyleMacro __STDC__
|
|
||||||
= new ObjectStyleMacro("__STDC__".toCharArray(), "1".toCharArray());
|
|
||||||
|
|
||||||
protected void setupBuiltInMacros() {
|
protected void setupBuiltInMacros() {
|
||||||
|
|
||||||
// gcc extensions
|
definitions.put(__STDC__.name, __STDC__);
|
||||||
if( language == ParserLanguage.CPP )
|
if( language == ParserLanguage.CPP )
|
||||||
definitions.put(__cplusplus.name, __cplusplus);
|
definitions.put(__cplusplus.name, __cplusplus);
|
||||||
definitions.put(__STDC_HOSTED__.name, __STDC_HOSTED__);
|
|
||||||
definitions.put(__STDC_VERSION__.name, __STDC_VERSION__);
|
// gcc extensions
|
||||||
|
definitions.put(__inline__.name, __inline__);
|
||||||
|
definitions.put(__extension__.name, __extension__);
|
||||||
definitions.put(__attribute__.name, __attribute__);
|
definitions.put(__attribute__.name, __attribute__);
|
||||||
|
definitions.put(__restrict__.name, __restrict__);
|
||||||
|
definitions.put(__restrict.name, __restrict);
|
||||||
|
if( language == ParserLanguage.CPP )
|
||||||
|
definitions.put(__asm__.name, __asm__);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
|
@ -1639,7 +1668,6 @@ public class Scanner2 implements IScanner, IScannerData {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// standard extensions
|
// standard extensions
|
||||||
definitions.put(__STDC__.name, __STDC__);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if( getDefinition(__STDC__) == null )
|
if( getDefinition(__STDC__) == null )
|
||||||
|
|
Loading…
Add table
Reference in a new issue