1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-21 21:52:10 +02:00

Bug 338936 - Makefile parsers don't close the input streams

This commit is contained in:
Anton Leherbauer 2011-03-07 16:24:27 +00:00
parent 85a953ca4c
commit eb02ad7b69
6 changed files with 329 additions and 280 deletions

View file

@ -11,5 +11,6 @@
source.. = src/
output.. = bin/
bin.includes = .,\
META-INF/
META-INF/,\
data/
src.includes = about.html

View file

@ -0,0 +1,4 @@
VAR = foo
include Makefile.incl
main: $(VAR)
nothing

View file

@ -0,0 +1,2 @@
INCLVAR = bar
foo.o: .PHONY

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2008 Nokia and others.
* Copyright (c) 2008, 2011 Nokia 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
@ -7,20 +7,34 @@
*
* Contributors:
* Nokia (Ed Swartz) - initial API and implementation
* Wind River Systems - Bug 338936
*******************************************************************************/
package org.eclipse.cdt.make.core.tests;
import org.eclipse.cdt.make.core.MakeCorePlugin;
import org.eclipse.cdt.make.core.makefile.*;
import org.eclipse.core.filesystem.URIUtil;
import org.eclipse.core.runtime.*;
import java.io.*;
import java.net.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.eclipse.cdt.make.core.MakeCorePlugin;
import org.eclipse.cdt.make.core.makefile.IMacroDefinition;
import org.eclipse.cdt.make.core.makefile.IMakefile;
import org.eclipse.cdt.make.core.makefile.IMakefileReaderProvider;
import org.eclipse.cdt.make.core.makefile.IRule;
import org.eclipse.core.filesystem.URIUtil;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
public class MakefileReaderProviderTests extends TestCase {
private String[] inclDirs;
@ -91,7 +105,7 @@ public class MakefileReaderProviderTests extends TestCase {
public void testInMemoryReaderProvider() throws Exception {
IMakefile makefile = MakeCorePlugin.createMakefile(
URIUtil.toURI("Makefile.main"), true, inclDirs,
URIUtil.toURI("/memory/Makefile.main"), true, inclDirs,
new IMakefileReaderProvider() {
public Reader getReader(URI fileURI) throws IOException {
@ -119,6 +133,25 @@ public class MakefileReaderProviderTests extends TestCase {
assertMakefileContents(makefile);
}
public void testReaderIsClosed_Bug338936() throws Exception {
final boolean[] streamIsClosed = { false };
MakeCorePlugin.createMakefile(
URIUtil.toURI("Makefile.main"), true, inclDirs,
new IMakefileReaderProvider() {
public Reader getReader(URI fileURI) throws IOException {
return new StringReader("") {
@Override
public void close() {
super.close();
streamIsClosed[0] = true;
}
};
}
});
assertTrue("Stream is not closed", streamIsClosed[0]);
}
/**
* @param makefile
*/
@ -152,19 +185,18 @@ public class MakefileReaderProviderTests extends TestCase {
}
private URL getPluginRelativeURL(IPath path) throws Exception {
if (MakeTestsPlugin.getDefault() != null)
return FileLocator.find(
if (MakeTestsPlugin.getDefault() != null) {
URL url = FileLocator.find(
MakeTestsPlugin.getDefault().getBundle(),
path, null);
return url != null ? FileLocator.toFileURL(url) : null;
}
else {
return new URL("file", null, path.toFile().getAbsolutePath());
}
}
/**
* @return
*/
public static Test suite() {
return new MakefileReaderProviderTests();
return new TestSuite(MakefileReaderProviderTests.class);
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2010 QNX Software Systems and others.
* Copyright (c) 2000, 2011 QNX Software Systems 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
@ -7,6 +7,7 @@
*
* Contributors:
* QNX Software Systems - Initial API and implementation
* Wind River Systems - Bug 338936
*******************************************************************************/
package org.eclipse.cdt.make.internal.core.makefile.gnu;
@ -137,206 +138,210 @@ public class GNUMakefile extends AbstractMakefile implements IGNUMakefile {
setFileURI(fileURI);
while ((line = reader.readLine()) != null) {
startLine = endLine + 1;
endLine = reader.getLineNumber();
try {
while ((line = reader.readLine()) != null) {
startLine = endLine + 1;
endLine = reader.getLineNumber();
// Check if we enter in "define"
if (GNUMakefileUtil.isEndef(line)) {
// We should have a "define" for a "endef".
// Check if we enter in "define"
if (GNUMakefileUtil.isEndef(line)) {
// We should have a "define" for a "endef".
if (!defines.empty()) {
VariableDefinition def = defines.pop();
def.setEndLine(endLine);
}
Endef endef = new Endef(this);
endef.setLines(startLine, endLine);
addDirective(conditions, endef);
continue;
} else if (GNUMakefileUtil.isDefine(line)) {
VariableDefinition def = parseVariableDefinition(line);
def.setLines(startLine, endLine);
addDirective(conditions, def);
defines.push(def);
continue;
} else if (GNUMakefileUtil.isOverrideDefine(line)) {
VariableDefinition oDef = parseVariableDefinition(line);
oDef.setLines(startLine, endLine);
addDirective(conditions, oDef);
defines.push(oDef);
continue;
}
// We still in a define.
if (!defines.empty()) {
VariableDefinition def = defines.pop();
def.setEndLine(endLine);
}
Endef endef = new Endef(this);
endef.setLines(startLine, endLine);
addDirective(conditions, endef);
continue;
} else if (GNUMakefileUtil.isDefine(line)) {
VariableDefinition def = parseVariableDefinition(line);
def.setLines(startLine, endLine);
addDirective(conditions, def);
defines.push(def);
continue;
} else if (GNUMakefileUtil.isOverrideDefine(line)) {
VariableDefinition oDef = parseVariableDefinition(line);
oDef.setLines(startLine, endLine);
addDirective(conditions, oDef);
defines.push(oDef);
continue;
}
// We still in a define.
if (!defines.empty()) {
VariableDefinition def = defines.peek();
StringBuffer sb = def.getValue();
if (sb.length() > 0) {
sb.append('\n');
}
sb.append(line);
continue;
}
// 1- Try command first, since we can not strip '#' in command line
if (PosixMakefileUtil.isCommand(line)) {
Command cmd = new Command(this, line);
cmd.setLines(startLine, endLine);
if (!conditions.empty()) {
addDirective(conditions, cmd);
continue;
} else if (rules != null) {
// The command is added to the rules
for (Rule rule : rules) {
rule.addDirective(cmd);
rule.setEndLine(endLine);
VariableDefinition def = defines.peek();
StringBuffer sb = def.getValue();
if (sb.length() > 0) {
sb.append('\n');
}
sb.append(line);
continue;
}
// If we have no rules/condition for the command,
// give the other directives a chance by falling through
}
// 2- Strip away any comments.
int pound = Util.indexOfComment(line);
if (pound != -1) {
Comment cmt = new Comment(this, line.substring(pound + 1));
cmt.setLines(startLine, endLine);
if (rules != null) {
// The comment is added to the rules.
for (Rule rule : rules) {
rule.addDirective(cmt);
rule.setEndLine(endLine);
// 1- Try command first, since we can not strip '#' in command line
if (PosixMakefileUtil.isCommand(line)) {
Command cmd = new Command(this, line);
cmd.setLines(startLine, endLine);
if (!conditions.empty()) {
addDirective(conditions, cmd);
continue;
} else if (rules != null) {
// The command is added to the rules
for (Rule rule : rules) {
rule.addDirective(cmd);
rule.setEndLine(endLine);
}
continue;
}
} else {
addDirective(conditions, cmt);
// If we have no rules/condition for the command,
// give the other directives a chance by falling through
}
line = line.substring(0, pound);
// If all we have left are spaces continue
// 2- Strip away any comments.
int pound = Util.indexOfComment(line);
if (pound != -1) {
Comment cmt = new Comment(this, line.substring(pound + 1));
cmt.setLines(startLine, endLine);
if (rules != null) {
// The comment is added to the rules.
for (Rule rule : rules) {
rule.addDirective(cmt);
rule.setEndLine(endLine);
}
} else {
addDirective(conditions, cmt);
}
line = line.substring(0, pound);
// If all we have left are spaces continue
if (Util.isEmptyLine(line)) {
continue;
}
// The rest of the line maybe a valid directives.
// keep on trying by falling through.
}
// 3- Empty lines ?
if (Util.isEmptyLine(line)) {
Directive empty = new EmptyLine(this);
empty.setLines(startLine, endLine);
if (rules != null) {
// The EmptyLine is added to the rules.
for (Rule rule : rules) {
rule.addDirective(empty);
rule.setEndLine(endLine);
}
} else {
addDirective(conditions, empty);
}
continue;
}
// The rest of the line maybe a valid directives.
// keep on trying by falling through.
}
// 3- Empty lines ?
if (Util.isEmptyLine(line)) {
Directive empty = new EmptyLine(this);
empty.setLines(startLine, endLine);
if (rules != null) {
// The EmptyLine is added to the rules.
for (Rule rule : rules) {
rule.addDirective(empty);
rule.setEndLine(endLine);
// 4- reset the rules to null
// The first non empty line that does not begin with a <TAB> or '#'
// shall begin a new entry.
rules = null;
if (GNUMakefileUtil.isElse(line)) {
Conditional elseDirective = parseConditional(line);
elseDirective.setLines(startLine, endLine);
// Are we missing a if condition ?
if (!conditions.empty()) {
Conditional cond = (Conditional) conditions.pop();
cond.setEndLine(endLine - 1);
}
} else {
addDirective(conditions, empty);
addDirective(conditions, elseDirective);
conditions.push(elseDirective);
continue;
} else if (GNUMakefileUtil.isEndif(line)) {
Endif endif = new Endif(this);
endif.setLines(startLine, endLine);
// Are we missing a if/else condition ?
if (!conditions.empty()) {
Conditional cond = (Conditional) conditions.pop();
cond.setEndLine(endLine);
}
addDirective(conditions, endif);
continue;
}
continue;
}
// 4- reset the rules to null
// The first non empty line that does not begin with a <TAB> or '#'
// shall begin a new entry.
rules = null;
if (GNUMakefileUtil.isElse(line)) {
Conditional elseDirective = parseConditional(line);
elseDirective.setLines(startLine, endLine);
// Are we missing a if condition ?
if (!conditions.empty()) {
Conditional cond = (Conditional) conditions.pop();
cond.setEndLine(endLine - 1);
// 5- Check for the conditionnals.
Directive directive = processConditions(line);
if (directive != null) {
directive.setLines(startLine, endLine);
addDirective(conditions, directive);
conditions.push(directive);
continue;
}
addDirective(conditions, elseDirective);
conditions.push(elseDirective);
continue;
} else if (GNUMakefileUtil.isEndif(line)) {
Endif endif = new Endif(this);
endif.setLines(startLine, endLine);
// Are we missing a if/else condition ?
if (!conditions.empty()) {
Conditional cond = (Conditional) conditions.pop();
cond.setEndLine(endLine);
// 6- Check for other special gnu directives.
directive = processGNUDirectives(line);
if (directive != null) {
directive.setLines(startLine, endLine);
addDirective(conditions, directive);
continue;
}
addDirective(conditions, endif);
continue;
}
// 5- Check for the conditionnals.
Directive directive = processConditions(line);
if (directive != null) {
directive.setLines(startLine, endLine);
addDirective(conditions, directive);
conditions.push(directive);
continue;
}
// 6- Check for other special gnu directives.
directive = processGNUDirectives(line);
if (directive != null) {
directive.setLines(startLine, endLine);
addDirective(conditions, directive);
continue;
}
// 7- Check for GNU special rules.
SpecialRule special = processSpecialRules(line);
if (special != null) {
rules = new Rule[] { special };
special.setLines(startLine, endLine);
addDirective(conditions, special);
continue;
}
// - Check for inference rule.
if (PosixMakefileUtil.isInferenceRule(line)) {
InferenceRule irule = parseInferenceRule(line);
irule.setLines(startLine, endLine);
addDirective(conditions, irule);
rules = new Rule[] { irule };
continue;
}
// - Variable Definiton ?
if (GNUMakefileUtil.isVariableDefinition(line)) {
VariableDefinition vd = parseVariableDefinition(line);
vd.setLines(startLine, endLine);
addDirective(conditions, vd);
if (!vd.isTargetSpecific()) {
continue;
// 7- Check for GNU special rules.
SpecialRule special = processSpecialRules(line);
if (special != null) {
rules = new Rule[] { special };
special.setLines(startLine, endLine);
addDirective(conditions, special);
continue;
}
}
// - GNU Static Target rule ?
if (GNUMakefileUtil.isStaticTargetRule(line)) {
StaticTargetRule[] srules = parseStaticTargetRule(line);
for (StaticTargetRule srule : srules) {
srule.setLines(startLine, endLine);
addDirective(conditions, srule);
// - Check for inference rule.
if (PosixMakefileUtil.isInferenceRule(line)) {
InferenceRule irule = parseInferenceRule(line);
irule.setLines(startLine, endLine);
addDirective(conditions, irule);
rules = new Rule[] { irule };
continue;
}
rules = srules;
continue;
}
// - Target Rule ?
if (GNUMakefileUtil.isGNUTargetRule(line)) {
TargetRule[] trules = parseGNUTargetRules(line);
for (TargetRule trule : trules) {
trule.setLines(startLine, endLine);
addDirective(conditions, trule);
// - Variable Definiton ?
if (GNUMakefileUtil.isVariableDefinition(line)) {
VariableDefinition vd = parseVariableDefinition(line);
vd.setLines(startLine, endLine);
addDirective(conditions, vd);
if (!vd.isTargetSpecific()) {
continue;
}
}
rules = trules;
continue;
// - GNU Static Target rule ?
if (GNUMakefileUtil.isStaticTargetRule(line)) {
StaticTargetRule[] srules = parseStaticTargetRule(line);
for (StaticTargetRule srule : srules) {
srule.setLines(startLine, endLine);
addDirective(conditions, srule);
}
rules = srules;
continue;
}
// - Target Rule ?
if (GNUMakefileUtil.isGNUTargetRule(line)) {
TargetRule[] trules = parseGNUTargetRules(line);
for (TargetRule trule : trules) {
trule.setLines(startLine, endLine);
addDirective(conditions, trule);
}
rules = trules;
continue;
}
// XXX ?? Should not be here.
BadDirective stmt = new BadDirective(this, line);
stmt.setLines(startLine, endLine);
addDirective(conditions, stmt);
}
// XXX ?? Should not be here.
BadDirective stmt = new BadDirective(this, line);
stmt.setLines(startLine, endLine);
addDirective(conditions, stmt);
setLines(1, endLine);
} finally {
reader.close();
}
setLines(1, endLine);
// TEST please remove.
//GNUMakefileValidator validator = new GNUMakefileValidator();
//validator.validateDirectives(null, getDirectives());

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2010 QNX Software Systems and others.
* Copyright (c) 2000, 2011 QNX Software Systems 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
@ -7,6 +7,7 @@
*
* Contributors:
* QNX Software Systems - Initial API and implementation
* Wind River Systems - Bug 338936
*******************************************************************************/
package org.eclipse.cdt.make.internal.core.makefile.posix;
@ -117,111 +118,115 @@ public class PosixMakefile extends AbstractMakefile {
setFileURI(fileURI);
while ((line = reader.readLine()) != null) {
startLine = endLine + 1;
endLine = reader.getLineNumber();
try {
while ((line = reader.readLine()) != null) {
startLine = endLine + 1;
endLine = reader.getLineNumber();
// 1- Try command first, since we can not strip '#' in command line
if (PosixMakefileUtil.isCommand(line)) {
Command cmd = new Command(this, line);
cmd.setLines(startLine, endLine);
// The command is added to the rules
if (rules != null) {
for (int i = 0; i < rules.length; i++) {
rules[i].addDirective(cmd);
rules[i].setEndLine(endLine);
// 1- Try command first, since we can not strip '#' in command line
if (PosixMakefileUtil.isCommand(line)) {
Command cmd = new Command(this, line);
cmd.setLines(startLine, endLine);
// The command is added to the rules
if (rules != null) {
for (int i = 0; i < rules.length; i++) {
rules[i].addDirective(cmd);
rules[i].setEndLine(endLine);
}
continue;
}
continue;
// If we have no rules for the command,
// give the other directives a chance by falling through
}
// If we have no rules for the command,
// give the other directives a chance by falling through
}
// 2- Strip away any comments.
int pound = Util.indexOfComment(line);
if (pound != -1) {
Comment cmt = new Comment(this, line.substring(pound + 1));
cmt.setLines(startLine, endLine);
if (rules != null) {
for (int i = 0; i < rules.length; i++) {
rules[i].addDirective(cmt);
rules[i].setEndLine(endLine);
// 2- Strip away any comments.
int pound = Util.indexOfComment(line);
if (pound != -1) {
Comment cmt = new Comment(this, line.substring(pound + 1));
cmt.setLines(startLine, endLine);
if (rules != null) {
for (int i = 0; i < rules.length; i++) {
rules[i].addDirective(cmt);
rules[i].setEndLine(endLine);
}
} else {
addDirective(cmt);
}
} else {
addDirective(cmt);
line = line.substring(0, pound);
// If all we have left are spaces continue
if (Util.isEmptyLine(line)) {
continue;
}
// The rest of the line maybe a valid directive.
// keep on trying by falling through.
}
line = line.substring(0, pound);
// If all we have left are spaces continue
// 3- Empty lines ?
if (Util.isEmptyLine(line)) {
Directive empty = new EmptyLine(this);
empty.setLines(startLine, endLine);
if (rules != null) {
for (int i = 0; i < rules.length; i++) {
rules[i].addDirective(empty);
rules[i].setEndLine(endLine);
}
} else {
addDirective(empty);
}
continue;
}
// The rest of the line maybe a valid directive.
// keep on trying by falling through.
}
// 3- Empty lines ?
if (Util.isEmptyLine(line)) {
Directive empty = new EmptyLine(this);
empty.setLines(startLine, endLine);
if (rules != null) {
for (int i = 0; i < rules.length; i++) {
rules[i].addDirective(empty);
rules[i].setEndLine(endLine);
}
} else {
addDirective(empty);
// 4- reset the rules to null
// The first non empty line that does not begin with a <TAB> or '#'
// shall begin a new entry.
rules = null;
// 5- Check for the special rules.
SpecialRule special = processSpecialRule(line);
if (special != null) {
rules = new Rule[] { special };
special.setLines(startLine, endLine);
addDirective(special);
continue;
}
continue;
}
// 4- reset the rules to null
// The first non empty line that does not begin with a <TAB> or '#'
// shall begin a new entry.
rules = null;
// 6- Check for inference rule.
if (PosixMakefileUtil.isInferenceRule(line)) {
InferenceRule irule = parseInferenceRule(line);
irule.setLines(startLine, endLine);
addDirective(irule);
rules = new Rule[]{irule};
continue;
}
// 5- Check for the special rules.
SpecialRule special = processSpecialRule(line);
if (special != null) {
rules = new Rule[] { special };
special.setLines(startLine, endLine);
addDirective(special);
continue;
}
// 7- Macro Definiton ?
if (PosixMakefileUtil.isMacroDefinition(line)) {
Directive stmt = parseMacroDefinition(line);
stmt.setLines(startLine, endLine);
addDirective(stmt);
continue;
}
// 6- Check for inference rule.
if (PosixMakefileUtil.isInferenceRule(line)) {
InferenceRule irule = parseInferenceRule(line);
irule.setLines(startLine, endLine);
addDirective(irule);
rules = new Rule[]{irule};
continue;
}
// 8- Target Rule ?
if (PosixMakefileUtil.isTargetRule(line)) {
TargetRule[] trules = parseTargetRule(line);
for (int i = 0; i < trules.length; i++) {
trules[i].setLines(startLine, endLine);
addDirective(trules[i]);
}
rules = trules;
continue;
}
// 7- Macro Definiton ?
if (PosixMakefileUtil.isMacroDefinition(line)) {
Directive stmt = parseMacroDefinition(line);
// XXX ?? Should not be here.
BadDirective stmt = new BadDirective(this, line);
stmt.setLines(startLine, endLine);
addDirective(stmt);
continue;
}
// 8- Target Rule ?
if (PosixMakefileUtil.isTargetRule(line)) {
TargetRule[] trules = parseTargetRule(line);
for (int i = 0; i < trules.length; i++) {
trules[i].setLines(startLine, endLine);
addDirective(trules[i]);
}
rules = trules;
continue;
}
// XXX ?? Should not be here.
BadDirective stmt = new BadDirective(this, line);
stmt.setLines(startLine, endLine);
addDirective(stmt);
setLines(1, endLine);
} finally {
reader.close();
}
setLines(1, endLine);
}
/* (non-Javadoc)