[cwn] Attn: Development Editor, Latest Caml Weekly News

Alan Schmitt alan.schmitt at polytechnique.org
Tue Jul 11 00:35:47 PDT 2006


Hello,

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

========================================================================
1) A global exception handler...
Archive: <http://groups.google.com/group/fa.caml/browse_thread/thread/ 
45fbdd2e388b6b4f/c02a6e728f30451c#c02a6e728f30451c>
------------------------------------------------------------------------
** 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 global_handler.ml
open Camlp4.PreCast;

value ghost = Loc.ghost;

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

value find_global_handler = object
   inherit Ast.map 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
   };
end;

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

$ ocamlc -I +camlp4 -c -pp camlp4rf global_handler.ml

$ cat global_handler_test.ml
open Format;;
let f1 x = printf "f1 %d at ." x;;
let f2 x = printf "f2 %f at ." x;;
let f3 x = printf "f3 %s at ." 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 at ." (Printexc.to_string e)

$ ocamlc -pp 'camlp4o global_handler.cmo' global_handler_test.ml

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

$ camlp4o global_handler.cmo -printer OCaml global_handler_test.ml
try
   let module Main =
     struct
       open Format
       let f1 x = printf "f1 %d at ." x
       let f2 x = printf "f2 %f at ." x
       let f3 x = printf "f3 %s at ." 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 at ." (Printexc.to_string e)
     end
   in ()
with
| e ->
     (fun e -> Format.eprintf "global_handler: % 
s at ." (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.

========================================================================
2) "Hello web" please
Archive: <http://groups.google.com/group/fa.caml/browse_thread/thread/ 
b7f086eb86e92d7d/a6d4126e2473ed53#a6d4126e2473ed53>
------------------------------------------------------------------------
** 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
<https://gps.dynxs.de/wwwsvn/trunk/code/src/netcgi/?root=lib-ocamlnet2>
of OcamlNet-2 <https://gps.dynxs.de/openapps/svnindex.cgi>, 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 (add.ml 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,
ChriS

[   hello.ml ]
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\" \
         \"<http://www.w3.org/TR/REC-html40/strict.dtd>\">\n";
   out ("<html>\n<head><title>" ^ text title ^"</title></head>
<body>\n");
   out html;
   out "</body>\n</html>"

let main (cgi:cgi) =
   cgi#set_header
     ~cache:`No_cache
     ~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 Netcgi_cgi.run by
    another connector entry point (FCGI, SCGI, AJP, Apache mod). *)
let () =
   let buffered _ ch = new Netchannels.buffered_trans_channel ch in
   Netcgi_cgi.run ~output_type:(`Transactional buffered) main

** Jonathan Hayward then asked and Christophe TROESTLER answered:

 > I've been urged to use Netcgi from OcamlNet-2 from
 > <http://www.ocaml-programming.de/packages/ocamlnet-2.2test2.tar.gz> .

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 <https://gps.dynxs.de/svn/lib-ocamlnet2/trunk/> lib-ocamlnet2

 > When I tried to configure OcamlNet2 it said it needed PCRE -- and  
even
 > though I installed what was labelled as PCRE from
 > <ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/> ,  
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:
         <http://ocaml.info/home/ocaml_sources.html#toc13>

========================================================================
3) in and out channels into memory
Archive: <http://groups.google.com/group/fa.caml/browse_thread/thread/ 
a51bfd3a3691d587/db3a36d648594394#db3a36d648594394>
------------------------------------------------------------------------
** 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 (<http://www.ocaml-programming.de/rec/IO-Classes.html>) 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}$'?'<1':1
zM
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
(alan.schmitt at polytechnique.org) and I'll mail it to you, or go take  
a look at
the archive (<http://alan.petitepomme.net/cwn/>) or the RSS feed of the
archives (<http://alan.petitepomme.net/cwn/cwn.rss>). If you also wish
to receive it every week by mail, you may subscribe online at
<http://lists.idyll.org/listinfo/caml-news-weekly/> .

========================================================================

-- 
Alan Schmitt <http://alan.petitepomme.net/>

The hacker: someone who figured things out and made something cool  
happen.
.O.
..O
OOO


-------------- next part --------------
A non-text attachment was scrubbed...
Name: PGP.sig
Type: application/pgp-signature
Size: 186 bytes
Desc: This is a digitally signed message part
Url : http://lists.idyll.org/pipermail/caml-news-weekly/attachments/20060711/544c58b8/PGP.bin


More information about the caml-news-weekly mailing list