Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose argv[0] since it is missing in the entrypoint: def main(args: Array[String]) #266

Open
frgomes opened this issue Aug 5, 2016 · 4 comments

Comments

@frgomes
Copy link

frgomes commented Aug 5, 2016

Context

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"

Discussion

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

@frgomes
Copy link
Author

frgomes commented Aug 5, 2016

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) )
}

@fbertra
Copy link
Contributor

fbertra commented Aug 7, 2016

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

@densh densh added the interop label Aug 8, 2016
@densh densh added this to the Backlog milestone Aug 8, 2016
@densh
Copy link
Member

densh commented Aug 8, 2016

We should probably do something along the lines of JSApp from Scala.js to expose an alternative C-style entry point.

@frgomes
Copy link
Author

frgomes commented Aug 8, 2016

I volunteer for implementing this. Thanks.

@densh densh added the feature label Nov 30, 2016
@densh densh modified the milestones: 0.4, Backlog May 20, 2017
@densh densh modified the milestones: 0.4, Backlog Jan 9, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants