Browse Source

Make <jjtree>'s outputdirectory and outputfile attributes work as

expected (i.e. consistent with the command line of jjtree).

PR: 21526
Submitted by:	Jene Jasper <jjasper at abz dot nl>


git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@275090 13f79535-47bb-0310-9956-ffa450edef68
master
Stefan Bodewig 22 years ago
parent
commit
58968aaa63
2 changed files with 439 additions and 10 deletions
  1. +346
    -0
      docs/manual/OptionalTasks/jjtree.html
  2. +93
    -10
      src/main/org/apache/tools/ant/taskdefs/optional/javacc/JJTree.java

+ 346
- 0
docs/manual/OptionalTasks/jjtree.html View File

@@ -186,10 +186,356 @@ Example</h3>
This invokes JJTree on grammar file src/Parser.jjt, writing the generated
grammar file, Parser.jj, file to build/src. The grammar option NODE_USES_PARSER
is set to true when invoking JJTree.
<br>

<h3>Comparison output locations between command line JJTree and different Ant taskdef versions</h3>

<table cellpadding="3" border="1">
<tr>
<td><b>Command Line JJTree options</b>
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<i>and Generated Files</i> (working directory: <code>/tmp</code>)</td>
<td><b>Ant 1.5.3</b> versus command line</td>
<td><b>Ant 1.6</b> versus command line</td>
</tr>
<tr>
<td><pre><b>jjtree grammar.jjt</b>
/tmp/grammar.jj
/tmp/&lt;generated&gt;.java</pre>
</td>
<td>Same</td>
<td>Same</td>
</tr>
<tr>
<td><pre><b>jjtree relative/grammar.jjt</b>
/tmp/grammar.jj
/tmp/&lt;generated&gt;.java</pre>
</td>
<td><pre>
/tmp/relative/grammar.jj
/tmp/relative/&lt;generated&gt;.java</pre>
</td>
<td>Same</td>
</tr>
<tr>
<td><pre><b>jjtree /tmp/absolute/grammar.jjt</b>
/tmp/grammar.jj
/tmp/&lt;generated&gt;.java</pre>
</td>
<td><pre>
/tmp/absolute/grammar.jj
/tmp/absolute/&lt;generated&gt;.java</pre>
</td>
<td>Same</td>
</tr>
<tr>
<td><pre><b>jjtree -OUTPUT_DIRECTORY:relative grammar.jjt</b>
/tmp/relative/grammar.jj
/tmp/relative/&lt;generated&gt;.java</pre>
</td>
<td>Same</td>
<td>Same</td>
</tr>
<tr>
<td><pre><b>jjtree -OUTPUT_DIRECTORY:relative relative/grammar.jjt</b>
/tmp/relative/grammar.jj
/tmp/relative/&lt;generated&gt;.java</pre>
</td>
<td>Same</td>
<td>Same</td>
</tr>
<tr>
<td><pre><b>jjtree -OUTPUT_DIRECTORY:relative /tmp/absolute/grammar.jjt</b>
/tmp/relative/grammar.jj
/tmp/relative/&lt;generated&gt;.java</pre>
</td>
<td>Same</td>
<td>Same</td>
</tr>
<tr>
<td><pre><b>jjtree -OUTPUT_DIRECTORY:/tmp/absolute/ grammar.jjt</b>
/tmp/absolute/grammar.jj
/tmp/absolute/&lt;generated&gt;.java</pre>
</td>
<td>Same</td>
<td>Same</td>
</tr>
<tr>
<td><pre><b>jjtree -OUTPUT_DIRECTORY:/tmp/absolute/ relative/grammar.jjt</b>
/tmp/absolute/grammar.jj
/tmp/absolute/&lt;generated&gt;.java</pre>
</td>
<td>Same</td>
<td>Same</td>
</tr>
<tr>
<td><pre><b>jjtree -OUTPUT_DIRECTORY:/tmp/absolute/ /tmp/absolute/grammar.jjt</b>
/tmp/absolute/grammar.jj
/tmp/absolute/&lt;generated&gt;.java</pre>
</td>
<td>Same</td>
<td>Same</td>
</tr>
<tr>
<td><pre><b>jjtree -OUTPUT_FILE:output.jj grammar.jjt</b>
/tmp/output.jj
/tmp/&lt;generated&gt;.java</pre>
</td>
<td>Not Supported</td>
<td>Same</td>
</tr>
<tr>
<td><pre><b>jjtree -OUTPUT_FILE:output.jj relative/grammar.jjt</b>
/tmp/output.jj
/tmp/&lt;generated&gt;.java</pre>
</td>
<td>Not Supported</td>
<td>Same</td>
</tr>
<tr>
<td><pre><b>jjtree -OUTPUT_FILE:output.jj /tmp/absolute/grammar.jjt</b>
/tmp/output.jj
/tmp/&lt;generated&gt;.java</pre>
</td>
<td>Not Supported</td>
<td>Same</td>
</tr>
<tr>
<td><pre><b>jjtree -OUTPUT_FILE:output.jj -OUTPUT_DIRECTORY:relative grammar.jjt</b>
/tmp/relative/output.jj
/tmp/relative/&lt;generated&gt;.java</pre>
</td>
<td>Not Supported</td>
<td>Same</td>
</tr>
<tr>
<td><pre><b>jjtree -OUTPUT_FILE:output.jj -OUTPUT_DIRECTORY:relative relative/grammar.jjt</b>
/tmp/relative/output.jj
/tmp/relative/&lt;generated&gt;.java</pre>
</td>
<td>Not Supported</td>
<td>Same</td>
</tr>
<tr>
<td><pre><b>jjtree -OUTPUT_FILE:output.jj -OUTPUT_DIRECTORY:relative /tmp/absolute/grammar.jjt</b>
/tmp/relative/output.jj
/tmp/relative/&lt;generated&gt;.java</pre>
</td>
<td>Not Supported</td>
<td>Same</td>
</tr>
<tr>
<td><pre><b>jjtree -OUTPUT_FILE:output.jj -OUTPUT_DIRECTORY:/tmp/absolute/ grammar.jjt</b>
/tmp/absolute/output.jj
/tmp/absolute/&lt;generated&gt;.java</pre>
</td>
<td>Not Supported</td>
<td>Same</td>
</tr>
<tr>
<td><pre><b>jjtree -OUTPUT_FILE:output.jj -OUTPUT_DIRECTORY:/tmp/absolute/ relative/grammar.jjt</b>
/tmp/absolute/output.jj
/tmp/absolute/&lt;generated&gt;.java</pre>
</td>
<td>Not Supported</td>
<td>Same</td>
</tr>
<tr>
<td><pre><b>jjtree -OUTPUT_FILE:output.jj -OUTPUT_DIRECTORY:/tmp/absolute/ /tmp/absolute/grammar.jjt</b>
/tmp/absolute/output.jj
/tmp/absolute/&lt;generated&gt;.java</pre>
</td>
<td>Not Supported</td>
<td>Same</td>
</tr>
<tr>
<td><pre><b>jjtree -OUTPUT_FILE:subdir/output.jj grammar.jjt</b>
/tmp/subdir/output.jj
/tmp/&lt;generated&gt;.java</pre>
</td>
<td>Not Supported</td>
<td>Same</td>
</tr>
<tr>
<td><pre><b>jjtree -OUTPUT_FILE:subdir/output.jj relative/grammar.jjt</b>
/tmp/subdir/output.jj
/tmp/&lt;generated&gt;.java</pre>
</td>
<td>Not Supported</td>
<td>Same</td>
</tr>
<tr>
<td><pre><b>jjtree -OUTPUT_FILE:subdir/output.jj /tmp/absolute/grammar.jjt</b>
/tmp/subdir/output.jj
/tmp/&lt;generated&gt;.java</pre>
</td>
<td>Not Supported</td>
<td>Same</td>
</tr>
<tr>
<td><pre><b>jjtree -OUTPUT_FILE:subdir/output.jj -OUTPUT_DIRECTORY:relative grammar.jjt</b>
/tmp/relative/subdir/output.jj
/tmp/relative/&lt;generated&gt;.java</pre>
</td>
<td>Not Supported</td>
<td>Same</td>
</tr>
<tr>
<td><pre><b>jjtree -OUTPUT_FILE:subdir/output.jj -OUTPUT_DIRECTORY:relative relative/grammar.jjt</b>
/tmp/relative/subdir/output.jj
/tmp/relative/&lt;generated&gt;.java</pre>
</td>
<td>Not Supported</td>
<td>Same</td>
</tr>
<tr>
<td><pre><b>jjtree -OUTPUT_FILE:subdir/output.jj -OUTPUT_DIRECTORY:relative /tmp/absolute/grammar.jjt</b>
/tmp/relative/subdir/output.jj
/tmp/relative/&lt;generated&gt;.java</pre>
</td>
<td>Not Supported</td>
<td>Same</td>
</tr>
<tr>
<td><pre><b>jjtree -OUTPUT_FILE:subdir/output.jj -OUTPUT_DIRECTORY:/tmp/absolute/ grammar.jjt</b>
/tmp/absolute/subdir/output.jj
/tmp/absolute/&lt;generated&gt;.java</pre>
</td>
<td>Not Supported</td>
<td>Same</td>
</tr>
<tr>
<td><pre><b>jjtree -OUTPUT_FILE:subdir/output.jj -OUTPUT_DIRECTORY:/tmp/absolute/ relative/grammar.jjt</b>
/tmp/absolute/subdir/output.jj
/tmp/absolute/&lt;generated&gt;.java</pre>
</td>
<td>Not Supported</td>
<td>Same</td>
</tr>
<tr>
<td><pre><b>jjtree -OUTPUT_FILE:subdir/output.jj -OUTPUT_DIRECTORY:/tmp/absolute/ /tmp/absolute/grammar.jjt</b>
/tmp/absolute/subdir/output.jj
/tmp/absolute/&lt;generated&gt;.java</pre>
</td>
<td>Not Supported</td>
<td>Same</td>
</tr>
<tr>
<td><pre><b>jjtree -OUTPUT_FILE:/tmp/subdir/output.jj grammar.jjt</b>
/tmp/subdir/output.jj
/tmp/&lt;generated&gt;.java</pre>
</td>
<td>Not Supported</td>
<td>Same</td>
</tr>
<tr>
<td><pre><b>jjtree -OUTPUT_FILE:/tmp/subdir/output.jj relative/grammar.jjt</b>
/tmp/subdir/output.jj
/tmp/&lt;generated&gt;.java</pre>
</td>
<td>Not Supported</td>
<td>Same</td>
</tr>
<tr>
<td><pre><b>jjtree -OUTPUT_FILE:/tmp/subdir/output.jj /tmp/absolute/grammar.jjt</b>
/tmp/subdir/output.jj
/tmp/&lt;generated&gt;.java</pre>
</td>
<td>Not Supported</td>
<td>Same</td>
</tr>
<tr>
<td><pre><b>jjtree -OUTPUT_FILE:<i><u>D:</u></i>/tmp/subdir/output.jj grammar.jjt</b>
/tmp/subdir/output.jj
/tmp/&lt;generated&gt;.java</pre>
</td>
<td>Not Supported</td>
<td>Not Supported *)</td>
</tr>
<tr>
<td><pre><b>jjtree -OUTPUT_FILE:<i><u>D:</u></i>/tmp/subdir/output.jj relative/grammar.jjt</b>
/tmp/subdir/output.jj
/tmp/&lt;generated&gt;.java</pre>
</td>
<td>Not Supported</td>
<td>Not Supported *)</td>
</tr>
<tr>
<td><pre><b>jjtree -OUTPUT_FILE:<i><u>D:</u></i>/tmp/subdir/output.jj /tmp/absolute/grammar.jjt</b>
/tmp/subdir/output.jj
/tmp/&lt;generated&gt;.java</pre>
</td>
<td>Not Supported</td>
<td>Not Supported *)</td>
</tr>
<tr>
<td><pre><b>jjtree -OUTPUT_FILE:/tmp/subdir/output.jj -OUTPUT_DIRECTORY:relative grammar.jjt</b>
/tmp/relative/tmp/subdir/output.jj
/tmp/relative/&lt;generated&gt;.java</pre>
</td>
<td>Not Supported</td>
<td>Same</td>
</tr>
<tr>
<td><pre><b>jjtree -OUTPUT_FILE:/tmp/subdir/output.jj -OUTPUT_DIRECTORY:relative relative/grammar.jjt</b>
/tmp/relative/tmp/subdir/output.jj
/tmp/relative/&lt;generated&gt;.java</pre>
</td>
<td>Not Supported</td>
<td>Same</td>
</tr>
<tr>
<td><pre><b>jjtree -OUTPUT_FILE:/tmp/subdir/output.jj -OUTPUT_DIRECTORY:relative /tmp/absolute/grammar.jjt</b>
/tmp/relative/tmp/subdir/output.jj
/tmp/relative/&lt;generated&gt;.java</pre>
</td>
<td>Not Supported</td>
<td>Same</td>
</tr>
<tr>
<td><pre><b>jjtree -OUTPUT_FILE:/tmp/subdir/output.jj -OUTPUT_DIRECTORY:/tmp/absolute/ grammar.jjt</b>
/tmp/absolute/tmp/subdir/output.jj
/tmp/absolute/&lt;generated&gt;.java</pre>
</td>
<td>Not Supported</td>
<td>Same</td>
</tr>
<tr>
<td><pre><b>jjtree -OUTPUT_FILE:/tmp/subdir/output.jj -OUTPUT_DIRECTORY:/tmp/absolute/ relative/grammar.jjt</b>
/tmp/absolute/tmp/subdir/output.jj
/tmp/absolute/&lt;generated&gt;.java</pre>
</td>
<td>Not Supported</td>
<td>Same</td>
</tr>
<tr>
<td><pre><b>jjtree -OUTPUT_FILE:/tmp/subdir/output.jj -OUTPUT_DIRECTORY:/tmp/absolute/ /tmp/absolute/grammar.jjt</b>
/tmp/absolute/tmp/subdir/output.jj
/tmp/absolute/&lt;generated&gt;.java</pre>
</td>
<td>Not Supported</td>
<td>Same</td>
</tr>
</table>

<p>*) <u>Footnote</u>: When running JJTree with the Ant taskdesk <i>jjtree</i> the option <code>-OUTPUT_DIRECTORY</code> must always
be set, because the project's basedir and the ant working directory might differ. So even if you don't specify the jjtree taskdef
<i>outputdirectory</i> JJTree will be called with the <code>-OUTPUT_DIRECTORY</code> set to the project's basedirectory.
But when the <code>-OUTPUT_DIRECTORY</code> is set, the <code>-OUTPUT_FILE</code> setting is handled as if relative to this
<code>-OUTPUT_DIRECTORY</code>. Thus when the <code>-OUTPUT_FILE</code> is absolute or contains a drive letter we have a
problem.
Therefore absolute <i>outputfile</i>s (when the <i>outputdirectory</i> isn't specified) are made relative to the default directory.
And for this reason <i>outputfile</i>s that contain a drive letter can't be supported.</p>

<p>By the way: specifying a drive letter in the <code>-OUTPUT_FILE</code> when the <code>-OUTPUT_DIRECTORY</code> is set, also
results in strange behavior when running JJTree from the command line.</p>

<br>
<hr>
<p align="center">Copyright &copy; 2001-2003 Apache Software Foundation. All rights
Reserved.</p>



</body>
</html>


+ 93
- 10
src/main/org/apache/tools/ant/taskdefs/optional/javacc/JJTree.java View File

@@ -233,15 +233,15 @@ public class JJTree extends Task {
throw new BuildException("Invalid target: " + target);
}

if (outputFile != null) {
cmdl.createArgument().setValue("-" + OUTPUT_FILE + ":"
+ outputFile.replace('\\', '/'));
}

File javaFile = null;

// use the directory containing the target as the output directory
if (outputDirectory == null) {
// convert backslashes to slashes, otherwise jjtree will
// put this as comments and this seems to confuse javacc
cmdl.createArgument().setValue("-OUTPUT_DIRECTORY:"
+ getDefaultOutputDirectory());

javaFile = new File(createOutputFileName(target, outputFile,
null));
} else {
@@ -267,6 +267,12 @@ public class JJTree extends Task {
Project.MSG_VERBOSE);
return;
}

if (outputFile != null) {
cmdl.createArgument().setValue("-" + OUTPUT_FILE + ":"
+ outputFile.replace('\\', '/'));
}

cmdl.createArgument().setValue(target.getAbsolutePath());

cmdl.setClassname(JavaCC.getMainClass(javaccHome,
@@ -300,6 +306,8 @@ public class JJTree extends Task {

private String createOutputFileName(File target, String optionalOutputFile,
String outputDirectory) {
optionalOutputFile = validateOutputFile(optionalOutputFile,
outputDirectory);
String jjtreeFile = target.getAbsolutePath().replace('\\','/');

if ((optionalOutputFile == null) || optionalOutputFile.equals("")) {
@@ -326,11 +334,7 @@ public class JJTree extends Task {
}

if ((outputDirectory == null) || outputDirectory.equals("")) {
if (isAbsolute(optionalOutputFile)) {
return optionalOutputFile.replace('\\','/');
} else {
outputDirectory = getProject().getBaseDir().getAbsolutePath();
}
outputDirectory = getDefaultOutputDirectory();
}

return (outputDirectory + "/" + optionalOutputFile).replace('\\', '/');
@@ -339,4 +343,83 @@ public class JJTree extends Task {
private boolean isAbsolute(String fileName) {
return (fileName.startsWith("/") || (new File(fileName).isAbsolute()));
}

/**
* When running JJTree from an Ant taskdesk the -OUTPUT_DIRECTORY must
* always be set. But when -OUTPUT_DIRECTORY is set, -OUTPUT_FILE is
* handled as if relative of this -OUTPUT_DIRECTORY. Thus when the
* -OUTPUT_FILE is absolute or contains a drive letter we have a problem.
*
* @param outputFile
* @param outputDirectory
* @return
* @throws BuildException
*/
private String validateOutputFile(String outputFile,
String outputDirectory)
throws BuildException {
if (outputFile == null) {
return null;
}

if ((outputDirectory == null)
&& (outputFile.startsWith("/") || outputFile.startsWith("\\"))) {
String relativeOutputFile = makeOutputFileRelative(outputFile);
setOutputfile(relativeOutputFile);

return relativeOutputFile;
}

String root = getRoot(new File(outputFile)).getAbsolutePath();

if ((root.length() > 1)
&& outputFile.startsWith(root.substring(0, root.length() - 1))) {
throw new BuildException("Drive letter in 'outputfile' not "
+ "supported: " + outputFile);
}

return outputFile;
}

private String makeOutputFileRelative(String outputFile) {
StringBuffer relativePath = new StringBuffer();
String defaultOutputDirectory = getDefaultOutputDirectory();
int nextPos = defaultOutputDirectory.indexOf('/');
int startPos = nextPos + 1;

while (startPos > -1 && startPos < defaultOutputDirectory.length()) {
relativePath.append("/..");
nextPos = defaultOutputDirectory.indexOf('/', startPos);

if (nextPos == -1) {
startPos = nextPos;
} else {
startPos = nextPos + 1;
}
}

relativePath.append(outputFile);

return relativePath.toString();
}

private String getDefaultOutputDirectory() {
return getProject().getBaseDir().getAbsolutePath().replace('\\', '/');
}

/**
* Determine root directory for a given file.
*
* @param file
* @return file's root directory
*/
private File getRoot(File file) {
File root = file.getAbsoluteFile();

while (root.getParent() != null) {
root = root.getParentFile();
}

return root;
}
}

Loading…
Cancel
Save