I am using ANTLRWorks 1.4.3 together with ANTLR 3.4 to generate a Java-based parser and lexer from a grammar file. The generated .java-files contain strings like
C:\\Users\\[path to the eclipse project]\\src\\some\\package\\name\\MyGrammar.g
This absolute path is used as
return string e.g. in method getGrammarFileName() of lexer and parser, and
throughout the both files various times as comment.
I see following disadvantages:
If somebody else with different paths in his development environment will regenerate these files, a lot of changes will be introduced even if no changes in the grammar file were done.
Nobody, especially in an open source project, needs to know where I exactly store my grammar files. E.g., what about C:\\Users\\simon\\customerA\\crap_software\\[rest of the path to grammar file]
Is there a way to control this in ANTLRWorks or ANTLR s.th. at least only relative paths are used?
Finally I found a way to solve my own problem.
Paths seem to depend from where and how you invoke ANTLR. I was not able to achieve this with ANTLRWorks, but using command line ANTLR you are able to perform this. You can do the following (example is for Windows but should be reproducible on other OSes, too):
Download Antlr for command line and copy it to e.g.
C:\Program Files (x86)\ANTLRworks\antlr-3.4-complete.jar.
Open a Windows command line (cmd.exe) and change to the directory where your grammar file is located:
cd C:\Users[path to the eclipse project]\src\some\package\name
Invoke
java -jar "C:\Program Files (x86)\ANTLRworks\antlr-3.4-complete.jar" MyGrammar.g
from commandline.
The generated java files will only contain the name of your grammar file and no path anymore.
Is there a way to control this in ANTLRWorks or ANTLR s.th. at least only relative paths are used?
Short answer
No.
Long(er) answer (Containing highly subjective views! Proceed at own risk)
This is target-specific, but, AFAIK, no target allows you to specify the type (absolute or relative) of the path.
The "no" might be because getGrammarFileName() is only used while debugging generated lexers/parsers. And one should probably not check in generated source files into source control, so no one would ever see the path you see in your generated source file. One ought to check in the grammar, and let developers generate their own lexers/parsers from it.
Again, this is all speculation on my part.
Related
bash
/Desktop/Lab 3$ cd Stemmer
/Desktop/Lab 3/Stemmer$ java Stemmer
/Desktop/Lab 3/Stemmer$ cd ..
/Desktop/Lab 3$ java Stemmer/Stemmer
Error: Could not find or load main class Stemmer.Stemmer
Caused by: java.lang.NoClassDefFoundError: Stemmer (wrong name: Stemmer/Stemmer)
/Desktop/Lab 3$
Why doesn't java run Stemmer when I specify a relative path?
It seems to have run the program when I was in the directory, but I want java to run Stemmer as it did when I was in the directory that it was located in.
Could someone explain what is happening here please.
When you run a Java program, you specify the class name including the fully specified package, not the file path. This means that you separate the package "path" with dots, not slash. If you compiled a file named Stemmer.java that is in a folder named Stemmer and has package Stemmer as the first line, then you do
java Stemmer.Stemmer
There are 2 broad options:
You are trying to write an application in java
Then you need an IDE to develop it in, and a build system to produce the distributables, in the form of a jar file. There is no point or reason to trying to run this 'on the command line' the way you are. You need packages and a project definition.
You are just toying around for now, writing some basic code in a single source file.
Then just run the source file. This is a feature introduced in, I think, java11. Before that, this model of writing (stuff some lines in a source file and run it right away) is not what java itself is good at, only IDEs do that properly.
Starting with java11:
java Stemmer/Stemmer.java
works great, and no need to (re)compile anything. java will take care of it.
Explanation
When you run a Java program, you specify the class name including the fully specified package, not the file path.
You read this answer before, and then proceeded to completely ignore it and try java Stemmer.Stemmer which obviously doesn't work.
The class you have is named Stemmer, and it is in the unnamed package. Thus, to run it, java Stemmer is how to do this. It's not a file name. Stemmer.Stemmer is not java-ese for 'run the class file Stemmer in the subdirectory Stemmer, and 'package' is not java-ese for 'directory on the filesystem'.
The classpath root for your Stemmer class is its own directory, as you are not using any packages. the default classpath is the current directory. It is not possible to run the Stemmer class file without having its root on the classpath, so if /Desktop/Lab 3/Stemmer is not on the cp, you can't do it. So let's fix this:
java -cp '/Desktop/Lab 3/Stemmer' Stemmer
and that'll work fine.
More generally, using the unnamed package is a bad idea, and trying to run raw class files is similarly a bad idea - use an IDE for development, and a build system to build projects.
These rules and caveats all make perfect sense when writing a 'real' project (one you check into source control, and eventually deploy someplace or ship as a product to other users). But it's onerous and a tad ridiculous if just messing around. That's exactly why (these days) you can just specify a path to a java source file, which seems to be what you want to do. So, do that.
I'm seeing a lot of errors, upwards of 170, when building my j2objc integrated project.
I think the java j2re library is correctly being located and the linking step says
-Llib/j2objcDist/lib
-Llib/j2objcDist/lib/macosx
-F/Users/username/Library/Developer/Xcode/DerivedData/MyApp-dkbwtvvwogkqknfpbozsmzhgrcei/Build/Products/Debug-iphonesimulator
-Flib/j2objcDist/frameworks
A lot of the paths that I'm seeing include the full user path but on the lib/j2objcDist/lib paths.
My library search paths are
${PROJECT_DIR}/lib/j2objcDist/lib/
My header search paths are
${PROJECT_DIR}/lib/j2objcDist/include
${DERIVED_FILES_DIR}
${PROJECT_DIR}/lib/j2objcDist/frameworks/JRE.framework/Headers
${PROJECT_DIR}/lib/j2objcDist/lib
My framework search paths are
${PROJECT_DIR}/lib/j2objcDist/frameworks
I've replicated the settings in the demo app available on the j2objc.org site to be best of my knowledge.
Any suggestions on what to try or where to look to fix this would be great.
It looks like you've set it up correctly for where to find the libraries, but haven't told the linker to include any libraries. In Other Linker Flags, set either "-ljre_emul" (or "-l jre_emul") to tell the linker to include the JRE emulation library.
That will fix all the errors you listed, but if you use other libraries then they need separate -l flags. For example, if you use any Google Guava classes, then "-lguava" also needs to be specified.
The linker finds libraries by taking each -l argument and converting it into a library name ("lib" + arg " + ".a", or libjre_emul.a in this case). It then checks each -L path to find this file, so the library should be listed with "ls ${PROJECT_DIR}/lib/j2objcDist/lib/libjre_emul.a" (substituting the actual project directory, of course).
If there is a -ljre_emul flag and a valid -L path to that library, then the issue is likely to be using a translator from one J2ObjC release and libraries from a different one. J2ObjC is a compiler, and its generated files need to be treated as transient build artifacts, not permanent source files. If your project saves translated .m and .h files, then every time a new distribution is used, all Java sources need to be updated with new translations.
In Unix (or Linux), if I want to run a shell script, I can start the file with #!/bin/sh. With awk, I start the executable file with #!/usr/bin/awk -f and it treats the rest of the file as the program.
How do I do that with a Java program? I tried copying the simple.class to simple, putting #!/export/appl/Mail/java/bin/java at the top and making the file executable, but I get:
69> ./simple
Error: Could not find or load main class ..simple
I know this can be done with an executable shell script, or a C program that execs the java interpreter. Every other interpreter on Unix can be called with a #! load card, surely there's a way to do it with Java.
The most usual way is to have a wrapper for the Java. A shell script that executes the "java -jar yourJar.jar" or equivalent. And then you bundle the shell script and the windows equivalent bat file with your product.
Another option is to have a native launcher. For example you can see the Eclipse project which has gone that way. You download Eclipse and you have a native executable to run. The native executable will launch your Java program.
One more option is to compile Java into native code. For example you can use this commercial tool called Excelsior JET ( http://www.excelsior-usa.com/jet.html ).
The Java class file format doesn't allow text before the header, that's why the Java runtime no longer accepts the .class file after your modification.
On Linux you can use binfmt_misc to support additional executable formats, including .class files. It's basically a way to tell the Linux kernel how to detect executable formats and how to execute them.
This Archilinux Wiki article explains in more detail how to get this effect.
You cannot do it with a Java program. Firstly, the Java program needs to be compiled before execution. Secondly, even if compilation wasn't required, the hash sign is not a comment in Java, so that would be a syntax error.
I've never heard the term "load card". What you have is an "interpreter directive" designated by a shebang. This merely designates which interpreter the shell should invoke on a given script.
As for why C programs can be run directly in the shell, executables recognized by the operating system are passed to the loader. A Java class isn't an executable, at least to the OS anyway. So the shell must know which interpreter to pass control to.
But as you've noticed, the shebang doesn't work. The reason is that the class file is in a specific binary format that the JVM expects. Editing this file will break convention and lead to an error. Therefore, there is no way to do what you've asked.
However, you can create a "shortcut" to the program you want to run by creating an alias or perhaps writing a one-line Shell script to wrap the java command you need. This is the common practice as I understand it.
The other answers explain why you can't do what you are trying to do. However, if your shell is zsh, you can create a suffix alias. For example, to execute .jar files using java:
alias -s .jar="/usr/bin/java -jar"
Then, to execute blarg.jar, you just type ./blarg.jar. Of course, you must chmod +x your .jar file first.
Apart from the wrapper script and binfmt_misc solutions suggested by others, I'd like to suggest a potential solution which doesn't directly answer your question but maybe it solves your actual problem.
Since Scala does have an interpreter that can run code without you having to compile it first, and this code can reference any Java code, if your goal can be summed up as "using Java as a shell scripting language", you could use a .scala file as your starter script (which can include the shebang to be run with scala) from which you can call all your Java classes. This isn't any simpler tha having a bash-based starter script, but it's a good starting point to gradually move to scripting in Scala instead of Java in which case you can get rid of the need to compile to .class file in the first place.
The reason this doesn't work is that Java isn't really an interpreted language, it's partially compiled, partially interpreted.
The .java source code that you'd put the hashbang directive in needs to be compiled to a .class file before the java interpreter can run it. Comments are stripped out by the compiler, so there's no way to push a comment from the .java into the .class file. The .class file is "compiled" output in a specific format, so adding a hashbang directive to the top of it would break the format.
Java isn't really meant to be a scripting language - but some JVM languages are. For example Groovy supports hashbang and so does Clojure.
I have a java jar file consists of some classes that each class has some variables, constants, functions,...
I want to extract the name of these classes, variables, constants, functions and function parameters in my Delphi program.
A work like that JD-GUI does. How can I do this? Is there any java sdk command line to do this ?
I once wrote a class-file parser for Delphi. You can find it here:
http://essmodel.cvs.sourceforge.net/viewvc/essmodel/essmodel/Integrator/CodeIO/JavaClass/
It is from 2004 but should still work unless the class-file format has changed considerably since then.
The parser is part of the freeware tool ESS-Model that creates static class diagrams.
Note that the parser works on class-files only. If you want to parse jar-files you need to first unzip the jar-file and extract the containing class-files (a jar-file is just a standard zip-file with the ".jar" extension).
Emil M. Santos has done the job for you.
He is the author of Class Explorer : an utility for browsing the low-level contents of a Java compiled class file (.class).
(source: codexterity.com)
You can grab its (Delphi for sure) source code here.
Good luck.
I would like to create a program in a linux/unix environment that runs from command line. The desired outcome would be to have the ability to tab complete directories. Are there any libraries available to achieve this?
Synopsis: /ho
[tab] /home/
There exists a JNI wrapper for the GNU "readline" library (which is what Bash uses for tab-completion); see http://sourceforge.net/projects/java-readline/. Tab-completion is a generic feature, not specifically tied to the filesystem — for example, the PostgreSQL command-line client uses tab-completion to complete table-names — so you'll probably want to use this in concert with the PrefixFileFilter that Tomasz Nurkiewicz mentions (or another similar approach for generating the list of filenames).
PrefixFileFilter from apache-commons IO might be helpful:
File dir = new File(".");
String[] files = dir.list(new PrefixFileFilter("ho"));
This will return a list of files in current directory starting with ho. You'll get the rest.
I don't think you need a library for that, just code it your self. File class already contains everything needed like:
File[] listFiles()
boolean isDirectory()
boolean isFile()
...
Then you just need to create:
take the temporary path, eg "/home/Ja"
split it between last concrete part and part to complete, /home and Ja
list files from concrete part new File("/home").listFiles()
and select only currently correct for partial file.getName().startsWith("Ja")
I guess it will be around 50-100 LOCs including all the checks necessary to avoid weird things.
If you want a good approach, use FilenameFilter, so that you will be able to filter out files directly when invoking listFiles, eg
files = folder.listFiles(new PartialFileFilter("Ja"))
Are there any Java libraries to create command line applications with TAB completion of directories?
You may be interested in picocli. Picocli is a 1-file Java library for building command line applications with almost zero code; it can generate ANSI colored usage help messages, and picocli supports command line autocompletion on Linux (and Cygwin and babun on Windows) since version 1.0.
How does this work? The bash and zsh Unix shells provide something called "programmable completion", and picocli leverages this to generate an autocompletion script tailored to the #Option and #Command annotations in your application.
With this script installed, users can type the TAB key, and the Unix shell will show a list of the available subcommands and options. For options associated with a java.io.File or java.nio.file.Path field, the shell will show the available files and directories that match what the user typed so far.
This actually handles more than just files and directories: the picocli-generated completion script shows known hosts (from the user's /etc/hosts file) for options of type java.net.InetAddress, and shows enumvalues for options on fields of any enum type, including custom enums.
The below animation demonstrates what is possible.
You can use a recent JLine version.
The latest one is available from https://github.com/jline/jline3.
It provides built-in completers for directories and files.
JLine is probably no longer maintained, but there are still quite a few Java projects that use it:
http://jline.sourceforge.net/index.html
However, if you know what you want to use Linux/Unix, and the only completion you want is simple file/directory names, you could just shift the problem and run your Java app under rlwrap:
$ rlwrap -c java ...