From 58968aaa63891f65d5a9a7197310471fbc21f4e1 Mon Sep 17 00:00:00 2001 From: Stefan Bodewig Date: Thu, 14 Aug 2003 14:52:42 +0000 Subject: [PATCH] Make 's outputdirectory and outputfile attributes work as expected (i.e. consistent with the command line of jjtree). PR: 21526 Submitted by: Jene Jasper git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@275090 13f79535-47bb-0310-9956-ffa450edef68 --- docs/manual/OptionalTasks/jjtree.html | 346 ++++++++++++++++++ .../ant/taskdefs/optional/javacc/JJTree.java | 103 +++++- 2 files changed, 439 insertions(+), 10 deletions(-) diff --git a/docs/manual/OptionalTasks/jjtree.html b/docs/manual/OptionalTasks/jjtree.html index 15b224231..51b74d56f 100644 --- a/docs/manual/OptionalTasks/jjtree.html +++ b/docs/manual/OptionalTasks/jjtree.html @@ -186,10 +186,356 @@ Example 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. +
+ +

Comparison output locations between command line JJTree and different Ant taskdef versions

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Command Line JJTree options +
     and Generated Files (working directory: /tmp)
Ant 1.5.3 versus command lineAnt 1.6 versus command line
jjtree  grammar.jjt
+    /tmp/grammar.jj
+    /tmp/<generated>.java
+
SameSame
jjtree  relative/grammar.jjt
+    /tmp/grammar.jj
+    /tmp/<generated>.java
+
+/tmp/relative/grammar.jj
+/tmp/relative/<generated>.java
+
Same
jjtree  /tmp/absolute/grammar.jjt
+    /tmp/grammar.jj
+    /tmp/<generated>.java
+
+/tmp/absolute/grammar.jj
+/tmp/absolute/<generated>.java
+
Same
jjtree  -OUTPUT_DIRECTORY:relative  grammar.jjt
+    /tmp/relative/grammar.jj
+    /tmp/relative/<generated>.java
+
SameSame
jjtree  -OUTPUT_DIRECTORY:relative  relative/grammar.jjt
+    /tmp/relative/grammar.jj
+    /tmp/relative/<generated>.java
+
SameSame
jjtree  -OUTPUT_DIRECTORY:relative  /tmp/absolute/grammar.jjt
+    /tmp/relative/grammar.jj
+    /tmp/relative/<generated>.java
+
SameSame
jjtree  -OUTPUT_DIRECTORY:/tmp/absolute/  grammar.jjt
+    /tmp/absolute/grammar.jj
+    /tmp/absolute/<generated>.java
+
SameSame
jjtree  -OUTPUT_DIRECTORY:/tmp/absolute/  relative/grammar.jjt
+    /tmp/absolute/grammar.jj
+    /tmp/absolute/<generated>.java
+
SameSame
jjtree  -OUTPUT_DIRECTORY:/tmp/absolute/  /tmp/absolute/grammar.jjt
+    /tmp/absolute/grammar.jj
+    /tmp/absolute/<generated>.java
+
SameSame
jjtree  -OUTPUT_FILE:output.jj  grammar.jjt
+    /tmp/output.jj
+    /tmp/<generated>.java
+
Not SupportedSame
jjtree  -OUTPUT_FILE:output.jj  relative/grammar.jjt
+    /tmp/output.jj
+    /tmp/<generated>.java
+
Not SupportedSame
jjtree  -OUTPUT_FILE:output.jj  /tmp/absolute/grammar.jjt
+    /tmp/output.jj
+    /tmp/<generated>.java
+
Not SupportedSame
jjtree  -OUTPUT_FILE:output.jj  -OUTPUT_DIRECTORY:relative  grammar.jjt
+    /tmp/relative/output.jj
+    /tmp/relative/<generated>.java
+
Not SupportedSame
jjtree  -OUTPUT_FILE:output.jj  -OUTPUT_DIRECTORY:relative  relative/grammar.jjt
+    /tmp/relative/output.jj
+    /tmp/relative/<generated>.java
+
Not SupportedSame
jjtree  -OUTPUT_FILE:output.jj  -OUTPUT_DIRECTORY:relative  /tmp/absolute/grammar.jjt
+    /tmp/relative/output.jj
+    /tmp/relative/<generated>.java
+
Not SupportedSame
jjtree  -OUTPUT_FILE:output.jj  -OUTPUT_DIRECTORY:/tmp/absolute/  grammar.jjt
+    /tmp/absolute/output.jj
+    /tmp/absolute/<generated>.java
+
Not SupportedSame
jjtree  -OUTPUT_FILE:output.jj  -OUTPUT_DIRECTORY:/tmp/absolute/  relative/grammar.jjt
+    /tmp/absolute/output.jj
+    /tmp/absolute/<generated>.java
+
Not SupportedSame
jjtree  -OUTPUT_FILE:output.jj  -OUTPUT_DIRECTORY:/tmp/absolute/  /tmp/absolute/grammar.jjt
+    /tmp/absolute/output.jj
+    /tmp/absolute/<generated>.java
+
Not SupportedSame
jjtree  -OUTPUT_FILE:subdir/output.jj  grammar.jjt
+    /tmp/subdir/output.jj
+    /tmp/<generated>.java
+
Not SupportedSame
jjtree  -OUTPUT_FILE:subdir/output.jj  relative/grammar.jjt
+    /tmp/subdir/output.jj
+    /tmp/<generated>.java
+
Not SupportedSame
jjtree  -OUTPUT_FILE:subdir/output.jj  /tmp/absolute/grammar.jjt
+    /tmp/subdir/output.jj
+    /tmp/<generated>.java
+
Not SupportedSame
jjtree  -OUTPUT_FILE:subdir/output.jj  -OUTPUT_DIRECTORY:relative  grammar.jjt
+    /tmp/relative/subdir/output.jj
+    /tmp/relative/<generated>.java
+
Not SupportedSame
jjtree  -OUTPUT_FILE:subdir/output.jj  -OUTPUT_DIRECTORY:relative  relative/grammar.jjt
+    /tmp/relative/subdir/output.jj
+    /tmp/relative/<generated>.java
+
Not SupportedSame
jjtree  -OUTPUT_FILE:subdir/output.jj  -OUTPUT_DIRECTORY:relative  /tmp/absolute/grammar.jjt
+    /tmp/relative/subdir/output.jj
+    /tmp/relative/<generated>.java
+
Not SupportedSame
jjtree  -OUTPUT_FILE:subdir/output.jj  -OUTPUT_DIRECTORY:/tmp/absolute/  grammar.jjt
+    /tmp/absolute/subdir/output.jj
+    /tmp/absolute/<generated>.java
+
Not SupportedSame
jjtree  -OUTPUT_FILE:subdir/output.jj  -OUTPUT_DIRECTORY:/tmp/absolute/  relative/grammar.jjt
+    /tmp/absolute/subdir/output.jj
+    /tmp/absolute/<generated>.java
+
Not SupportedSame
jjtree  -OUTPUT_FILE:subdir/output.jj  -OUTPUT_DIRECTORY:/tmp/absolute/  /tmp/absolute/grammar.jjt
+    /tmp/absolute/subdir/output.jj
+    /tmp/absolute/<generated>.java
+
Not SupportedSame
jjtree  -OUTPUT_FILE:/tmp/subdir/output.jj  grammar.jjt
+    /tmp/subdir/output.jj
+    /tmp/<generated>.java
+
Not SupportedSame
jjtree  -OUTPUT_FILE:/tmp/subdir/output.jj  relative/grammar.jjt
+    /tmp/subdir/output.jj
+    /tmp/<generated>.java
+
Not SupportedSame
jjtree  -OUTPUT_FILE:/tmp/subdir/output.jj  /tmp/absolute/grammar.jjt
+    /tmp/subdir/output.jj
+    /tmp/<generated>.java
+
Not SupportedSame
jjtree  -OUTPUT_FILE:D:/tmp/subdir/output.jj  grammar.jjt
+    /tmp/subdir/output.jj
+    /tmp/<generated>.java
+
Not SupportedNot Supported *)
jjtree  -OUTPUT_FILE:D:/tmp/subdir/output.jj  relative/grammar.jjt
+    /tmp/subdir/output.jj
+    /tmp/<generated>.java
+
Not SupportedNot Supported *)
jjtree  -OUTPUT_FILE:D:/tmp/subdir/output.jj  /tmp/absolute/grammar.jjt
+    /tmp/subdir/output.jj
+    /tmp/<generated>.java
+
Not SupportedNot Supported *)
jjtree  -OUTPUT_FILE:/tmp/subdir/output.jj  -OUTPUT_DIRECTORY:relative  grammar.jjt
+    /tmp/relative/tmp/subdir/output.jj
+    /tmp/relative/<generated>.java
+
Not SupportedSame
jjtree  -OUTPUT_FILE:/tmp/subdir/output.jj  -OUTPUT_DIRECTORY:relative  relative/grammar.jjt
+    /tmp/relative/tmp/subdir/output.jj
+    /tmp/relative/<generated>.java
+
Not SupportedSame
jjtree  -OUTPUT_FILE:/tmp/subdir/output.jj  -OUTPUT_DIRECTORY:relative  /tmp/absolute/grammar.jjt
+    /tmp/relative/tmp/subdir/output.jj
+    /tmp/relative/<generated>.java
+
Not SupportedSame
jjtree  -OUTPUT_FILE:/tmp/subdir/output.jj  -OUTPUT_DIRECTORY:/tmp/absolute/  grammar.jjt
+    /tmp/absolute/tmp/subdir/output.jj
+    /tmp/absolute/<generated>.java
+
Not SupportedSame
jjtree  -OUTPUT_FILE:/tmp/subdir/output.jj  -OUTPUT_DIRECTORY:/tmp/absolute/  relative/grammar.jjt
+    /tmp/absolute/tmp/subdir/output.jj
+    /tmp/absolute/<generated>.java
+
Not SupportedSame
jjtree  -OUTPUT_FILE:/tmp/subdir/output.jj  -OUTPUT_DIRECTORY:/tmp/absolute/  /tmp/absolute/grammar.jjt
+    /tmp/absolute/tmp/subdir/output.jj
+    /tmp/absolute/<generated>.java
+
Not SupportedSame
+ +

*) Footnote: When running JJTree with the Ant taskdesk jjtree the option -OUTPUT_DIRECTORY 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 +outputdirectory JJTree will be called with the -OUTPUT_DIRECTORY set to the project's basedirectory. +But when the -OUTPUT_DIRECTORY is set, the -OUTPUT_FILE setting is handled as if relative to this +-OUTPUT_DIRECTORY. Thus when the -OUTPUT_FILE is absolute or contains a drive letter we have a +problem. +Therefore absolute outputfiles (when the outputdirectory isn't specified) are made relative to the default directory. +And for this reason outputfiles that contain a drive letter can't be supported.

+ +

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

+

Copyright © 2001-2003 Apache Software Foundation. All rights Reserved.

+ + + diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/javacc/JJTree.java b/src/main/org/apache/tools/ant/taskdefs/optional/javacc/JJTree.java index 9b1377973..82d6e95e7 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/javacc/JJTree.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/javacc/JJTree.java @@ -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; + } }