C programmers (and even bash programmers) are used to do tricks with command line arguments. A very common trick is testing argv[0] (this is C!) in order to assume certain defaults. For example, grep, egrep and fgrep are all the same executable really, which behaves differently depending on how it is invoked.
The entry point of a C application is:
int main(int argc, void* argv[])
So, when you invoke fgrep abc file.txt, this is what the application sees:
argc = 3
argv[0] = "fgrep"
argv[1] = "abc"
argv[2] = "file.txt"
Now compare with Scala Native. The entry point of a Scala application is:
def main(args: Array[String]): Unit
If you invoke `fgrep-out abc file.txt``, this is what the application sees:
args(0) = "abc"
args(1) = "file.txt"
I suggest that Scala Native somehow passes the name of the executable to the program.
Possibly the runtime enviroment could simply expose a variable which contains the argv[0] which was ignored when args was populated. Something like exposing...
private var argv0 = ""
def program: String = argv0
... and initializing argv0 like this:
argv0 = argv(0)
just before:
82 while (c < argc-1) {
83 // use the default Charset (UTF_8 atm)
84 args(c) = fromCString(argv(c+1))
85 c += 1
86 }
Ideas? Thanks
At this point, scala-bindgen simply fakes argv(0) like shown below:
def main(args: Array[String]): Unit = {
val argc = args.length + 1
val argv: Ptr[CString] = malloc(sizeof[CString] * argc).cast[Ptr[CString]]
argv(0) = "bindgen" //FIXME: https://github.com/scala-native/scala-native/issues/266
args.zipWithIndex.foreach { case (arg, idx) => argv(idx+1) = args(idx) }
System.exit( main(argc, argv) )
}
I vote for a dual entry point. The programmer choose which one in build.sbt:
JVM style, the default:
def main(args: Array[String]): Unit
C style, if some configuration is set in build.sbt
def main(argc: Int, argv: Ptr[CString]): Int
As a side effect, this solution supports better the case where the application uses the Scala syntax but calls only C functions as it doesn't introduce unused dependencies on java.lang.String and scala.Array
We should probably do something along the lines of JSApp from Scala.js to expose an alternative C-style entry point.
I volunteer for implementing this. Thanks.
Most helpful comment
I vote for a dual entry point. The programmer choose which one in
build.sbt:JVM style, the default:
def main(args: Array[String]): UnitC style, if some configuration is set in
build.sbtdef main(argc: Int, argv: Ptr[CString]): IntAs a side effect, this solution supports better the case where the application uses the Scala syntax but calls only C functions as it doesn't introduce unused dependencies on
java.lang.Stringandscala.Array