This is the fault of interpreters. Interpreters receive the entire file as input, with the shebang line and all. That can easily support the encoding of additional parameters.
In TXR Lisp, I invented a novel way of doing this, which I call the "hash bang null hack".
If you put a NUL character into the hash bang line, then TXR will process arguments after that character. The NUL character is a string terminator, and so the operating system kernel doesn't see it; it thinks that's the end of the hash bang line.
So for instance (^@ represents NUL):
#!/usr/bin/env txr^@arg arg arg
This hack is not necessary, of course; a given language interpreter can do this in any number of ways.
E.g. arguments in a comment in the following line. The convention could be, say, that if the next line also starts with #!, it holds parameters:
#!/usr/bin/env my-language
#!--args to my language
I didn't do it this way because the language doesn't use # comments (so hacking argument recognition into comment processing is out) and I didn't want to complicate the hash bang logic to dealing with two or more lines: everything is handled in the one line and that's it.
Another solution is to rely on env having the BSD -S option, which specifies a string that becomes multiple arguments.
#!/usr/bin/env -S program --option arg
the hash bang mechanism will pass "program --option arg" as a single argument to env, whose -S option will split that into multiple arguments. You might run into a limit on the hash bang header. E.g. if the given operating system reads only, say, 32 bytses of the file (really ancient Unix system), in which it looks for the hash bang line, then you have only that much space to cram into that -S argument.
The -S option implemented in BSD unixes has a lot of bells and whistles: you can use escape characters in it to encode control characters and $ to expand environment variables. E.g. silly example:
#!/usr/bin/env -S $USER/bin/interp
would use every user's own "interp" in their own bin directory to run the program.
-S is not portable; it's not specified in POSIX. Newer versions of GNU Coreutils have it (but not with all the BSD features, I think). If you maintain a programing language, it behooves you to solve this problem for the users, so the only nonstandard thing they rely on is your language, without any collateral nonstandard stuff.
In TXR Lisp, I invented a novel way of doing this, which I call the "hash bang null hack".
If you put a NUL character into the hash bang line, then TXR will process arguments after that character. The NUL character is a string terminator, and so the operating system kernel doesn't see it; it thinks that's the end of the hash bang line.
So for instance (^@ represents NUL):
#!/usr/bin/env txr^@arg arg arg
This hack is not necessary, of course; a given language interpreter can do this in any number of ways. E.g. arguments in a comment in the following line. The convention could be, say, that if the next line also starts with #!, it holds parameters:
I didn't do it this way because the language doesn't use # comments (so hacking argument recognition into comment processing is out) and I didn't want to complicate the hash bang logic to dealing with two or more lines: everything is handled in the one line and that's it.Another solution is to rely on env having the BSD -S option, which specifies a string that becomes multiple arguments.
the hash bang mechanism will pass "program --option arg" as a single argument to env, whose -S option will split that into multiple arguments. You might run into a limit on the hash bang header. E.g. if the given operating system reads only, say, 32 bytses of the file (really ancient Unix system), in which it looks for the hash bang line, then you have only that much space to cram into that -S argument.The -S option implemented in BSD unixes has a lot of bells and whistles: you can use escape characters in it to encode control characters and $ to expand environment variables. E.g. silly example:
would use every user's own "interp" in their own bin directory to run the program.-S is not portable; it's not specified in POSIX. Newer versions of GNU Coreutils have it (but not with all the BSD features, I think). If you maintain a programing language, it behooves you to solve this problem for the users, so the only nonstandard thing they rely on is your language, without any collateral nonstandard stuff.