1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-22 06:02:11 +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/ source.. = src/
output.. = bin/ output.. = bin/
bin.includes = .,\ bin.includes = .,\
META-INF/ META-INF/,\
data/
src.includes = about.html 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 * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -7,20 +7,34 @@
* *
* Contributors: * Contributors:
* Nokia (Ed Swartz) - initial API and implementation * Nokia (Ed Swartz) - initial API and implementation
* Wind River Systems - Bug 338936
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.make.core.tests; package org.eclipse.cdt.make.core.tests;
import org.eclipse.cdt.make.core.MakeCorePlugin; import java.io.File;
import org.eclipse.cdt.make.core.makefile.*; import java.io.FileNotFoundException;
import org.eclipse.core.filesystem.URIUtil; import java.io.IOException;
import org.eclipse.core.runtime.*; import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.*; import java.io.Reader;
import java.net.*; import java.io.StringReader;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import junit.framework.Test; import junit.framework.Test;
import junit.framework.TestCase; 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 { public class MakefileReaderProviderTests extends TestCase {
private String[] inclDirs; private String[] inclDirs;
@ -91,7 +105,7 @@ public class MakefileReaderProviderTests extends TestCase {
public void testInMemoryReaderProvider() throws Exception { public void testInMemoryReaderProvider() throws Exception {
IMakefile makefile = MakeCorePlugin.createMakefile( IMakefile makefile = MakeCorePlugin.createMakefile(
URIUtil.toURI("Makefile.main"), true, inclDirs, URIUtil.toURI("/memory/Makefile.main"), true, inclDirs,
new IMakefileReaderProvider() { new IMakefileReaderProvider() {
public Reader getReader(URI fileURI) throws IOException { public Reader getReader(URI fileURI) throws IOException {
@ -119,6 +133,25 @@ public class MakefileReaderProviderTests extends TestCase {
assertMakefileContents(makefile); 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 * @param makefile
*/ */
@ -152,19 +185,18 @@ public class MakefileReaderProviderTests extends TestCase {
} }
private URL getPluginRelativeURL(IPath path) throws Exception { private URL getPluginRelativeURL(IPath path) throws Exception {
if (MakeTestsPlugin.getDefault() != null) if (MakeTestsPlugin.getDefault() != null) {
return FileLocator.find( URL url = FileLocator.find(
MakeTestsPlugin.getDefault().getBundle(), MakeTestsPlugin.getDefault().getBundle(),
path, null); path, null);
return url != null ? FileLocator.toFileURL(url) : null;
}
else { else {
return new URL("file", null, path.toFile().getAbsolutePath()); return new URL("file", null, path.toFile().getAbsolutePath());
} }
} }
/**
* @return
*/
public static Test suite() { 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 * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -7,6 +7,7 @@
* *
* Contributors: * Contributors:
* QNX Software Systems - Initial API and implementation * QNX Software Systems - Initial API and implementation
* Wind River Systems - Bug 338936
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.make.internal.core.makefile.gnu; package org.eclipse.cdt.make.internal.core.makefile.gnu;
@ -137,206 +138,210 @@ public class GNUMakefile extends AbstractMakefile implements IGNUMakefile {
setFileURI(fileURI); setFileURI(fileURI);
while ((line = reader.readLine()) != null) { try {
startLine = endLine + 1; while ((line = reader.readLine()) != null) {
endLine = reader.getLineNumber(); startLine = endLine + 1;
endLine = reader.getLineNumber();
// Check if we enter in "define" // Check if we enter in "define"
if (GNUMakefileUtil.isEndef(line)) { if (GNUMakefileUtil.isEndef(line)) {
// We should have a "define" for a "endef". // 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()) { if (!defines.empty()) {
VariableDefinition def = defines.pop(); VariableDefinition def = defines.peek();
def.setEndLine(endLine); StringBuffer sb = def.getValue();
} if (sb.length() > 0) {
Endef endef = new Endef(this); sb.append('\n');
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);
} }
sb.append(line);
continue; continue;
} }
// If we have no rules/condition for the command,
// give the other directives a chance by falling through
}
// 2- Strip away any comments. // 1- Try command first, since we can not strip '#' in command line
int pound = Util.indexOfComment(line); if (PosixMakefileUtil.isCommand(line)) {
if (pound != -1) { Command cmd = new Command(this, line);
Comment cmt = new Comment(this, line.substring(pound + 1)); cmd.setLines(startLine, endLine);
cmt.setLines(startLine, endLine); if (!conditions.empty()) {
if (rules != null) { addDirective(conditions, cmd);
// The comment is added to the rules. continue;
for (Rule rule : rules) { } else if (rules != null) {
rule.addDirective(cmt); // The command is added to the rules
rule.setEndLine(endLine); for (Rule rule : rules) {
rule.addDirective(cmd);
rule.setEndLine(endLine);
}
continue;
} }
} else { // If we have no rules/condition for the command,
addDirective(conditions, cmt); // 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)) { 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; continue;
} }
// The rest of the line maybe a valid directives.
// keep on trying by falling through.
}
// 3- Empty lines ? // 4- reset the rules to null
if (Util.isEmptyLine(line)) { // The first non empty line that does not begin with a <TAB> or '#'
Directive empty = new EmptyLine(this); // shall begin a new entry.
empty.setLines(startLine, endLine); rules = null;
if (rules != null) {
// The EmptyLine is added to the rules. if (GNUMakefileUtil.isElse(line)) {
for (Rule rule : rules) { Conditional elseDirective = parseConditional(line);
rule.addDirective(empty); elseDirective.setLines(startLine, endLine);
rule.setEndLine(endLine); // Are we missing a if condition ?
if (!conditions.empty()) {
Conditional cond = (Conditional) conditions.pop();
cond.setEndLine(endLine - 1);
} }
} else { addDirective(conditions, elseDirective);
addDirective(conditions, empty); 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 // 5- Check for the conditionnals.
// The first non empty line that does not begin with a <TAB> or '#' Directive directive = processConditions(line);
// shall begin a new entry. if (directive != null) {
rules = null; directive.setLines(startLine, endLine);
addDirective(conditions, directive);
if (GNUMakefileUtil.isElse(line)) { conditions.push(directive);
Conditional elseDirective = parseConditional(line); continue;
elseDirective.setLines(startLine, endLine);
// Are we missing a if condition ?
if (!conditions.empty()) {
Conditional cond = (Conditional) conditions.pop();
cond.setEndLine(endLine - 1);
} }
addDirective(conditions, elseDirective);
conditions.push(elseDirective); // 6- Check for other special gnu directives.
continue; directive = processGNUDirectives(line);
} else if (GNUMakefileUtil.isEndif(line)) { if (directive != null) {
Endif endif = new Endif(this); directive.setLines(startLine, endLine);
endif.setLines(startLine, endLine); addDirective(conditions, directive);
// Are we missing a if/else condition ? continue;
if (!conditions.empty()) {
Conditional cond = (Conditional) conditions.pop();
cond.setEndLine(endLine);
} }
addDirective(conditions, endif);
continue;
}
// 5- Check for the conditionnals. // 7- Check for GNU special rules.
Directive directive = processConditions(line); SpecialRule special = processSpecialRules(line);
if (directive != null) { if (special != null) {
directive.setLines(startLine, endLine); rules = new Rule[] { special };
addDirective(conditions, directive); special.setLines(startLine, endLine);
conditions.push(directive); addDirective(conditions, special);
continue; 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;
} }
}
// - GNU Static Target rule ? // - Check for inference rule.
if (GNUMakefileUtil.isStaticTargetRule(line)) { if (PosixMakefileUtil.isInferenceRule(line)) {
StaticTargetRule[] srules = parseStaticTargetRule(line); InferenceRule irule = parseInferenceRule(line);
for (StaticTargetRule srule : srules) { irule.setLines(startLine, endLine);
srule.setLines(startLine, endLine); addDirective(conditions, irule);
addDirective(conditions, srule); rules = new Rule[] { irule };
continue;
} }
rules = srules;
continue;
}
// - Target Rule ? // - Variable Definiton ?
if (GNUMakefileUtil.isGNUTargetRule(line)) { if (GNUMakefileUtil.isVariableDefinition(line)) {
TargetRule[] trules = parseGNUTargetRules(line); VariableDefinition vd = parseVariableDefinition(line);
for (TargetRule trule : trules) { vd.setLines(startLine, endLine);
trule.setLines(startLine, endLine); addDirective(conditions, vd);
addDirective(conditions, trule); 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);
} }
setLines(1, endLine);
// XXX ?? Should not be here. } finally {
BadDirective stmt = new BadDirective(this, line); reader.close();
stmt.setLines(startLine, endLine);
addDirective(conditions, stmt);
} }
setLines(1, endLine);
// TEST please remove. // TEST please remove.
//GNUMakefileValidator validator = new GNUMakefileValidator(); //GNUMakefileValidator validator = new GNUMakefileValidator();
//validator.validateDirectives(null, getDirectives()); //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 * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -7,6 +7,7 @@
* *
* Contributors: * Contributors:
* QNX Software Systems - Initial API and implementation * QNX Software Systems - Initial API and implementation
* Wind River Systems - Bug 338936
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.make.internal.core.makefile.posix; package org.eclipse.cdt.make.internal.core.makefile.posix;
@ -117,111 +118,115 @@ public class PosixMakefile extends AbstractMakefile {
setFileURI(fileURI); setFileURI(fileURI);
while ((line = reader.readLine()) != null) { try {
startLine = endLine + 1; while ((line = reader.readLine()) != null) {
endLine = reader.getLineNumber(); startLine = endLine + 1;
endLine = reader.getLineNumber();
// 1- Try command first, since we can not strip '#' in command line // 1- Try command first, since we can not strip '#' in command line
if (PosixMakefileUtil.isCommand(line)) { if (PosixMakefileUtil.isCommand(line)) {
Command cmd = new Command(this, line); Command cmd = new Command(this, line);
cmd.setLines(startLine, endLine); cmd.setLines(startLine, endLine);
// The command is added to the rules // The command is added to the rules
if (rules != null) { if (rules != null) {
for (int i = 0; i < rules.length; i++) { for (int i = 0; i < rules.length; i++) {
rules[i].addDirective(cmd); rules[i].addDirective(cmd);
rules[i].setEndLine(endLine); 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. // 2- Strip away any comments.
int pound = Util.indexOfComment(line); int pound = Util.indexOfComment(line);
if (pound != -1) { if (pound != -1) {
Comment cmt = new Comment(this, line.substring(pound + 1)); Comment cmt = new Comment(this, line.substring(pound + 1));
cmt.setLines(startLine, endLine); cmt.setLines(startLine, endLine);
if (rules != null) { if (rules != null) {
for (int i = 0; i < rules.length; i++) { for (int i = 0; i < rules.length; i++) {
rules[i].addDirective(cmt); rules[i].addDirective(cmt);
rules[i].setEndLine(endLine); rules[i].setEndLine(endLine);
}
} else {
addDirective(cmt);
} }
} else { line = line.substring(0, pound);
addDirective(cmt); // 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)) { 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; continue;
} }
// The rest of the line maybe a valid directive.
// keep on trying by falling through.
}
// 3- Empty lines ? // 4- reset the rules to null
if (Util.isEmptyLine(line)) { // The first non empty line that does not begin with a <TAB> or '#'
Directive empty = new EmptyLine(this); // shall begin a new entry.
empty.setLines(startLine, endLine); rules = null;
if (rules != null) {
for (int i = 0; i < rules.length; i++) { // 5- Check for the special rules.
rules[i].addDirective(empty); SpecialRule special = processSpecialRule(line);
rules[i].setEndLine(endLine); if (special != null) {
} rules = new Rule[] { special };
} else { special.setLines(startLine, endLine);
addDirective(empty); addDirective(special);
continue;
} }
continue;
}
// 4- reset the rules to null // 6- Check for inference rule.
// The first non empty line that does not begin with a <TAB> or '#' if (PosixMakefileUtil.isInferenceRule(line)) {
// shall begin a new entry. InferenceRule irule = parseInferenceRule(line);
rules = null; irule.setLines(startLine, endLine);
addDirective(irule);
rules = new Rule[]{irule};
continue;
}
// 5- Check for the special rules. // 7- Macro Definiton ?
SpecialRule special = processSpecialRule(line); if (PosixMakefileUtil.isMacroDefinition(line)) {
if (special != null) { Directive stmt = parseMacroDefinition(line);
rules = new Rule[] { special }; stmt.setLines(startLine, endLine);
special.setLines(startLine, endLine); addDirective(stmt);
addDirective(special); continue;
continue; }
}
// 6- Check for inference rule. // 8- Target Rule ?
if (PosixMakefileUtil.isInferenceRule(line)) { if (PosixMakefileUtil.isTargetRule(line)) {
InferenceRule irule = parseInferenceRule(line); TargetRule[] trules = parseTargetRule(line);
irule.setLines(startLine, endLine); for (int i = 0; i < trules.length; i++) {
addDirective(irule); trules[i].setLines(startLine, endLine);
rules = new Rule[]{irule}; addDirective(trules[i]);
continue; }
} rules = trules;
continue;
}
// 7- Macro Definiton ? // XXX ?? Should not be here.
if (PosixMakefileUtil.isMacroDefinition(line)) { BadDirective stmt = new BadDirective(this, line);
Directive stmt = parseMacroDefinition(line);
stmt.setLines(startLine, endLine); stmt.setLines(startLine, endLine);
addDirective(stmt); addDirective(stmt);
continue;
} }
setLines(1, endLine);
// 8- Target Rule ? } finally {
if (PosixMakefileUtil.isTargetRule(line)) { reader.close();
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);
} }
/* (non-Javadoc) /* (non-Javadoc)