Native shebang: Difference between revisions
Content deleted Content added
m →{{header|C}}: fix vim typo |
→{{header|C}}: add {{header|UNIX_shell}} |
||
Line 21: | Line 21: | ||
=={{header|C}}== |
=={{header|C}}== |
||
'''File: script_gcc.c''' |
'''File: script_gcc.c''' |
||
<lang c># |
<lang c>#!/usr/local/bin/script_gcc.sh |
||
#include <errno.h> |
|||
#include <libgen.h> |
#include <libgen.h> |
||
#include <stdarg.h> |
#include <stdarg.h> |
||
Line 30: | Line 31: | ||
#include <unistd.h> |
#include <unistd.h> |
||
/* the shebang is: |
/* the actual shebang for C targets is: |
||
#!/usr/local/bin/script_gcc |
#!/usr/local/bin/script_gcc.c |
||
*/ |
*/ |
||
Line 148: | Line 149: | ||
'''Test Source File: echo.c''' |
'''Test Source File: echo.c''' |
||
<lang c>#!/usr/local/bin/script_gcc |
<lang c>#!/usr/local/bin/script_gcc.c |
||
#include <stdio.h> |
|||
#include <string.h> |
|||
#include <stdlib.h> |
|||
int main(int argc, char **argv, char **envp){ |
|||
char ofs = '\0'; |
|||
for(argv++; *argv; argv++){ |
|||
if(ofs)putchar(ofs); else ofs=' '; |
|||
fwrite(*argv, strlen(*argv), 1, stdout); |
|||
} |
|||
putchar('\n'); |
|||
exit(EXIT_SUCCESS); |
|||
}</lang> |
|||
'''Test Execution:''' |
|||
<pre> |
|||
$ ./echo.c Hello, world! |
|||
</pre> |
|||
'''Test Output:''' |
|||
<pre> |
|||
Hello, world! |
|||
</pre> |
|||
=={{header|UNIX Shell}}== |
|||
{{works with|Bourne Again SHell}} |
|||
Note: this '''Native shebang''' task does not exactly apply to [[bash]] because is interpretive, but as a skeleton template the following script is an example of how compiled languages can implement the shebang. Also: this bash code can be used to ''automatically'' compile the C code in /usr/local/bin/script_gcc.c above. |
|||
'''File: script_gcc.sh''' |
|||
<lang bash>#!/bin/bash |
|||
# Alternative: |
|||
#!/bin/bash /usr/local/bin/gcc_script.sh |
|||
# CACHE=No # to turn off caching... |
|||
# Note: this shell should be re-written in actual C! :-) |
|||
DIALECT=c # or cpp |
|||
CC="gcc" |
|||
COPTS="-lm -x $DIALECT" |
|||
IEXT=.$DIALECT |
|||
OEXT=.out |
|||
ENOENT=2 |
|||
srcpath="$1"; shift # => "$@" |
|||
#basename="$(basename "$srcpath" ."$DIALECT")" |
|||
basename="$(basename "$srcpath")" |
|||
# Warning: current dir "." is in path, AND */tmp directories are common/shared |
|||
paths="$(dirname "$srcpath") |
|||
$HOME/bin |
|||
/usr/local/bin |
|||
. |
|||
$HOME/tmp |
|||
$HOME |
|||
$HOME/Desktop" |
|||
#/tmp |
|||
while read dirnamew; do |
|||
[ -w "$dirnamew" ] && break |
|||
done << end_here_is |
|||
$paths |
|||
end_here_is |
|||
compile(){ |
|||
sed -n '2,$p' "$srcpath" | "$CC" $COPTS -o "$binpath" - |
|||
} |
|||
if [ "'$CACHE'" = "'No'" ]; then |
|||
binpath="$dirnamew/$basename-v$$$OEXT" |
|||
if compile; then |
|||
( sleep 0.1; exec rm "$binpath" ) & exec "$binpath" "$@" |
|||
fi |
|||
else |
|||
while read dirnamex; do |
|||
binpath="$dirnamex/$basename$OEXT" |
|||
if [ -x "$binpath" -a "$binpath" -nt "$srcpath" ]; |
|||
then exec "$binpath" "$@"; fi |
|||
done << end_here_is |
|||
$paths |
|||
end_here_is |
|||
binpath="$dirnamew/$basename$OEXT" |
|||
if compile; then exec "$binpath" "$@"; fi |
|||
echo "$binpath: executable not available" 1>&2 |
|||
exit $ENOENT |
|||
fi</lang> |
|||
'''Test Source File: echo.c''' |
|||
<lang c>#!/usr/local/bin/script_gcc.sh |
|||
#include <stdio.h> |
#include <stdio.h> |
||
#include <string.h> |
#include <string.h> |