>Invoking Green Card

12. Invoking Green Card

The general syntax for invoking Green Card is:

green-card [options] [filename]

Green Card reads from standard input if no filename is given. The options can be any of those:

-?, -h, --help

Print a usage message listing all available options, then exit successfully.

-V, --version

Print the version number, then exit successfully.

-v, --verbose

Print more information while processing the input.

-d, --debug

Output extra debug information.

-i <directories>, --include-dir=<directories>

Search the directories named in the colon (:) separated list for imported files. The directories will be searched in a left to right order.

-s <sufs>, --suffix=<sufs>

When searching, use colon separated list of source file suffixes (standard: no suffix or .gc)

-t <target>, --target=<target>

Generate Haskell code for a particular system. Targets currently supported: ghc, hugs, nhc, and ffi. You're encouraged to use the ffi target, since the Haskell output it generates can be used with all Haskell systems that support the common FFI (as of June 2001, all of them).

-S, --safe-code

Generates code that can use callbacks to Haskell (GHC only.) This makes the generated code slower (but safer!). See Section 7.2 for details.

-n, --no-inline

Put C code in a separate file (GHC target only.)

-4, --haskell1.4

Generate Haskell 1.4 compatible instead of Haskell 98.

-m <scheme>, --name-mangling-scheme=<scheme>

Control how you mangle external names into Haskell ones. Schemes currently supported: std and classic. The default is std mangling, which will just change the casing of the first character:

A_STD_EXAMPLE   
   ==>  a_STD_EXAMPLE  (variable case)
   ==>  A_STD_EXAMPLE  (datacon  case)

The classic name mangling scheme removes underscores and upper-cases each word, i.e.:

A_CLASSIC_EXAMPLE   
   ==>  aClassicExample  (variable case)
   ==>  AClassicExample  (datacon  case)
--stub-debug

Include debugging code in generated code.

--dll-name

Generate ``foreign imports'' to dynamic library DLL (FFI backend only).

--callconv

Use specific calling convention (stdcall or ccall).

12.1. Green Card output

Green Card will create one or more output files when running. The following options control where the output goes:

-o <file>, --output=<file>

where to put generated Haskell file.

-c <file>, --output-c=<file>

where to put generated C file (if any header files are generated, they'll go in (dropSuffix file ++ ".h").

-p <pre>, --output-prefix=<pre>

Use <prefix> as stem when generating output filenames that haven't been specificed directly, i.e., using -p Right, the Haskell and C output will be output in Right.hs and Right.c, respectively.

If none of the above output options are used, the name of the output files are constructed from the name of the input file. The filename suffix is dropped and the appropriate suffix is appended, e.g., running Green Card on foo.gc will create a Haskell file called foo.hs.

12.2. Debugging Green Card output

ToDo: add more debugging tips.

When working with GHC, a commonly occurring problem for Green Card generated code is that of functions being called unsafely when they should have been called safely. The manifestation of this is as an almighty crash. To help debug this, Green Card supports the option --stub-debug which will emit debug code into the generated code. For instance, for the following procedure specification:

%fun Foo :: Int -> IO Int
%code Foo(arg1)

It will generate something like this:

foo :: Int -> IO Int
foo arg1 =
  _casm_ ``do {int arg1;int res1;
               arg1 = %0;
               __current_fun__ = "foo";
               do { Foo(arg1);
                   %r = (int)(res1);} while(0);} while(0);'' arg1
  >>= \  res1  ->
  (return (res1))

On top of the normal boilerplate gubbins, the variable __current_fun__ is assigned (Green Card doesn't define this variable, so you'll have to define it yourself.) Using __current_fun__, it is possible to catch unsafe calls that really should have been safe. Here's how a Win32 library catches this condition in the (C wrapper) for its Haskell callback:

char* __current_fun__ = NULL;

...
#if defined(DEBUG)
   extern int inCCallGC;
   if (inCCallGC == 0) {
      fprintf(stderr,
              "Warning: unsafe ccall %s invokes Haskell callback\n",
              __current_fun__);
   }
#endif

The variable inCCallGC is defined by the GHC RTS, and its value is equal to the number of safe calls currently executing. (PS: The above code doesn't catch all erroneous cases.)