You don't need to install anything; you could put this on the first line of your file, and achieve the same effect, with just tools you already have installed:<p><pre><code> //usr/bin/make -s "${0%.c}" && ./"${0%.c}" "$@"; s=$?; rm ./"${0%.c}"; exit $s
</code></pre>
Actually, you could extend this to any file type that Make has built-in rules for, and which uses // as a comment delimiter:<p><pre><code> //usr/bin/make -s "${0%.*}" && ./"${0%.*}" "$@"; s=$?; rm ./"${0%.*}"; exit $s</code></pre>
I find this construct quite interesting....<p><pre><code> help_msg() {
>&$1 echo "Usage: $0 [file.c...
>&$1 echo "Execute C progams from the command line."
...
}
</code></pre>
for that it puts the redirection at the beginning of the line, which is unusual and I didn't even realize until now that it's valid. ( example: >&55 redirects stdout to filescriptor number 55, and here >&$1 redirects stdout of echo to the filedescriptor number given as the first argument to the function)<p><pre><code> # help if we have no arguments and no stdin
if [ $# -eq 0 ] && [ -t 0 ]; then
help_msg 2 # <--- NOTE 2 = stderr
exit 1
fi
# help if we get the flags
if [ "$1" == "--help" ] || [ "$1" == "-h" ]; then
help_msg 1 - <--- NOTE 1 = stdout
exit 0
fi
</code></pre>
And second, that the author seems to switch between outputting the help_msg on stdout or stderr, depending on if stdout exists. I always was under the impression that only the actual script result ought to go to stdout, and personally I always put out general debugging, error messages, but also the usage, unconditionally to stderr.
Neat hack, but if I wanted to compile, I'd just go ahead and compile. These are more interesting:<p><pre><code> http://bellard.org/tcc/ (use -run)
https://root.cern.ch/drupal/content/cint
https://root.cern.ch/drupal/content/cling</code></pre>
Congratulations, but <a href="http://bellard.org/tcc/" rel="nofollow">http://bellard.org/tcc/</a> already do that!<p>How do they compare?
A quick note, I see a few big issues:<p>1. There's no guarantee that you can run anything directly out of /tmp/. IIRC lots of distros mount /tmp/ with noexec specifically so you can't do this. You might still be able to invoke ld directly to run it, but that's still kinda a hack to get around the noexec.<p>2. You need write access to the .c file. That means you can't install any scripts using this system-wide, because you won't have write-access to the .c source unless you're root.<p>IMO, the most obvious solution to the second is to make a copy of the .c source and edit that instead. AFAIK there isn't an easy solution to the first issue though.
This doesn't appear to cache compiled "scripts", which to me makes it kind of useless. It's nice not to leave binaries laying around but I'd expect things to be saved (otherwise it's pretty slow).
Here is a way to do it without installing a /usr/bin/c.<p>All you takes is a few lines of shell code to the top of the C file.<p><a href="http://rosettacode.org/wiki/Multiline_shebang#C" rel="nofollow">http://rosettacode.org/wiki/Multiline_shebang#C</a><p>I contributed that, anonymously. Previously, the task had been marked "omit from C", would you believe it!<p>Also, note the little "Student exercise" below the code. For this to be useful, you want to cache the compiler output; you want to recompile the underlying executable only if the C script has changed.<p>The inconvenience of invoking C programs obviously isn't the real obstacle to its use as a scripting language, otherwise this kind of thing would be widely used.
I have done something like this and use it for simple tests of my assumptions [1]. This one from OP is more polished I suppose. I must check if it supports (with shebang) putting "c-script",in pipeline.<p>As was already mentioned Fabrice Bellard's tcc is great in this regard. There were similar projects done with LLVM.<p>What I would really like to have is some kind of compiler or different C preprocessor that would implement modules, such as that building C would be as simple as building Go programs. Price for it I suppose are macros. I think it's possible.<p>[1] <a href="http://hawski.com/ccrun" rel="nofollow">http://hawski.com/ccrun</a>
Beware that using another script as the executable in shebang <i>may not</i> work everywhere [0]<p>[0] <a href="http://www.in-ulm.de/~mascheck/various/shebang/#interpreter-script" rel="nofollow">http://www.in-ulm.de/~mascheck/various/shebang/#interpreter-...</a>
I do something similar when working on single-file programs, but without any external dependencies, by making the file both a valid shell script (for my shell) and a valid C program. Here's an example in Swift, although the same idea works for C too:<p><a href="https://gist.github.com/mikeash/70d74f7b7745cf6fbd3f" rel="nofollow">https://gist.github.com/mikeash/70d74f7b7745cf6fbd3f</a>
Nice to have another option, but been able to do this (as well as C++, FORTRAN, assembler, Java and Pascal) under Linux for a while:<p><a href="https://www.netfort.gr.jp/~dancer/software/binfmtc.html.en" rel="nofollow">https://www.netfort.gr.jp/~dancer/software/binfmtc.html.en</a><p>For Debian, "apt-get install binfmtc"