November 18, 2008

Treat your C code like scripts with C Cod

Author: Ben Martin

C Cod is a front end to your C, C++, or Objective-C compiler that lets you treat C more like a scripting language. C Cod comes with C Server Pages, which provides support for CGI so you can write Web applications in C or C++ and have them automatically compiled on demand.

There are no packages of C Cod for Ubuntu, Fedora, or openSUSE. I'll build from source using version 1.2.8 on a 64-bit Fedora 9 machine. I ran into a slight hitch during compilation which can be resolved by adding an option for position-independent code to your CFLAGS as shown below. PIC code has the advantage that it can be loaded at different locations in memory; this is useful for compiling code for shared libraries because it allows them to be moved when multiple libraries would otherwise want the same address.

$ tar xzvf /.../ccod-1.2.8.tar.gz
$ cd ./ccod-*/
$ ./configure
$ make
/usr/bin/ld: csp.o: relocation R_X86_64_32 against `a local symbol' can not be used when making a shared object; recompile with -fPIC
csp.o: could not read symbols: Bad value

$ vi Makefile
PACKAG = ccod-1.2.8
LFLAGS = -shared -Wl,-soname,libcsp.so
CFLAGS = -O2 -fPIC
LIBSTA = *.a
$ make clean
$ make
$ sudo make install

My first attempt to use ccod failed with a segfault, as shown below.

$ cat main1.c
#!/usr/bin/ccod
#pragma CCOD:script no

int main( int argc, char** argv )
{
printf("hi there\n");
return 0;
}

$ chmod +x main1.c
$ ./main1.c
Segmentation fault

Digging into this, I found that the cksum() function was the cause. After experimentation, the below change to the size of the s variable seemed to fix the issue (or at least it no longer crashed).

$ gdb /usr/bin/ccod
(gdb) r main1.c
...
(gdb) bt
#0 0x0000000000404554 in cksum (path=0x10f3390 "/home/ben/testing/ccod/hello-world.c") at ccod.c:1306
#1 0x000000000040441b in get_sourcesum () at ccod.c:1203
#2 0x0000000000409605 in main (in_argc=2, in_argv=0x7fff6008bcd8) at ccod.c:3398
(gdb) q

$ vi /home/ben/testing/ccod/hello-world.c
...
static unsigned long
cksum(const unsigned char *path)
{
// register unsigned long i, c, s = 0;
register unsigned long i, c = 0;
int s = 0;
...

... recompile and reinstall ccod ...

$ ./main1.c
hi there

In the above example I used ccod in a way that leaves your source code closest to a normal standard C file. For simple, single-file programs you only need to add the two lines at the top of the source code to use it with ccod. Most of the examples on the ccod Web site instead use a mixed mode C syntax that is modeled after PHP. For instance, in the below example, notice that there is no longer a main() function, and that any text that is outside the <? block is simply printed to the terminal when the program is executed.

$ cat ./main2.c
#!/usr/bin/ccod

hi there

printf("and more\n");
return 0;
?>

$ chmod +x ./main2.c
$ ./main2.c

hi there

and more

The invasive syntax works well if you want to use ccod for Web programming with the supplied C Server Pages interface. The documentation page lists a small collection of functions that make CGI programming with C Server Pages fairly painless. The functions one expects for Web programming, such as session handling, cookies, forms, access to the query string, and redirection, are all available as normal C functions for C Server Page applications.

In the first example, I used #pragma CCOD:script to tweak the way ccod handled the C source file. The project provides about a dozen such pragmas, allowing you to specify what compiler to use, what flags to invoke the compiler with, which additional libraries to link the program with, and a few options specific to C Server Page programs.

As ccod will cache compiled binaries, your source code is not compiled every time you execute it. Of course, my little tweak to the cksum function is not thoroughly tested and may break the caching. The problem seemed to be that the variable s was getting values that were too large, so I changed the data type. Another solution might be to poach a different checksum function to replace the cksum implementation completely.

If you have an existing C or C++ code base and want to expose part of its functionality to the Web for prototyping, C Cod might be just the ticket. For simple code, compile, run test cycles C Cod can help you avoid always having to create makefiles or worry about the compilation process at all.

Category:

  • C/C++