- Notifications
You must be signed in to change notification settings - Fork13
A shebang-friendly script for "interpreting" single C99, C11, and C++ files, including rcfile support.
License
RhysU/c99sh
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
A shebang-friendly script for "interpreting" single C99, C11, and C++ files,including rcfile support.
For example, installing this~/.c99shrc
control file
-Wall -g -O2#include <stdio.h>
permits executinghello containing
#!/usr/bin/env c99shint main(){ puts("Hello, world!");}
to produce the output one expects providedc99sh is in the path. Youmay also runc99sh foo.c
to execute somefoo.c
lacking the shebang line. Tryc99sh -v foo.c
if you encounter trouble and want to see the compilationcommand. Check outc99sh -h
for all the command line options you might use. Inparticular, for simple tasks you might find that the command line options inconjunction with HERE documents can accomplish many things. For example,
$ ./c99sh -sm <<HEREputs("Hello, world!");HERE
One or more lines can be included using-e
:
$ ./c99sh -e 'int main()' -e '{}'
Usually,-sm
appears alongside-e
:
$ ../c99sh -e 'int start = 3;' -sm <<HEREif (start == 3) { printf("Hello from 1-liner\n");} else { return 1;}HERE
Beware quote escaping for-e
could use someprintf
love. Patches welcome.
Control files can supply compilation and linking flags, preprocessor directiveslike#include
, andpkg-config directives tosimplify library usage. Ac99shrc
located in the same directory as theinterpreted source will be used. Otherwise a~/.c99shrc
is processed ifavailable. Seec99shrc.example for an extended control fileenablingGSL,GLib, andSQLitecapabilities. Control files ease accessing libraries with higher-leveldata structures.
A more entertaining example is anOpenMP-enabled MonteCarlo computation of π screaming like a banshee on all your cores(c99shrc,source):
#!/usr/bin/env c99shint main(int argc, char *argv[]){ long long niter = argc > 1 ? atof(argv[1]) : 100000; long long count = 0; #pragma omp parallel { unsigned int seed = omp_get_thread_num(); #pragma omp for reduction(+: count) schedule(static) for (long long i = 0; i < niter; ++i) { const double x = rand_r(&seed) / (double) RAND_MAX; const double y = rand_r(&seed) / (double) RAND_MAX; count += sqrt(x*x + y*y) < 1; } } printf("%lld: %g\n", niter, M_PI - 4*(count / (double) niter));}
Take that,GIL.
Kidding aside, the speedup in the edit-compile-run loop can be handy duringprototyping or analysis. It is nice when useful one-off scripts can be moveddirectly into C ABI code instead of requiring an additional{Python,Octave,R}-to-C translation and debugging phase. For example, comparetheOctave version of some simple logic with theequivalent c99sh-based version requiring only a fewone-time additions to your~/.c99shrc
.
Dual shebang/compiled support, that is a source file that can be bothinterpreted via./shebang.c
and compiled viagcc shebang.c
, can mostsuccinctly be achieved as follows:
#if 0exec c99sh "$0" "$@"#endif#include <stdio.h>int main(int argc, char *argv[]){ for (int i = 1; i < argc; ++i) { printf("Hello, %s!\n", argv[i]); }}
This dual shebang approach permits quick testing/iteration on validC source files using the-t
option:
#if 0exec c99sh -t 'test()' "$0" "$@"#endif#include <stdio.h>int logic(){ return 42;}static void test(){ printf("%d\n", logic());}
Testing in this manner resembles how folks use Python's__main__
insidelibraries.
As nearly the entire C99-oriented implementation works for C++, by invokingc99sh through either a copy or symlink namedcxxsh, you canwrite C++-based logic. The relevant control files are named likecxxshrc
inthis case and they support directives likeusing namespace std
andnamespace fb = foo::bar
. Seecxx/hello andcxx/cxxshrc for ahello world C++ example. Seecxx/shebang.cpp andcxx/quicktest.cpp for C++ dual shebang/compiled idioms.
One nice use case is hacking atopEigen since itprovides pkg-config support. That is,cxxsh -p eigen3 myprogram
builds andruns a one-off, Eigen-based program. With the rightcxxshrc
, such a programcan be turned into a script. Though, you will likely notice the compilationoverhead much moreso with C++ than C99. That said, for repeated invocation anoutput binary can be saved with the-x
option should repeated recompilation beprohibitively expensive.
C11 can be used via a symlink namedc11sh with control files likec11shrc
.
The idea forc99sh
came from21st CenturyC's section "Compiling CPrograms via Here Document" (availableonline)byBen Klemens. Additionally, I wrote it somewhat inreaction to browsing the C++-ish work byelsamuko/cppsh.
The dual shebang/compiled approach was suggested bymcandre andjtsagata. Thank you both for pushing on theidea, as I did not think it could be done in three clean lines.
The one line execution similar to Perl's -e was done bymattapiroglu.
The-l
command line option was contributed byflipcoder.
The-F
and-L
command line options were contributed byProducerMatt.
About
A shebang-friendly script for "interpreting" single C99, C11, and C++ files, including rcfile support.