Previous week Up Next week


Here is the latest Caml Weekly News, for the week of July 04 to 11, 2006.

  1. A global exception handler...
  2. "Hello web" please
  3. in and out channels into memory

A global exception handler...


Jonathan Roewen asked, Till Varoquaux suggested, and Nicolas Pouillard answered:
> > Is it possible to register a global exception handler? 

> > I suppose I could just nest everything inside one giant function if I 
> > really had to, but I like my toplevel expressions ;-) 

> CamlP4 might come in handy here. I'm guessing you could rewrite your 
> program so that all your toplevel expressions are in one main () 
> function using camlp4. It would have some limitations though: for 
> instance your exception handler could not use anything defined in main 
> (unless you where using references). I'm guessing it's not so bad 
> because whatever happens you cannot have a global exception handler 
> relying to much on stuff defined in your programm. 

Here is a simple Camlp4 filter that written for the new Camlp4 version (CVS) : 
$ cat 
open Camlp4.PreCast; 

value ghost = Loc.ghost; 

value global_handler_ref = ref <:expr@ghost<>>; 

value find_global_handler = object 
  inherit as super; 
  method str_item st = do { 
    match st with 
    [ <:str_item< value global_handler = $f$ >> -> global_handler_ref.val := f 
    | _ -> () ]; 
    super#str_item st 

  (fun st -> 
    let _ = find_global_handler#str_item st in 
    <:str_item@ghost< try let module Main = struct $st$ end in () 
                      with e -> $global_handler_ref.val$ e >>); 

$ ocamlc -I +camlp4 -c -pp camlp4rf 

$ cat 
open Format;; 
let f1 x = printf "f1 %d@." x;; 
let f2 x = printf "f2 %f@." x;; 
let f3 x = printf "f3 %s@." x;; 
f1 1;; 
f2 1.1;; 
f3 "1.1.1";; 
raise (Failure "test");; 
let global_handler e = 
  (* Note that I need to give the complete name for eprintf since 
     Format is not opened in the new environment of global_handler. *) 
  Format.eprintf "global_handler: %s@." (Printexc.to_string e) 

$ ocamlc -pp 'camlp4o global_handler.cmo' 

$ ./a.out 
f1 1 
f2 1.100000 
f3 1.1.1 
global_handler: Failure("test") 

$ camlp4o global_handler.cmo -printer OCaml 
  let module Main = 
      open Format 
      let f1 x = printf "f1 %d@." x 
      let f2 x = printf "f2 %f@." x 
      let f3 x = printf "f3 %s@." x 
      let _ = f1 1 
      let _ = f2 1.1 
      let _ = f3 "1.1.1" 
      let _ = raise (Failure "test") 
      let global_handler e = 
        (* Note that I need to give the complete name for eprintf since 
     Format is not opened in the new environment of global_handler. *) 
        Format.eprintf "global_handler: %s@." (Printexc.to_string e) 
  in () 
| e -> 
    (fun e -> Format.eprintf "global_handler: %s@." (Printexc.to_string e)) e 
Jonathan Roewen asked and Nicolas Pouillard answered:
> Ah, defining a module inside a function is a neat trick! I didn't 
> think of that. Well, I guess it couldn't hurt to do that with all the 
> modules which could cause trouble at runtime... 

> Can I build the new camlp4 with 3.09.2 tools? 

In fact camlp4 will be part of OCaml 3.10 distribution, so it's better 
to try it directly like that, instead of mixing them with 3.09.2. 

"Hello web" please


Jonathan Hayward asked and Christophe TROESTLER answered:
> I'm trying to figure out how to use CamlGI with OCaml, [...] 

CamlGI code has been integrated into the Netcgi component 
of OcamlNet-2, please use 
that instead. 
> [...] script that [...] prints a webpage saying only "Yes", "No", 
> "Other" or "Undefined" depending on whether the CGI variable "foo" 
> has value 1, 0, some other defined value, or is undefined (never 
> mind about multiple values)? 

You can find examples in the examples/ directory ( is a very 
simple one).  As for the specific example you desire, it is attached. 
It is maybe a bit more complex that you expected because it 
demonstrates additional features (text escaping, setting the header, 
buffered output). 
Hope it helps, 

[ ] 
open Netcgi 

let text = Netencoding.Html.encode_from_latin1 
  (* This function encodes "<", ">", "&", double quotes, and Latin 1 
     characters as character entities.  E.g. text "<" = "&lt;", and 
     text "ä" = "&auml;" *) 

(* Normally you would use a template system instead of this *) 
let html_page (cgi:cgi) title html = 
  let out = cgi#out_channel#output_string in 
  out "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \ 
  out ("<html>\n<head><title>" ^ text title ^"</title></head> 
  out html; 
  out "</body>\n</html>" 

let main (cgi:cgi) = 
    ~content_type:"text/html; charset=\"iso-8859-1\"" 
  let foo = cgi#argument_value "foo" 
  let html = match foo with 
    | "1" -> "Yes" 
    | "0" -> "No" 
    | _ -> "Undefined" in 
  html_page cgi foo html 

(* You can buffer or not the output.  If buffered you can rollback 
   (useful in case of error). You can replace by 
   another connector entry point (FCGI, SCGI, AJP, Apache mod). *) 
let () = 
  let buffered _ ch = new Netchannels.buffered_trans_channel ch in ~output_type:(`Transactional buffered) main 
Jonathan Hayward then asked and Christophe TROESTLER answered:
> I've been urged to use Netcgi from OcamlNet-2 from 
> . 

Ok.  I was pointing you to the subversion repository so you can browse 
the files and see whether that is what you need.  You can download the 
files with 
  svn co lib-ocamlnet2 

> When I tried to configure OcamlNet2 it said it needed PCRE -- and even 
> though I installed what was labelled as PCRE from 
> , OcamlNet-2 refused 
> to configure because it couldn't recognize PCRE as being installed, and when 
> I commented out the test for PCRE in the configure it still couldn't find 
> it. 

You need the OCaml interface to the C library.  Get it here: 

in and out channels into memory


Jim Miller asked and Richard Jones answered:
> Is there a way in OCaml to read and write into memory using in and out 
> channels in the standard distribution?  It seems like there are functions 
> for converting everything else to in and out channels but I can't seem to 
> find anything for writing into and out of memory.  If there isn't something 
> already, is there a function for creating new in and out channels? 

Not for the in/out_channel in the standard distribution. 
However if you can change the code to use the IO class types defined 
here ( then you 
can use something like input_string from the Netstring library: 

 let s = "1\n2\n3\n4" in 
 let ch = new input_string s in 
 ch#input_line () 

If you can't change the code, then the best you can do might be to 
read and write a temporary file (see: Filename.open_temp_file). 

Another alternative from the std lib is Buffer, but that also requires 
changing the code. 

Using folding to read the cwn in vim 6+

Here is a quick trick to help you read this CWN if you are viewing it using vim (version 6 or greater).

:set foldmethod=expr
:set foldexpr=getline(v:lnum)=~'^=\\{78}$'?'&lt;1':1

If you know of a better way, please let me know.

Old cwn

If you happen to miss a CWN, you can send me a message and I'll mail it to you, or go take a look at the archive or the RSS feed of the archives.

If you also wish to receive it every week by mail, you may subscribe online.

Alan Schmitt