<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Richard WM Jones &#187; ocaml</title>
	<atom:link href="http://rwmj.wordpress.com/tag/ocaml/feed/" rel="self" type="application/rss+xml" />
	<link>http://rwmj.wordpress.com</link>
	<description>Virtualization, tools and tips</description>
	<lastBuildDate>Tue, 21 May 2013 09:38:50 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='rwmj.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>Richard WM Jones &#187; ocaml</title>
		<link>http://rwmj.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://rwmj.wordpress.com/osd.xml" title="Richard WM Jones" />
	<atom:link rel='hub' href='http://rwmj.wordpress.com/?pushpress=hub'/>
		<item>
		<title>More static analysis with CIL</title>
		<link>http://rwmj.wordpress.com/2013/02/07/more-static-analysis-with-cil/</link>
		<comments>http://rwmj.wordpress.com/2013/02/07/more-static-analysis-with-cil/#comments</comments>
		<pubDate>Thu, 07 Feb 2013 18:18:35 +0000</pubDate>
		<dc:creator>rich</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[cil]]></category>
		<category><![CDATA[libguestfs]]></category>
		<category><![CDATA[libvirt]]></category>
		<category><![CDATA[ocaml]]></category>
		<category><![CDATA[static analysis]]></category>
		<category><![CDATA[virt-tools]]></category>

		<guid isPermaLink="false">http://rwmj.wordpress.com/?p=4163</guid>
		<description><![CDATA[Years ago I played around with CIL to analyze libvirt. More recently Dan used CIL to analyze libvirt&#8217;s locking code. We didn&#8217;t get so far either time, but I&#8217;ve been taking a deeper look at CIL in an attempt to &#8230; <a href="http://rwmj.wordpress.com/2013/02/07/more-static-analysis-with-cil/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rwmj.wordpress.com&#038;blog=6840703&#038;post=4163&#038;subd=rwmj&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Years ago I <a href="http://people.redhat.com/~rjones/cil-analysis-of-libvirt/">played around</a> with <a href="http://www.cs.berkeley.edu/~necula/cil/">CIL</a> to analyze <a href="http://libvirt.org">libvirt</a>.  More recently <a href="https://rwmj.wordpress.com/2009/05/15/dan-uses-ocaml-cil-to-analyze-libvirts-locking-patterns/">Dan used CIL to analyze libvirt&#8217;s locking code</a>.</p>
<p>We didn&#8217;t get so far either time, but I&#8217;ve been taking a deeper look at CIL in an attempt to verify error handling in <a href="http://libguestfs.org/">libguestfs</a>.</p>
<p>Here is my partly working code so far.</p>
<pre>
<tt><i><font color="#9A1900">(*</font></i>
<i><font color="#9A1900"> * Analyse libguestfs APIs to find error overwriting.</font></i>
<i><font color="#9A1900"> * Copyright (C) 2008-2013 Red Hat, Inc.</font></i>
<i><font color="#9A1900"> *</font></i>
<i><font color="#9A1900"> * This library is free software; you can redistribute it and/or</font></i>
<i><font color="#9A1900"> * modify it under the terms of the GNU Lesser General Public</font></i>
<i><font color="#9A1900"> * License as published by the Free Software Foundation; either</font></i>
<i><font color="#9A1900"> * version 2.1 of the License, or (at your option) any later version.</font></i>
<i><font color="#9A1900"> *</font></i>
<i><font color="#9A1900"> * This library is distributed in the hope that it will be useful,</font></i>
<i><font color="#9A1900"> * but WITHOUT ANY WARRANTY; without even the implied warranty of</font></i>
<i><font color="#9A1900"> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU</font></i>
<i><font color="#9A1900"> * Lesser General Public License for more details.</font></i>
<i><font color="#9A1900"> *</font></i>
<i><font color="#9A1900"> * You should have received a copy of the GNU Lesser General Public</font></i>
<i><font color="#9A1900"> * License along with this library.  If not, see</font></i>
<i><font color="#9A1900"> * &lt;http://www.gnu.org/licenses/&gt;.</font></i>
<i><font color="#9A1900"> *</font></i>
<i><font color="#9A1900"> * Author: Daniel P. Berrange &lt;berrange@redhat.com&gt;</font></i>
<i><font color="#9A1900"> * Author: Richard W.M. Jones &lt;rjones@redhat.com&gt;</font></i>
<i><font color="#9A1900"> *)</font></i>

<b><font color="#000080">open</font></b> <font color="#009900">Unix</font>
<b><font color="#000080">open</font></b> <font color="#009900">Printf</font>

<b><font color="#000080">open</font></b> <font color="#009900">Cil</font>

<b><font color="#0000FF">let</font></b> debug <font color="#990000">=</font> <font color="#009900">ref</font> <b><font color="#0000FF">false</font></b>

<i><font color="#9A1900">(* Set of ints. *)</font></i>
<b><font color="#0000FF">module</font></b> <font color="#009900">IntSet</font> <font color="#990000">=</font> <b><font color="#000080">Set</font></b><font color="#990000">.</font><font color="#009900">Make</font> <font color="#990000">(</font><b><font color="#0000FF">struct</font></b> <b><font color="#0000FF">type</font></b> t <font color="#990000">=</font> <font color="#009900">int</font> <b><font color="#0000FF">let</font></b> compare <font color="#990000">=</font> compare <b><font color="#0000FF">end</font></b><font color="#990000">)</font>

<i><font color="#9A1900">(* A module for storing any set (unordered list) of functions. *)</font></i>
<b><font color="#0000FF">module</font></b> <font color="#009900">FunctionSet</font> <font color="#990000">=</font> <b><font color="#000080">Set</font></b><font color="#990000">.</font><font color="#009900">Make</font> <font color="#990000">(</font>
  <b><font color="#0000FF">struct</font></b>
    <b><font color="#0000FF">type</font></b> t <font color="#990000">=</font> varinfo
    <b><font color="#0000FF">let</font></b> compare v1 v2 <font color="#990000">=</font> compare v1<font color="#990000">.</font>vid v2<font color="#990000">.</font>vid
  <b><font color="#0000FF">end</font></b>
<font color="#990000">)</font>

<i><font color="#9A1900">(* Directed graph of functions.</font></i>
<i><font color="#9A1900"> *</font></i>
<i><font color="#9A1900"> * Function = a node in the graph</font></i>
<i><font color="#9A1900"> * FunctionDigraph = the directed graph</font></i>
<i><font color="#9A1900"> * FunctionPathChecker = path checker module using Dijkstra's algorithm</font></i>
<i><font color="#9A1900"> *)</font></i>
<b><font color="#0000FF">module</font></b> <font color="#009900">Function</font> <font color="#990000">=</font>
<b><font color="#0000FF">struct</font></b>
  <b><font color="#0000FF">type</font></b> t <font color="#990000">=</font> varinfo
  <b><font color="#0000FF">let</font></b> compare f1 f2 <font color="#990000">=</font> compare f1<font color="#990000">.</font>vid f2<font color="#990000">.</font>vid
  <b><font color="#0000FF">let</font></b> hash f <font color="#990000">=</font> <b><font color="#000080">Hashtbl</font></b><font color="#990000">.</font>hash f<font color="#990000">.</font>vid
  <b><font color="#0000FF">let</font></b> equal f1 f2 <font color="#990000">=</font> f1<font color="#990000">.</font>vid <font color="#990000">=</font> f2<font color="#990000">.</font>vid
<b><font color="#0000FF">end</font></b>
<b><font color="#0000FF">module</font></b> <font color="#009900">FunctionDigraph</font> <font color="#990000">=</font> <b><font color="#000080">Graph</font></b><font color="#990000">.</font><b><font color="#000080">Imperative</font></b><font color="#990000">.</font><b><font color="#000080">Digraph</font></b><font color="#990000">.</font><font color="#009900">Concrete</font> <font color="#990000">(</font><font color="#009900">Function</font><font color="#990000">)</font>
<b><font color="#0000FF">module</font></b> <font color="#009900">FunctionPathChecker</font> <font color="#990000">=</font> <b><font color="#000080">Graph</font></b><font color="#990000">.</font><b><font color="#000080">Path</font></b><font color="#990000">.</font><font color="#009900">Check</font> <font color="#990000">(</font><font color="#009900">FunctionDigraph</font><font color="#990000">)</font>

<i><font color="#9A1900">(* Module used to analyze the paths through each function. *)</font></i>
<b><font color="#0000FF">module</font></b> <font color="#009900">ErrorCounter</font> <font color="#990000">=</font>
<b><font color="#0000FF">struct</font></b>
  <b><font color="#0000FF">let</font></b> name <font color="#990000">=</font> <font color="#FF0000">"ErrorCounter"</font>
  <b><font color="#0000FF">let</font></b> debug <font color="#990000">=</font> debug

  <i><font color="#9A1900">(* Our current state is very simple, just the number of error</font></i>
<i><font color="#9A1900">   * function calls did encountered up to this statement.</font></i>
<i><font color="#9A1900">   *)</font></i>
  <b><font color="#0000FF">type</font></b> t <font color="#990000">=</font> <font color="#009900">int</font>

  <b><font color="#0000FF">let</font></b> copy errcalls <font color="#990000">=</font> errcalls

  <i><font color="#9A1900">(* Start data for each statement. *)</font></i>
  <b><font color="#0000FF">let</font></b> stmtStartData <font color="#990000">=</font> <b><font color="#000080">Inthash</font></b><font color="#990000">.</font>create <font color="#993399">97</font>

  <b><font color="#0000FF">let</font></b> printable errcalls <font color="#990000">=</font> sprintf <font color="#FF0000">"(errcalls=%d)"</font> errcalls

  <b><font color="#0000FF">let</font></b> pretty <font color="#990000">()</font> t <font color="#990000">=</font> <b><font color="#000080">Pretty</font></b><font color="#990000">.</font>text <font color="#990000">(</font>printable t<font color="#990000">)</font>

  <b><font color="#0000FF">let</font></b> computeFirstPredecessor stmt x <font color="#990000">=</font> x <i><font color="#9A1900">(* XXX??? *)</font></i>

  <b><font color="#0000FF">let</font></b> combinePredecessors stmt <font color="#990000">~</font>old<font color="#990000">:</font>old_t new_t <font color="#990000">=</font>
    <b><font color="#0000FF">if</font></b> old_t <font color="#990000">=</font> new_t <b><font color="#0000FF">then</font></b> <font color="#009900">None</font>
    <b><font color="#0000FF">else</font></b> <font color="#009900">Some</font> new_t

  <i><font color="#9A1900">(* This will be initialized after we have calculated the set of all</font></i>
<i><font color="#9A1900">   * functions which can call an error function, in main() below.</font></i>
<i><font color="#9A1900">   *)</font></i>
  <b><font color="#0000FF">let</font></b> error_functions_set <font color="#990000">=</font> <font color="#009900">ref</font> <b><font color="#000080">FunctionSet</font></b><font color="#990000">.</font>empty

  <i><font color="#9A1900">(* Handle a Cil.Instr. *)</font></i>
  <b><font color="#0000FF">let</font></b> doInstr instr _ <font color="#990000">=</font>
    <b><font color="#0000FF">match</font></b> instr <b><font color="#0000FF">with</font></b>
    <i><font color="#9A1900">(* A call to an error function. *)</font></i>
    <font color="#990000">|</font> <font color="#009900">Call</font> <font color="#990000">(</font>_<font color="#990000">,</font> <font color="#009900">Lval</font> <font color="#990000">(</font><font color="#009900">Var</font> callee<font color="#990000">,</font> _<font color="#990000">),</font> _<font color="#990000">,</font> _<font color="#990000">)</font>
        <b><font color="#0000FF">when</font></b> <b><font color="#000080">FunctionSet</font></b><font color="#990000">.</font>mem callee <font color="#990000">!</font>error_functions_set <font color="#990000">-&gt;</font>
      <b><font color="#000080">Dataflow</font></b><font color="#990000">.</font><font color="#009900">Post</font> <font color="#990000">(</font><b><font color="#0000FF">fun</font></b> errcalls <font color="#990000">-&gt;</font> errcalls<font color="#990000">+</font><font color="#993399">1</font><font color="#990000">)</font>

    <font color="#990000">|</font> _ <font color="#990000">-&gt;</font> <b><font color="#000080">Dataflow</font></b><font color="#990000">.</font><font color="#009900">Default</font>

  <i><font color="#9A1900">(* Handle a Cil.Stmt. *)</font></i>
  <b><font color="#0000FF">let</font></b> doStmt _ _ <font color="#990000">=</font> <b><font color="#000080">Dataflow</font></b><font color="#990000">.</font><font color="#009900">SDefault</font>

  <i><font color="#9A1900">(* Handle a Cil.Guard. *)</font></i>
  <b><font color="#0000FF">let</font></b> doGuard _ _ <font color="#990000">=</font> <b><font color="#000080">Dataflow</font></b><font color="#990000">.</font><font color="#009900">GDefault</font>

  <i><font color="#9A1900">(* Filter statements we've seen already to prevent loops. *)</font></i>
  <b><font color="#0000FF">let</font></b> filter_set <font color="#990000">=</font> <font color="#009900">ref</font> <b><font color="#000080">IntSet</font></b><font color="#990000">.</font>empty
  <b><font color="#0000FF">let</font></b> filterStmt <font color="#FF0000">{</font> sid <font color="#990000">=</font> sid <font color="#FF0000">}</font> <font color="#990000">=</font>
    <b><font color="#0000FF">if</font></b> <b><font color="#000080">IntSet</font></b><font color="#990000">.</font>mem sid <font color="#990000">!</font>filter_set <b><font color="#0000FF">then</font></b> <b><font color="#0000FF">false</font></b>
    <b><font color="#0000FF">else</font></b> <font color="#990000">(</font>
      filter_set <font color="#990000">:=</font> <b><font color="#000080">IntSet</font></b><font color="#990000">.</font>add sid <font color="#990000">!</font>filter_set<font color="#990000">;</font>
      <b><font color="#0000FF">true</font></b>
    <font color="#990000">)</font>

  <i><font color="#9A1900">(* Initialize the module before each function that we examine. *)</font></i>
  <b><font color="#0000FF">let</font></b> init stmts <font color="#990000">=</font>
    filter_set <font color="#990000">:=</font> <b><font color="#000080">IntSet</font></b><font color="#990000">.</font>empty<font color="#990000">;</font>
    <b><font color="#000080">Inthash</font></b><font color="#990000">.</font>clear stmtStartData<font color="#990000">;</font>
    <i><font color="#9A1900">(* Add the initial statement(s) to the hash. *)</font></i>
    <b><font color="#000080">List</font></b><font color="#990000">.</font>iter <font color="#990000">(</font><b><font color="#0000FF">fun</font></b> stmt <font color="#990000">-&gt;</font> <b><font color="#000080">Inthash</font></b><font color="#990000">.</font>add stmtStartData stmt<font color="#990000">.</font>sid <font color="#993399">0</font><font color="#990000">)</font> stmts
<b><font color="#0000FF">end</font></b>

<b><font color="#0000FF">module</font></b> <font color="#009900">ForwardsErrorCounter</font> <font color="#990000">=</font> <b><font color="#000080">Dataflow</font></b><font color="#990000">.</font><font color="#009900">ForwardsDataFlow</font> <font color="#990000">(</font><font color="#009900">ErrorCounter</font><font color="#990000">)</font>

<i><font color="#9A1900">(* The always useful filter + map function. *)</font></i>
<b><font color="#0000FF">let</font></b> <b><font color="#0000FF">rec</font></b> filter_map f <font color="#990000">=</font> <b><font color="#0000FF">function</font></b>
  <font color="#990000">|</font> <font color="#990000">[]</font> <font color="#990000">-&gt;</font> <font color="#990000">[]</font>
  <font color="#990000">|</font> x <font color="#990000">::</font> xs <font color="#990000">-&gt;</font>
      <b><font color="#0000FF">match</font></b> f x <b><font color="#0000FF">with</font></b>
      <font color="#990000">|</font> <font color="#009900">Some</font> y <font color="#990000">-&gt;</font> y <font color="#990000">::</font> filter_map f xs
      <font color="#990000">|</font> <font color="#009900">None</font> <font color="#990000">-&gt;</font> filter_map f xs

<b><font color="#0000FF">let</font></b> <b><font color="#0000FF">rec</font></b> main <font color="#990000">()</font> <font color="#990000">=</font>
  <i><font color="#9A1900">(* Read the list of input C files. *)</font></i>
  <b><font color="#0000FF">let</font></b> files <font color="#990000">=</font>
    <b><font color="#0000FF">let</font></b> chan <font color="#990000">=</font> open_process_in <font color="#FF0000">"find src -name '*.i' | sort"</font> <b><font color="#0000FF">in</font></b>
    <b><font color="#0000FF">let</font></b> files <font color="#990000">=</font> input_chan chan <b><font color="#0000FF">in</font></b>
    <b><font color="#0000FF">if</font></b> close_process_in chan <font color="#990000">&lt;&gt;</font> <font color="#009900">WEXITED</font> <font color="#993399">0</font> <b><font color="#0000FF">then</font></b>
      failwith <font color="#FF0000">"failed to read input list of files"</font><font color="#990000">;</font>
    <b><font color="#0000FF">if</font></b> files <font color="#990000">=</font> <font color="#990000">[]</font> <b><font color="#0000FF">then</font></b>
      failwith <font color="#FF0000">"no input files; is the program running from the top directory? did you compile with make -C src CFLAGS=\"-save-temps\"?"</font><font color="#990000">;</font>
    files <b><font color="#0000FF">in</font></b>

  <i><font color="#9A1900">(* Load and parse each input file. *)</font></i>
  <b><font color="#0000FF">let</font></b> files <font color="#990000">=</font>
    <b><font color="#000080">List</font></b><font color="#990000">.</font>map <font color="#990000">(</font>
      <b><font color="#0000FF">fun</font></b> filename <font color="#990000">-&gt;</font>
        printf <font color="#FF0000">"loading %s\n%!"</font> filename<font color="#990000">;</font>
        <b><font color="#000080">Frontc</font></b><font color="#990000">.</font>parse filename <font color="#990000">()</font>
    <font color="#990000">)</font> files <b><font color="#0000FF">in</font></b>

  <i><font color="#9A1900">(* Merge the files. *)</font></i>
  printf <font color="#FF0000">"merging files\n%!"</font><font color="#990000">;</font>
  <b><font color="#0000FF">let</font></b> sourcecode <font color="#990000">=</font> <b><font color="#000080">Mergecil</font></b><font color="#990000">.</font>merge files <font color="#FF0000">"libguestfs"</font> <b><font color="#0000FF">in</font></b>

  <i><font color="#9A1900">(* CFG analysis. *)</font></i>
  printf <font color="#FF0000">"computing control flow\n%!"</font><font color="#990000">;</font>
  <b><font color="#000080">Cfg</font></b><font color="#990000">.</font>computeFileCFG sourcecode<font color="#990000">;</font>

  <b><font color="#0000FF">let</font></b> functions <font color="#990000">=</font>
    filter_map <font color="#990000">(</font><b><font color="#0000FF">function</font></b> <font color="#009900">GFun</font> <font color="#990000">(</font>f<font color="#990000">,</font> loc<font color="#990000">)</font> <font color="#990000">-&gt;</font> <font color="#009900">Some</font> <font color="#990000">(</font>f<font color="#990000">,</font> loc<font color="#990000">)</font> <font color="#990000">|</font> _ <font color="#990000">-&gt;</font> <font color="#009900">None</font><font color="#990000">)</font>
      sourcecode<font color="#990000">.</font>globals <b><font color="#0000FF">in</font></b>

  <i><font color="#9A1900">(* Examine which functions directly call which other functions. *)</font></i>
  printf <font color="#FF0000">"computing call graph\n%!"</font><font color="#990000">;</font>
  <b><font color="#0000FF">let</font></b> call_graph <font color="#990000">=</font> make_call_graph functions <b><font color="#0000FF">in</font></b>
  <i><font color="#9A1900">(*</font></i>
<i><font color="#9A1900">  FunctionDigraph.iter_edges (</font></i>
<i><font color="#9A1900">    fun caller callee -&gt;</font></i>
<i><font color="#9A1900">      printf "%s calls %s\n" caller.vname callee.vname</font></i>
<i><font color="#9A1900">  ) call_graph;</font></i>
<i><font color="#9A1900">  *)</font></i>

  <i><font color="#9A1900">(* The libguestfs error functions.  These are global function names,</font></i>
<i><font color="#9A1900">   * but to be any use to us we have to look these up in the list of</font></i>
<i><font color="#9A1900">   * all global functions (ie. 'functions') and turn them into the</font></i>
<i><font color="#9A1900">   * corresponding varinfo structures.</font></i>
<i><font color="#9A1900">   *)</font></i>
  <b><font color="#0000FF">let</font></b> error_function_names <font color="#990000">=</font> <font color="#990000">[</font> <font color="#FF0000">"guestfs_error_errno"</font><font color="#990000">;</font>
                               <font color="#FF0000">"guestfs_perrorf"</font> <font color="#990000">]</font> <b><font color="#0000FF">in</font></b>

  <b><font color="#0000FF">let</font></b> find_function name <font color="#990000">=</font>
    <b><font color="#0000FF">try</font></b> <b><font color="#000080">List</font></b><font color="#990000">.</font>find <font color="#990000">(</font><b><font color="#0000FF">fun</font></b> <font color="#990000">(</font><font color="#FF0000">{</font> svar <font color="#990000">=</font> <font color="#FF0000">{</font> vname <font color="#990000">=</font> n <font color="#FF0000">}}</font><font color="#990000">,</font> _<font color="#990000">)</font> <font color="#990000">-&gt;</font> n <font color="#990000">=</font> name<font color="#990000">)</font> functions
    <b><font color="#0000FF">with</font></b> <font color="#009900">Not_found</font> <font color="#990000">-&gt;</font> failwith <font color="#990000">(</font><font color="#FF0000">"function '"</font> <font color="#990000">^</font> name <font color="#990000">^</font> <font color="#FF0000">"' does not exist"</font><font color="#990000">)</font>
  <b><font color="#0000FF">in</font></b>
  <b><font color="#0000FF">let</font></b> error_function_names <font color="#990000">=</font> <b><font color="#000080">List</font></b><font color="#990000">.</font>map <font color="#990000">(</font>
    <b><font color="#0000FF">fun</font></b> f <font color="#990000">-&gt;</font> <font color="#990000">(</font>fst <font color="#990000">(</font>find_function f<font color="#990000">)).</font>svar
  <font color="#990000">)</font> error_function_names <b><font color="#0000FF">in</font></b>

  <i><font color="#9A1900">(* Get a list of functions that might (directly or indirectly) call</font></i>
<i><font color="#9A1900">   * one of the error functions.</font></i>
<i><font color="#9A1900">   *)</font></i>
  <b><font color="#0000FF">let</font></b> error_functions<font color="#990000">,</font> non_error_functions <font color="#990000">=</font>
    functions_which_call call_graph error_function_names functions <b><font color="#0000FF">in</font></b>

  <i><font color="#9A1900">(*</font></i>
<i><font color="#9A1900">  List.iter (</font></i>
<i><font color="#9A1900">    fun f -&gt; printf "%s can call an error function\n" f.vname</font></i>
<i><font color="#9A1900">  ) error_functions;</font></i>

<i><font color="#9A1900">  List.iter (</font></i>
<i><font color="#9A1900">    fun f -&gt; printf "%s can NOT call an error function\n" f.vname</font></i>
<i><font color="#9A1900">  ) non_error_functions;</font></i>
<i><font color="#9A1900">  *)</font></i>

  <i><font color="#9A1900">(* Save the list of error functions in a global set for fast lookups. *)</font></i>
  <b><font color="#0000FF">let</font></b> set <font color="#990000">=</font>
    <b><font color="#000080">List</font></b><font color="#990000">.</font>fold_left <font color="#990000">(</font>
      <b><font color="#0000FF">fun</font></b> set elt <font color="#990000">-&gt;</font> <b><font color="#000080">FunctionSet</font></b><font color="#990000">.</font>add elt set
    <font color="#990000">)</font> <b><font color="#000080">FunctionSet</font></b><font color="#990000">.</font>empty error_functions <b><font color="#0000FF">in</font></b>
  <b><font color="#000080">ErrorCounter</font></b><font color="#990000">.</font>error_functions_set <font color="#990000">:=</font> set<font color="#990000">;</font>

  <i><font color="#9A1900">(* Analyze each top-level function to ensure it calls an error</font></i>
<i><font color="#9A1900">   * function exactly once on error paths, and never on normal return</font></i>
<i><font color="#9A1900">   * paths.</font></i>
<i><font color="#9A1900">   *)</font></i>
  printf <font color="#FF0000">"analyzing correctness of error paths\n%!"</font><font color="#990000">;</font>
  <b><font color="#000080">List</font></b><font color="#990000">.</font>iter compute_error_paths functions<font color="#990000">;</font>

  <font color="#990000">()</font>

<i><font color="#9A1900">(* Make a directed graph of which functions directly call which other</font></i>
<i><font color="#9A1900"> * functions.</font></i>
<i><font color="#9A1900"> *)</font></i>
<b><font color="#0000FF">and</font></b> make_call_graph functions <font color="#990000">=</font>
  <b><font color="#0000FF">let</font></b> graph <font color="#990000">=</font> <b><font color="#000080">FunctionDigraph</font></b><font color="#990000">.</font>create <font color="#990000">()</font> <b><font color="#0000FF">in</font></b>

  <b><font color="#000080">List</font></b><font color="#990000">.</font>iter <font color="#990000">(</font>
    <b><font color="#0000FF">fun</font></b> <font color="#990000">(</font><font color="#FF0000">{</font> svar <font color="#990000">=</font> caller<font color="#990000">;</font> sallstmts <font color="#990000">=</font> sallstmts <font color="#FF0000">}</font><font color="#990000">,</font> _<font color="#990000">)</font> <font color="#990000">-&gt;</font>
      <i><font color="#9A1900">(* Evaluate which other functions 'caller' calls.  First pull</font></i>
<i><font color="#9A1900">       * out every 'Call' instruction anywhere in the function.</font></i>
<i><font color="#9A1900">       *)</font></i>
      <b><font color="#0000FF">let</font></b> insns <font color="#990000">=</font>  <b><font color="#000080">List</font></b><font color="#990000">.</font>concat <font color="#990000">(</font>
        filter_map <font color="#990000">(</font>
          <b><font color="#0000FF">function</font></b>
          <font color="#990000">|</font> <font color="#FF0000">{</font> skind <font color="#990000">=</font> <font color="#009900">Instr</font> insns <font color="#FF0000">}</font> <font color="#990000">-&gt;</font> <font color="#009900">Some</font> insns
          <font color="#990000">|</font> _ <font color="#990000">-&gt;</font> <font color="#009900">None</font>
        <font color="#990000">)</font> sallstmts
      <font color="#990000">)</font> <b><font color="#0000FF">in</font></b>
      <b><font color="#0000FF">let</font></b> calls <font color="#990000">=</font> <b><font color="#000080">List</font></b><font color="#990000">.</font>filter <font color="#990000">(</font><b><font color="#0000FF">function</font></b> <font color="#009900">Call</font> _ <font color="#990000">-&gt;</font> <b><font color="#0000FF">true</font></b> <font color="#990000">|</font> _ <font color="#990000">-&gt;</font> <b><font color="#0000FF">false</font></b><font color="#990000">)</font> insns <b><font color="#0000FF">in</font></b>
      <i><font color="#9A1900">(* Then examine what function is being called at each place. *)</font></i>
      <b><font color="#0000FF">let</font></b> callees <font color="#990000">=</font> filter_map <font color="#990000">(</font>
        <b><font color="#0000FF">function</font></b>
        <font color="#990000">|</font> <font color="#009900">Call</font> <font color="#990000">(</font>_<font color="#990000">,</font> <font color="#009900">Lval</font> <font color="#990000">(</font><font color="#009900">Var</font> callee<font color="#990000">,</font> _<font color="#990000">),</font> _<font color="#990000">,</font> _<font color="#990000">)</font> <font color="#990000">-&gt;</font> <font color="#009900">Some</font> callee
        <font color="#990000">|</font> _ <font color="#990000">-&gt;</font> <font color="#009900">None</font>
      <font color="#990000">)</font> calls <b><font color="#0000FF">in</font></b>

      <b><font color="#000080">List</font></b><font color="#990000">.</font>iter <font color="#990000">(</font>
        <b><font color="#0000FF">fun</font></b> callee <font color="#990000">-&gt;</font>
          <b><font color="#000080">FunctionDigraph</font></b><font color="#990000">.</font>add_edge graph caller callee
      <font color="#990000">)</font> callees
  <font color="#990000">)</font> functions<font color="#990000">;</font>

  graph

<i><font color="#9A1900">(* [functions_which_call g endpoints functions] partitions the</font></i>
<i><font color="#9A1900"> * [functions] list, returning those functions that call directly or</font></i>
<i><font color="#9A1900"> * indirectly one of the functions in [endpoints], and a separate list</font></i>
<i><font color="#9A1900"> * of functions which do not.  [g] is the direct call graph.</font></i>
<i><font color="#9A1900"> *)</font></i>
<b><font color="#0000FF">and</font></b> functions_which_call g endpoints functions <font color="#990000">=</font>
  <b><font color="#0000FF">let</font></b> functions <font color="#990000">=</font> <b><font color="#000080">List</font></b><font color="#990000">.</font>map <font color="#990000">(</font><b><font color="#0000FF">fun</font></b> <font color="#990000">(</font><font color="#FF0000">{</font> svar <font color="#990000">=</font> svar <font color="#FF0000">}</font><font color="#990000">,</font> _<font color="#990000">)</font> <font color="#990000">-&gt;</font> svar<font color="#990000">)</font> functions <b><font color="#0000FF">in</font></b>

  <b><font color="#0000FF">let</font></b> checker <font color="#990000">=</font> <b><font color="#000080">FunctionPathChecker</font></b><font color="#990000">.</font>create g <b><font color="#0000FF">in</font></b>
  <b><font color="#000080">List</font></b><font color="#990000">.</font>partition <font color="#990000">(</font>
    <b><font color="#0000FF">fun</font></b> f <font color="#990000">-&gt;</font>
      <i><font color="#9A1900">(* Does a path exist from f to any of the endpoints? *)</font></i>
      <b><font color="#000080">List</font></b><font color="#990000">.</font>exists <font color="#990000">(</font>
        <b><font color="#0000FF">fun</font></b> endpoint <font color="#990000">-&gt;</font>
          <b><font color="#0000FF">try</font></b> <b><font color="#000080">FunctionPathChecker</font></b><font color="#990000">.</font>check_path checker f endpoint
          <b><font color="#0000FF">with</font></b>
          <i><font color="#9A1900">(* It appears safe to ignore this exception.  It seems to</font></i>
<i><font color="#9A1900">           * mean that this function is in a part of the graph which</font></i>
<i><font color="#9A1900">           * is completely disconnected from the other part of the graph</font></i>
<i><font color="#9A1900">           * that contains the endpoint.</font></i>
<i><font color="#9A1900">           *)</font></i>
          <font color="#990000">|</font> <font color="#009900">Invalid_argument</font> <font color="#FF0000">"[ocamlgraph] iter_succ"</font> <font color="#990000">-&gt;</font> <b><font color="#0000FF">false</font></b>
      <font color="#990000">)</font> endpoints
  <font color="#990000">)</font> functions

<b><font color="#0000FF">and</font></b> compute_error_paths <font color="#990000">(</font><font color="#FF0000">{</font> svar <font color="#990000">=</font> svar <font color="#FF0000">}</font> <b><font color="#0000FF">as</font></b> f<font color="#990000">,</font> loc<font color="#990000">)</font> <font color="#990000">=</font>
  <i><font color="#9A1900">(*ErrorCounter.debug := true;*)</font></i>

  <i><font color="#9A1900">(* Find the initial statement in this function (assumes that the</font></i>
<i><font color="#9A1900">   * function can only be entered in one place, which is normal for C</font></i>
<i><font color="#9A1900">   * functions).</font></i>
<i><font color="#9A1900">   *)</font></i>
  <b><font color="#0000FF">let</font></b> initial_stmts <font color="#990000">=</font>
    <b><font color="#0000FF">match</font></b> f<font color="#990000">.</font>sbody<font color="#990000">.</font>bstmts <b><font color="#0000FF">with</font></b>
    <font color="#990000">|</font> <font color="#990000">[]</font> <font color="#990000">-&gt;</font> <font color="#990000">[]</font>
    <font color="#990000">|</font> first<font color="#990000">::</font>_ <font color="#990000">-&gt;</font> <font color="#990000">[</font>first<font color="#990000">]</font> <b><font color="#0000FF">in</font></b>

  <i><font color="#9A1900">(* Initialize ErrorCounter. *)</font></i>
  <b><font color="#000080">ErrorCounter</font></b><font color="#990000">.</font>init initial_stmts<font color="#990000">;</font>

  <i><font color="#9A1900">(* Compute the error counters along paths through the function. *)</font></i>
  <b><font color="#000080">ForwardsErrorCounter</font></b><font color="#990000">.</font>compute initial_stmts<font color="#990000">;</font>

  <i><font color="#9A1900">(* Process all Return statements in this function. *)</font></i>
  <b><font color="#000080">List</font></b><font color="#990000">.</font>iter <font color="#990000">(</font>
    <b><font color="#0000FF">fun</font></b> stmt <font color="#990000">-&gt;</font>
      <b><font color="#0000FF">try</font></b>
        <b><font color="#0000FF">let</font></b> errcalls <font color="#990000">=</font> <b><font color="#000080">Inthash</font></b><font color="#990000">.</font>find <b><font color="#000080">ErrorCounter</font></b><font color="#990000">.</font>stmtStartData stmt<font color="#990000">.</font>sid <b><font color="#0000FF">in</font></b>

        <b><font color="#0000FF">match</font></b> stmt <b><font color="#0000FF">with</font></b>
        <i><font color="#9A1900">(* return -1; *)</font></i>
        <font color="#990000">|</font> <font color="#FF0000">{</font> skind <font color="#990000">=</font> <font color="#009900">Return</font> <font color="#990000">(</font><font color="#009900">Some</font> i<font color="#990000">,</font> loc<font color="#990000">)</font> <font color="#FF0000">}</font> <b><font color="#0000FF">when</font></b> is_literal_minus_one i <font color="#990000">-&gt;</font>
          <b><font color="#0000FF">if</font></b> errcalls <font color="#990000">=</font> <font color="#993399">0</font> <b><font color="#0000FF">then</font></b>
            printf <font color="#FF0000">"%s:%d: %s: may return an error code without calling error/perrorf\n"</font>
              loc<font color="#990000">.</font>file loc<font color="#990000">.</font>line svar<font color="#990000">.</font>vname
          <b><font color="#0000FF">else</font></b> <b><font color="#0000FF">if</font></b> errcalls <font color="#990000">&gt;</font> <font color="#993399">1</font> <b><font color="#0000FF">then</font></b>
            printf <font color="#FF0000">"%s:%d: %s: may call error/perrorf %d times (more than once) along an error path\n"</font>
          loc<font color="#990000">.</font>file loc<font color="#990000">.</font>line svar<font color="#990000">.</font>vname errcalls

        <i><font color="#9A1900">(* return 0; *)</font></i>
        <font color="#990000">|</font> <font color="#FF0000">{</font> skind <font color="#990000">=</font> <font color="#009900">Return</font> <font color="#990000">(</font><font color="#009900">Some</font> i<font color="#990000">,</font> loc<font color="#990000">)</font> <font color="#FF0000">}</font> <b><font color="#0000FF">when</font></b> is_literal_zero i <font color="#990000">-&gt;</font>
          <b><font color="#0000FF">if</font></b> errcalls <font color="#990000">&gt;=</font> <font color="#993399">1</font> <b><font color="#0000FF">then</font></b>
            printf <font color="#FF0000">"%s:%d: %s: may call error/perrorf along a non-error return path\n"</font>
              loc<font color="#990000">.</font>file loc<font color="#990000">.</font>line svar<font color="#990000">.</font>vname

        <i><font color="#9A1900">(* return; (void return) *)</font></i>
        <font color="#990000">|</font> <font color="#FF0000">{</font> skind <font color="#990000">=</font> <font color="#009900">Return</font> <font color="#990000">(</font><font color="#009900">None</font><font color="#990000">,</font> loc<font color="#990000">)</font> <font color="#FF0000">}</font> <font color="#990000">-&gt;</font>
          <b><font color="#0000FF">if</font></b> errcalls <font color="#990000">&gt;=</font> <font color="#993399">1</font> <b><font color="#0000FF">then</font></b>
            printf <font color="#FF0000">"%s:%d: %s: may call error/perrorf and return void\n"</font>
              loc<font color="#990000">.</font>file loc<font color="#990000">.</font>line svar<font color="#990000">.</font>vname

        <font color="#990000">|</font> _ <font color="#990000">-&gt;</font> <font color="#990000">()</font>

      <b><font color="#0000FF">with</font></b>
        <font color="#009900">Not_found</font> <font color="#990000">-&gt;</font>
          printf <font color="#FF0000">"%s:%d: %s: may contain unreachable code\n"</font>
            loc<font color="#990000">.</font>file loc<font color="#990000">.</font>line svar<font color="#990000">.</font>vname
  <font color="#990000">)</font> f<font color="#990000">.</font>sallstmts

<i><font color="#9A1900">(* Some convenience CIL matching functions. *)</font></i>
<b><font color="#0000FF">and</font></b> is_literal_minus_one <font color="#990000">=</font> <b><font color="#0000FF">function</font></b>
  <font color="#990000">|</font> <font color="#009900">Const</font> <font color="#990000">(</font><font color="#009900">CInt64</font> <font color="#990000">(-</font><font color="#993399">1L</font><font color="#990000">,</font> _<font color="#990000">,</font> _<font color="#990000">))</font> <font color="#990000">-&gt;</font> <b><font color="#0000FF">true</font></b>
  <font color="#990000">|</font> _ <font color="#990000">-&gt;</font> <b><font color="#0000FF">false</font></b>

<b><font color="#0000FF">and</font></b> is_literal_zero <font color="#990000">=</font> <b><font color="#0000FF">function</font></b>
  <font color="#990000">|</font> <font color="#009900">Const</font> <font color="#990000">(</font><font color="#009900">CInt64</font> <font color="#990000">(</font><font color="#993399">0L</font><font color="#990000">,</font> _<font color="#990000">,</font> _<font color="#990000">))</font> <font color="#990000">-&gt;</font> <b><font color="#0000FF">true</font></b>
  <font color="#990000">|</font> _ <font color="#990000">-&gt;</font> <b><font color="#0000FF">false</font></b>

<i><font color="#9A1900">(* Convenient routine to load the contents of a channel into a list of</font></i>
<i><font color="#9A1900"> * strings.</font></i>
<i><font color="#9A1900"> *)</font></i>
<b><font color="#0000FF">and</font></b> input_chan chan <font color="#990000">=</font>
  <b><font color="#0000FF">let</font></b> lines <font color="#990000">=</font> <font color="#009900">ref</font> <font color="#990000">[]</font> <b><font color="#0000FF">in</font></b>
  <b><font color="#0000FF">try</font></b> <b><font color="#0000FF">while</font></b> <b><font color="#0000FF">true</font></b><font color="#990000">;</font> <b><font color="#0000FF">do</font></b> lines <font color="#990000">:=</font> input_line chan <font color="#990000">::</font> <font color="#990000">!</font>lines <b><font color="#0000FF">done</font></b><font color="#990000">;</font> <font color="#990000">[]</font>
  <b><font color="#0000FF">with</font></b> <font color="#009900">End_of_file</font> <font color="#990000">-&gt;</font> <b><font color="#000080">List</font></b><font color="#990000">.</font>rev <font color="#990000">!</font>lines

<b><font color="#0000FF">and</font></b> input_file filename <font color="#990000">=</font>
  <b><font color="#0000FF">let</font></b> chan <font color="#990000">=</font> open_in filename <b><font color="#0000FF">in</font></b>
  <b><font color="#0000FF">let</font></b> r <font color="#990000">=</font> input_chan chan <b><font color="#0000FF">in</font></b>
  close_in chan<font color="#990000">;</font>
  r

<b><font color="#0000FF">let</font></b> <font color="#990000">()</font> <font color="#990000">=</font>
  <b><font color="#0000FF">try</font></b> main <font color="#990000">()</font>
  <b><font color="#0000FF">with</font></b> 
    <font color="#009900">exn</font> <font color="#990000">-&gt;</font>
      prerr_endline <font color="#990000">(</font><b><font color="#000080">Printexc</font></b><font color="#990000">.</font>to_string <font color="#009900">exn</font><font color="#990000">);</font>
      <b><font color="#000080">Printexc</font></b><font color="#990000">.</font>print_backtrace <b><font color="#000080">Pervasives</font></b><font color="#990000">.</font>stderr<font color="#990000">;</font>
      exit <font color="#993399">1</font>
</tt>
</pre>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/rwmj.wordpress.com/4163/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/rwmj.wordpress.com/4163/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rwmj.wordpress.com&#038;blog=6840703&#038;post=4163&#038;subd=rwmj&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://rwmj.wordpress.com/2013/02/07/more-static-analysis-with-cil/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/e3ec39948aca0fe41ac29e3e9f8a2649?s=96&#38;d=http%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">rich</media:title>
		</media:content>
	</item>
		<item>
		<title>OCaml Users and Developers slides and videos</title>
		<link>http://rwmj.wordpress.com/2012/09/26/ocaml-users-and-developers-slides-and-videos/</link>
		<comments>http://rwmj.wordpress.com/2012/09/26/ocaml-users-and-developers-slides-and-videos/#comments</comments>
		<pubDate>Wed, 26 Sep 2012 09:11:12 +0000</pubDate>
		<dc:creator>rich</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[ocaml]]></category>

		<guid isPermaLink="false">http://rwmj.wordpress.com/?p=4064</guid>
		<description><![CDATA[http://oud.ocaml.org/2012/#schedule (thanks Anil).<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rwmj.wordpress.com&#038;blog=6840703&#038;post=4064&#038;subd=rwmj&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p><a href="http://oud.ocaml.org/2012/#schedule">http://oud.ocaml.org/2012/#schedule</a> (thanks Anil).</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/rwmj.wordpress.com/4064/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/rwmj.wordpress.com/4064/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rwmj.wordpress.com&#038;blog=6840703&#038;post=4064&#038;subd=rwmj&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://rwmj.wordpress.com/2012/09/26/ocaml-users-and-developers-slides-and-videos/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/e3ec39948aca0fe41ac29e3e9f8a2649?s=96&#38;d=http%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">rich</media:title>
		</media:content>
	</item>
		<item>
		<title>xavierbot lives!</title>
		<link>http://rwmj.wordpress.com/2012/06/13/xavierbot-lives/</link>
		<comments>http://rwmj.wordpress.com/2012/06/13/xavierbot-lives/#comments</comments>
		<pubDate>Wed, 13 Jun 2012 21:23:31 +0000</pubDate>
		<dc:creator>rich</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[ocaml]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[xavierbot]]></category>

		<guid isPermaLink="false">http://rwmj.wordpress.com/?p=3999</guid>
		<description><![CDATA[Or at least he now has his own git repository.<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rwmj.wordpress.com&#038;blog=6840703&#038;post=3999&#038;subd=rwmj&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Or at least he now has his own <a href="http://git.annexia.org/?p=xavierbot.git;a=summary">git repository</a>.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/rwmj.wordpress.com/3999/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/rwmj.wordpress.com/3999/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rwmj.wordpress.com&#038;blog=6840703&#038;post=3999&#038;subd=rwmj&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://rwmj.wordpress.com/2012/06/13/xavierbot-lives/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/e3ec39948aca0fe41ac29e3e9f8a2649?s=96&#38;d=http%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">rich</media:title>
		</media:content>
	</item>
		<item>
		<title>OCaml 4.00.0 beta 2 is in Rawhide</title>
		<link>http://rwmj.wordpress.com/2012/06/09/ocaml-4-00-0-beta-2-is-in-rawhide/</link>
		<comments>http://rwmj.wordpress.com/2012/06/09/ocaml-4-00-0-beta-2-is-in-rawhide/#comments</comments>
		<pubDate>Sat, 09 Jun 2012 10:51:52 +0000</pubDate>
		<dc:creator>rich</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[fedora]]></category>
		<category><![CDATA[functional programming]]></category>
		<category><![CDATA[ocaml]]></category>

		<guid isPermaLink="false">http://rwmj.wordpress.com/?p=3992</guid>
		<description><![CDATA[OCaml 4.00.0 betas are available and I&#8217;ve packaged it up for Fedora Rawhide. In other OCaml news, the various &#8220;retired&#8221; code generators (PPC64, MIPS, IA64, HPPA, Alpha) now have their own repository. Who wants to volunteer to write an s/390x &#8230; <a href="http://rwmj.wordpress.com/2012/06/09/ocaml-4-00-0-beta-2-is-in-rawhide/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rwmj.wordpress.com&#038;blog=6840703&#038;post=3992&#038;subd=rwmj&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p><a href="https://sympa.inria.fr/sympa/arc/caml-list/2012-06/msg00030.html">OCaml 4.00.0 betas are available</a> and I&#8217;ve <a href="http://koji.fedoraproject.org/koji/packageinfo?packageID=2668">packaged it up for Fedora Rawhide</a>.</p>
<p>In other OCaml news, the various &#8220;retired&#8221; code generators (PPC64, MIPS, IA64, HPPA, Alpha) now have <a href="https://github.com/retired-camels/ocaml">their own repository</a>.  Who wants to volunteer to write an s/390x code generator?</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/rwmj.wordpress.com/3992/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/rwmj.wordpress.com/3992/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rwmj.wordpress.com&#038;blog=6840703&#038;post=3992&#038;subd=rwmj&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://rwmj.wordpress.com/2012/06/09/ocaml-4-00-0-beta-2-is-in-rawhide/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/e3ec39948aca0fe41ac29e3e9f8a2649?s=96&#38;d=http%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">rich</media:title>
		</media:content>
	</item>
		<item>
		<title>OCaml Users and Developers conference 2012</title>
		<link>http://rwmj.wordpress.com/2012/05/15/ocaml-users-and-developers-conference-2012/</link>
		<comments>http://rwmj.wordpress.com/2012/05/15/ocaml-users-and-developers-conference-2012/#comments</comments>
		<pubDate>Tue, 15 May 2012 19:43:25 +0000</pubDate>
		<dc:creator>rich</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[functional programming]]></category>
		<category><![CDATA[libguestfs]]></category>
		<category><![CDATA[ocaml]]></category>

		<guid isPermaLink="false">http://rwmj.wordpress.com/?p=3964</guid>
		<description><![CDATA[The OCaml Users and Developers Conference (14th September 2012, Copenhagen) is looking for speakers! I&#8217;m intending to submit a talk on using OCaml for code generation in libguestfs.<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rwmj.wordpress.com&#038;blog=6840703&#038;post=3964&#038;subd=rwmj&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>The <a href="http://oud.ocaml.org/2012/">OCaml Users and Developers Conference</a> (14th September 2012, Copenhagen) is looking for speakers!</p>
<p>I&#8217;m intending to submit a talk on using OCaml for code generation in <a href="http://libguestfs.org">libguestfs</a>.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/rwmj.wordpress.com/3964/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/rwmj.wordpress.com/3964/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rwmj.wordpress.com&#038;blog=6840703&#038;post=3964&#038;subd=rwmj&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://rwmj.wordpress.com/2012/05/15/ocaml-users-and-developers-conference-2012/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/e3ec39948aca0fe41ac29e3e9f8a2649?s=96&#38;d=http%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">rich</media:title>
		</media:content>
	</item>
		<item>
		<title>whenjobs 0.7.0 released</title>
		<link>http://rwmj.wordpress.com/2012/03/13/whenjobs-0-7-0-released/</link>
		<comments>http://rwmj.wordpress.com/2012/03/13/whenjobs-0-7-0-released/#comments</comments>
		<pubDate>Tue, 13 Mar 2012 20:45:05 +0000</pubDate>
		<dc:creator>rich</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[cron]]></category>
		<category><![CDATA[freebsd]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[ocaml]]></category>
		<category><![CDATA[whenjobs]]></category>

		<guid isPermaLink="false">http://rwmj.wordpress.com/?p=3857</guid>
		<description><![CDATA[I&#8217;ve just released whenjobs 0.7.0 to fix a couple of problems that I was having myself. Firstly, while it&#8217;s a nice feature of whenjobs that I can set variables, sometimes I don&#8217;t want jobs to be triggered as a result &#8230; <a href="http://rwmj.wordpress.com/2012/03/13/whenjobs-0-7-0-released/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rwmj.wordpress.com&#038;blog=6840703&#038;post=3857&#038;subd=rwmj&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>I&#8217;ve just released <a href="http://people.redhat.com/~rjones/whenjobs/">whenjobs 0.7.0</a> to fix a couple of problems that I was having myself.</p>
<p>Firstly, while it&#8217;s a nice feature of whenjobs that I can set variables, sometimes I don&#8217;t want jobs to be triggered as a result of setting variables.  The new <code>whenjobs --whisper</code> command lets me set variables without reevaluating when-clauses:</p>
<pre>
$ whenjobs --whisper libguestfs_version=1.17.16
</pre>
<p>Secondly, my jobs file was getting pretty long and unmaintainable (400 lines), since I added various libguestfs branches and hivex to be managed by whenjobs.  So I&#8217;ve added a feature where you can split the jobs file into multiple files:</p>
<pre>
$ ls -l .whenjobs/*.ml
-rw-rw-r--. 1 rjones rjones 3284 Mar 13 19:10 .whenjobs/jobs_hivex.ml
-rw-rw-r--. 1 rjones rjones 4039 Mar 13 19:07 .whenjobs/jobs_libguestfs.ml
-rw-rw-r--. 1 rjones rjones 3766 Mar 13 19:09 .whenjobs/jobs_libguestfs_stable.ml
-rw-rw-r--. 1 rjones rjones   45 Mar 13 19:10 .whenjobs/jobs.ml
</pre>
<p>I think I described whenjobs as a &#8220;cron replacement&#8221;.  It is a cron replacement for me, for my personal use, but it&#8217;s not officially a cron replacement and this project has nothing whatsoever to do with Red Hat or Fedora.  The reason I say this is I get some <a href="http://forums.freebsd.org/showthread.php?p=170003">pretty idiotic comments like these</a>.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/rwmj.wordpress.com/3857/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/rwmj.wordpress.com/3857/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rwmj.wordpress.com&#038;blog=6840703&#038;post=3857&#038;subd=rwmj&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://rwmj.wordpress.com/2012/03/13/whenjobs-0-7-0-released/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/e3ec39948aca0fe41ac29e3e9f8a2649?s=96&#38;d=http%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">rich</media:title>
		</media:content>
	</item>
		<item>
		<title>whenjobs &#8212; job lists, cancelling, algorithmic cleanup etc</title>
		<link>http://rwmj.wordpress.com/2012/02/24/whenjobs-job-lists-cancelling-algorithmic-cleanup-etc/</link>
		<comments>http://rwmj.wordpress.com/2012/02/24/whenjobs-job-lists-cancelling-algorithmic-cleanup-etc/#comments</comments>
		<pubDate>Fri, 24 Feb 2012 13:10:35 +0000</pubDate>
		<dc:creator>rich</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[cron]]></category>
		<category><![CDATA[ocaml]]></category>
		<category><![CDATA[unix]]></category>
		<category><![CDATA[whenjobs]]></category>

		<guid isPermaLink="false">http://rwmj.wordpress.com/?p=3792</guid>
		<description><![CDATA[You can now list and cancel jobs: $ whenjobs --jobs 61 job$1 running in: /tmp/whenjobs20d88a48f2c4eb0062e1b44ded6d0ae7 started at: 2012-02-23 22:43:20 62 job$2 running in: /tmp/whenjobse9e6b93c3ced1967cbf8c5865d6a1ccb started at: 2012-02-23 22:43:20 $ whenjobs --cancel 62 You can manually start jobs. Gerd&#8217;s ocamlnet makes &#8230; <a href="http://rwmj.wordpress.com/2012/02/24/whenjobs-job-lists-cancelling-algorithmic-cleanup-etc/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rwmj.wordpress.com&#038;blog=6840703&#038;post=3792&#038;subd=rwmj&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>You can now list and cancel jobs:</p>
<pre>
$ <b>whenjobs --jobs</b>
61 job$1
	running in: /tmp/whenjobs20d88a48f2c4eb0062e1b44ded6d0ae7
	started at: 2012-02-23 22:43:20
62 job$2
	running in: /tmp/whenjobse9e6b93c3ced1967cbf8c5865d6a1ccb
	started at: 2012-02-23 22:43:20
$ <b>whenjobs --cancel 62</b>
</pre>
<p>You can manually start jobs.  Gerd&#8217;s <a href="http://projects.camlcity.org/projects/ocamlnet.html">ocamlnet</a> makes it almost trivial to add new RPCs between the tool and the daemon, so adding functions like this is simple.</p>
<p>You can put arbitrary OCaml actions into the job script too, so you can run code when a job is cleaned up, and you will (soon) be able to create jobs algorithmically.  For example, the standard <code>mailto</code> cleanup lets you send mail containing the output of the job when it finishes.</p>
<pre>
let from = "me@example.com"
let to_addr = "you@example.com"
let prefix = "hostname "
let script = &lt;&lt; # shell script here &gt;&gt;

job (prefix ^ "poll")
cleanup (Whentools.mailto ~from to_addr)
every minute : script
</pre>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/rwmj.wordpress.com/3792/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/rwmj.wordpress.com/3792/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rwmj.wordpress.com&#038;blog=6840703&#038;post=3792&#038;subd=rwmj&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://rwmj.wordpress.com/2012/02/24/whenjobs-job-lists-cancelling-algorithmic-cleanup-etc/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/e3ec39948aca0fe41ac29e3e9f8a2649?s=96&#38;d=http%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">rich</media:title>
		</media:content>
	</item>
		<item>
		<title>A work in progress: whenjobs &#8212; another cron replacement</title>
		<link>http://rwmj.wordpress.com/2012/02/18/a-work-in-progress-whenjobs-another-cron-replacement/</link>
		<comments>http://rwmj.wordpress.com/2012/02/18/a-work-in-progress-whenjobs-another-cron-replacement/#comments</comments>
		<pubDate>Sat, 18 Feb 2012 17:23:11 +0000</pubDate>
		<dc:creator>rich</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[cron]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[ocaml]]></category>
		<category><![CDATA[unix]]></category>

		<guid isPermaLink="false">http://rwmj.wordpress.com/?p=3782</guid>
		<description><![CDATA[whenjobs (git repo) is a cron replacement. From the manual page &#8230; Whenjobs is a powerful but simple replacement for cron. It lets you run jobs periodically like cron, but it also lets you trigger jobs to run when user-defined &#8230; <a href="http://rwmj.wordpress.com/2012/02/18/a-work-in-progress-whenjobs-another-cron-replacement/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rwmj.wordpress.com&#038;blog=6840703&#038;post=3782&#038;subd=rwmj&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p><a href="http://git.annexia.org/?p=whenjobs.git;a=summary">whenjobs (git repo)</a> is a cron replacement.  From the manual page &#8230;</p>
<blockquote><p>
Whenjobs is a powerful but simple replacement for cron.  It lets you run jobs periodically like cron, but it also lets you trigger jobs to run when user-defined variables are set or change value.</p>
<p>Periodic jobs are written like this:</p>
<pre>
every 10 minutes :
&lt;&lt;
  # Get the current load average.
  load=`awk '{print $1}' /proc/loadavg`
  whenjobs --set load $load --type float
&gt;&gt;
</pre>
<p>When-statements let you create jobs that run based on variables set elsewhere:</p>
<pre>
when load &gt;= 6 :
&lt;&lt;
  mail -s "ALERT: high load average: $load" $LOGNAME &lt; /dev/null
&gt;&gt;
</pre>
<p>(When statements are &quot;edge-triggered&quot;, meaning that this job will only run when the load goes from under 6 to &ge; 6).
</p></blockquote>
<p>The motivation is building things from git automatically.  Here is another job script:</p>
<p>Every 10 minutes, get the latest tagged version from the git repository.  The variable &#8216;version&#8217; will be set to something like &#8220;v1.2.3&#8243;, &#8220;v1.2.4&#8243;, etc over time as new releases get tagged.</p>
<pre>
every 10 minutes :
&lt;&lt;
  cd /my/git/repo
  tag=`git-describe --tags`
  whenjobs --set version $tag
&gt;&gt;
</pre>
<p>When the &#8216;version&#8217; variable changes (ie. a new release is tagged) try to build it.  &#8216;changes&#8217; is a function that compares the previous value of a variable from when this job last ran with the current value of a variable, and returns true if the previous and current values are different.</p>
<pre>
when changes version :
&lt;&lt;
  cd /my/git/buildrepo
  git pull
  git reset --hard $version
  ./configure
  make clean all check dist
  whenjobs --set successful_local_build $version
&gt;&gt;
</pre>
<p>In parallel, build on a remote machine.</p>
<pre>
when changes version :
&lt;&lt;
  ssh remote ./do_build $version
  whenjobs --set successful_remote_build $version
&gt;&gt;
</pre>
<p>Only when the new release has been successfully built on local and remote, upload it to the website.</p>
<pre>
when successful_local_build == version &amp;&amp;
     successful_remote_build == version :
&lt;&lt;
  cd /my/git/buildrepo
  curl -T name-$success.tar.gz ftp://ftp.example.com/upload/
&gt;&gt;
</pre>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/rwmj.wordpress.com/3782/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/rwmj.wordpress.com/3782/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rwmj.wordpress.com&#038;blog=6840703&#038;post=3782&#038;subd=rwmj&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://rwmj.wordpress.com/2012/02/18/a-work-in-progress-whenjobs-another-cron-replacement/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/e3ec39948aca0fe41ac29e3e9f8a2649?s=96&#38;d=http%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">rich</media:title>
		</media:content>
	</item>
		<item>
		<title>Which foreign function interface is the best?</title>
		<link>http://rwmj.wordpress.com/2011/09/21/which-foreign-function-interface-is-the-best/</link>
		<comments>http://rwmj.wordpress.com/2011/09/21/which-foreign-function-interface-is-the-best/#comments</comments>
		<pubDate>Wed, 21 Sep 2011 21:15:53 +0000</pubDate>
		<dc:creator>rich</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[c++]]></category>
		<category><![CDATA[erlang]]></category>
		<category><![CDATA[FFI]]></category>
		<category><![CDATA[haskell]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[libguestfs]]></category>
		<category><![CDATA[ocaml]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programming languages]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://rwmj.wordpress.com/?p=3551</guid>
		<description><![CDATA[I&#8217;ve written libguestfs language bindings for Perl, Python, Ruby, Java, OCaml, PHP, Haskell, Erlang and C#. But which of these is the best? Which is the easiest? What makes this hard? Grubbing around in the internals of a language reveals &#8230; <a href="http://rwmj.wordpress.com/2011/09/21/which-foreign-function-interface-is-the-best/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rwmj.wordpress.com&#038;blog=6840703&#038;post=3551&#038;subd=rwmj&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p><b>I&#8217;ve written <a href="http://libguestfs.org/">libguestfs</a> language bindings for Perl, Python, Ruby, Java, OCaml, PHP, Haskell, Erlang and C#.  But which of these is the best?</b>  Which is the easiest?  What makes this hard?  Grubbing around in the internals of a language reveals mistakes made by the language designers, but what are the worst mistakes?</p>
<p><i>Note: There is source that goes with this.  Download <a href="http://www.libguestfs.org/download/1.13-development/libguestfs-1.13.13.tar.gz">libguestfs-1.13.13.tar.gz</a> and look in the respective directories.</i></p>
<p><b>The best</b></p>
<p>It&#8217;s going to be a controversial choice, but in my opinion: C#.  You just add some simple annotations to your functions and structs, and you can call into shared libraries (or &#8220;DllImport&#8221;s as Microsoft insisted on calling them) directly.  It&#8217;s just about as easy as directly calling C and that is no simple achievement considering how the underlying runtime of C# is very different from C.</p>
<p>Example: a C struct:</p>
<pre>
[StructLayout (LayoutKind.Sequential)]
public class _int_bool {
  int i;
  int b;
}
</pre>
<p><b>The worst</b></p>
<p>There are two languages in the doghouse: Haskell and PHP.  PHP first because their method of binding is just very broken.  For example, 64 bit types aren&#8217;t possible on a 32 bit platform.  It requires a very complex autoconf setup.  And the quality of their implementation is very poor verging on broken &#8212; it makes me wonder if the rest of PHP can be this bad.</p>
<p>Haskell: even though I&#8217;m an experienced functional programmer and have done a fair bit of Haskell programming in the past, the FFI is deeply strange and very poorly documented.  I simply could not work out how to return anything other than integers from my functions.  You end up with bindings that look like this:</p>
<pre>
write_file h path content size = do
  r &lt;- withCString path $ \path -&gt; withCString content $ \content -&gt; withForeignPtr h (\p -&gt; c_write_file p path content (fromIntegral size))
  if (r == -1)
    then do
      err &lt;- last_error h
      fail err
    else return ()
</pre>
<p><b>The middle tier</b></p>
<p>There&#8217;s not a lot to choose between OCaml, Ruby, Java and Erlang.  For all of them: you write bindings in C, there&#8217;s good documentation, it&#8217;s a bit tedious but basically mechanical, and in 3 out of 4 you&#8217;re dealing with a reasonable garbage collector so you have to be aware of GC issues.</p>
<p>Erlang is slightly peculiar because the method I chose (<a href="http://www.erlang.org/doc/tutorial/introduction.html">out of many possible</a>) is to <a href="http://www.erlang.org/doc/tutorial/erl_interface.html">write an external process that talks to the Erlang over stdin/stdout</a>.  But I can&#8217;t fault their documentation, and the rest of it is sensible.</p>
<p>Example: Here is a function binding in OCaml, but with mechanical changes this could be Ruby, Java or Erlang too:</p>
<pre>
CAMLprim value
ocaml_guestfs_add_drive_ro (value gv, value filenamev)
{
  CAMLparam2 (gv, filenamev);
  CAMLlocal1 (rv);

  guestfs_h *g = Guestfs_val (gv);
  if (g == NULL)
    ocaml_guestfs_raise_closed ("add_drive_ro");

  char *filename = guestfs_safe_strdup (g, String_val (filenamev));
  int r;

  caml_enter_blocking_section ();
  r = guestfs_add_drive_ro (g, filename);
  caml_leave_blocking_section ();
  free (filename);
  if (r == -1)
    ocaml_guestfs_raise_error (g, "add_drive_ro");

  rv = Val_unit;
  CAMLreturn (rv);
}
</pre>
<p><b>The ugly</b></p>
<p>Perl: Get reading.  You&#8217;d better start with <a href="http://perldoc.perl.org/perlxs.html">perlxs</a> because Perl uses its own language &#8212; C with bizarre macros on top so your code looks like this:</p>
<pre>
SV *
is_config (g)
      guestfs_h *g;
PREINIT:
      int r;
   CODE:
      r = guestfs_is_config (g);
      if (r == -1)
        croak ("%s", guestfs_last_error (g));
      RETVAL = newSViv (r);
 OUTPUT:
      RETVAL
</pre>
<p>After that, get familiar with <a href="http://perldoc.perl.org/perlguts.html">perlguts</a>.  Perl has only 3 structures and you&#8217;ll be using them a lot.  There are some brilliant things about Perl which shouldn&#8217;t be overlooked, including <a href="http://perldoc.perl.org/perlpod.html">POD</a> which libguestfs uses to make effortless manual pages.</p>
<p>Python:  Best described as half arsed.  Rather like the language itself.</p>
<p>Python, Ruby, Erlang: If your language depends on &#8220;int&#8221;, &#8220;long&#8221;, &#8220;long long&#8221; without defining what those mean, and differing based on your C compiler and platform, then you&#8217;ve made a big mistake that will unfortunately dog you throughout the runtime, FFIs and the language itself.  It&#8217;s better either to define them precisely (like Java) or to just use int32 and int64 (like OCaml).</p>
<p>And finally, reference counting (Perl, Python).  It&#8217;s tremendously easy to make mistakes that are fiendishly difficult to track down.  It&#8217;s a poor way to do GC and it indicates to me that the language designer didn&#8217;t know any better.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/rwmj.wordpress.com/3551/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/rwmj.wordpress.com/3551/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rwmj.wordpress.com&#038;blog=6840703&#038;post=3551&#038;subd=rwmj&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://rwmj.wordpress.com/2011/09/21/which-foreign-function-interface-is-the-best/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/e3ec39948aca0fe41ac29e3e9f8a2649?s=96&#38;d=http%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">rich</media:title>
		</media:content>
	</item>
		<item>
		<title>What I learned about AMQP</title>
		<link>http://rwmj.wordpress.com/2011/09/20/what-i-learned-about-amqp/</link>
		<comments>http://rwmj.wordpress.com/2011/09/20/what-i-learned-about-amqp/#comments</comments>
		<pubDate>Tue, 20 Sep 2011 12:18:11 +0000</pubDate>
		<dc:creator>rich</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[amqp]]></category>
		<category><![CDATA[ocaml]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[qpid]]></category>
		<category><![CDATA[rabbitmq]]></category>

		<guid isPermaLink="false">http://rwmj.wordpress.com/?p=3542</guid>
		<description><![CDATA[I&#8217;m playing with AMQP at the moment. I thought I&#8217;d start off with RabbitMQ first. The good: It works. OCaml and Python programs can talk to each other. It works across remote hosts. You need to open port 5672/tcp on &#8230; <a href="http://rwmj.wordpress.com/2011/09/20/what-i-learned-about-amqp/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rwmj.wordpress.com&#038;blog=6840703&#038;post=3542&#038;subd=rwmj&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>I&#8217;m playing with <a href="https://secure.wikimedia.org/wikipedia/en/wiki/Advanced_Message_Queuing_Protocol">AMQP</a> at the moment.  I thought I&#8217;d start off with <a href="http://www.rabbitmq.com/">RabbitMQ</a> first.</p>
<p>The good:</p>
<ul>
<li> It works.
<li> OCaml and Python programs <a href="https://sympa-roc.inria.fr/wws/arc/caml-list/2011-09/msg00168.html">can talk to each other</a>.
<li> It works across remote hosts.  You need to open port 5672/tcp on the firewall.
</ul>
<p>The bad:</p>
<ul>
<li> RabbitMQ and Apache Qpid use different versions of AMQP and are not interoperable!  <a href="http://it.toolbox.com/blogs/open-source-smb/whats-the-future-of-amqp-44450">Good summary of the mess here</a>.  This might be resolved when everyone gets around to supporting AMQP 1-0, but even though that standard has been published, no one is expecting interop to happen for at least a year.
<li> You can&#8217;t cluster different versions of the RabbitMQ broker together.
<li> Even if all your hosts are at the same RabbitMQ version, you <a href="http://old.nabble.com/Re%3A-problems-with-rabbitmq-cluster-across-2%09ubuntu-9.04-machines-p25632176.html">have to open more firewall ports and make changes to the start-up scripts</a>.  (Dynamic ports?  Really?  Did we learn nothing from NFS?)
<li> Long, obscure Erlang error messages which don&#8217;t point to the problem.  eg. You&#8217;ll get a good 25 lines of error message if another process is already bound to a port.
<li> Possibly just a Fedora packaging problem: I managed to get my host into some state where it&#8217;s impossible to stop the RabbitMQ server except by kill -9, and after that I can&#8217;t start or stop it.
</ul>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/rwmj.wordpress.com/3542/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/rwmj.wordpress.com/3542/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rwmj.wordpress.com&#038;blog=6840703&#038;post=3542&#038;subd=rwmj&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://rwmj.wordpress.com/2011/09/20/what-i-learned-about-amqp/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/e3ec39948aca0fe41ac29e3e9f8a2649?s=96&#38;d=http%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">rich</media:title>
		</media:content>
	</item>
		<item>
		<title>Arrrgghh writing GUI programs is tedious</title>
		<link>http://rwmj.wordpress.com/2011/09/04/arrrgghh-writing-gui-programs-is-tedious/</link>
		<comments>http://rwmj.wordpress.com/2011/09/04/arrrgghh-writing-gui-programs-is-tedious/#comments</comments>
		<pubDate>Sun, 04 Sep 2011 14:57:36 +0000</pubDate>
		<dc:creator>rich</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[gtk]]></category>
		<category><![CDATA[ocaml]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[rants]]></category>
		<category><![CDATA[virt-resize]]></category>

		<guid isPermaLink="false">http://rwmj.wordpress.com/?p=3509</guid>
		<description><![CDATA[Last week I thought it would be a good idea to write a small GUI front end to virt-resize. After two days, I nearly have the first tab (out of four) working. Granted, maybe the first tab is the hardest &#8230; <a href="http://rwmj.wordpress.com/2011/09/04/arrrgghh-writing-gui-programs-is-tedious/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rwmj.wordpress.com&#038;blog=6840703&#038;post=3509&#038;subd=rwmj&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Last week I thought it would be a good idea to write a small <a href="http://git.annexia.org/?p=virt-resize-ui.git;a=summary">GUI front end</a> to <a href="http://libguestfs.org/virt-resize.1.html">virt-resize</a>.</p>
<p>After two days, I <i>nearly</i> have the first tab (out of four) working.</p>
<p>Granted, maybe the first tab is the hardest one:</p>
<p><a href="http://rwmj.files.wordpress.com/2011/09/virt-resize-ui.png"><img src="http://rwmj.files.wordpress.com/2011/09/virt-resize-ui.png?w=438&#038;h=450" alt="" title="virt-resize-ui" width="438" height="450" class="aligncenter size-medium wp-image-3513" /></a></p>
<p>The job of the first tab is to ask the user for the source (disk image or libvirt guest).  It then fires off a background job to open that guest and <a href="http://libguestfs.org/virt-inspector.1.html">inspect it for operating systems</a>.  Based on the outcome of that (opened OK, found OSes, no OSes found, etc) it has to update and enable the other tabs.</p>
<p>Also the user can preselect a guest on the command line.  We also have to deal with connecting to libvirt asynchronously to read the list of guests (and this might also fail in a number of ways).</p>
<p>So far, 1600 lines of code, and the first tab is by no means complete.</p>
<p>One part of the problem is there&#8217;s a certain &#8220;impedance mismatch&#8221; between functional programming in OCaml and writing Gtk.  Gtk is heavily mutable and object based.  OCaml prefers (but does not require) immutability, and objects in OCaml are obscure and not widely used, and the Gtk bindings are written in a very hard-core object OCaml style.</p>
<p>Another part is just that it&#8217;s tedious.  It would be tedious if I was doing this in C or Python too.  You&#8217;ve got asynchronous actions going off here and there which update bits of state.  Every control or input could potentially affect every other control or output, resulting in a kind of O(n<sup>2</sup>) mess of wiring up signals and callbacks.</p>
<p>Is there an easier way?  I don&#8217;t know &#8230;</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/rwmj.wordpress.com/3509/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/rwmj.wordpress.com/3509/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rwmj.wordpress.com&#038;blog=6840703&#038;post=3509&#038;subd=rwmj&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://rwmj.wordpress.com/2011/09/04/arrrgghh-writing-gui-programs-is-tedious/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/e3ec39948aca0fe41ac29e3e9f8a2649?s=96&#38;d=http%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">rich</media:title>
		</media:content>

		<media:content url="http://rwmj.files.wordpress.com/2011/09/virt-resize-ui.png?w=438" medium="image">
			<media:title type="html">virt-resize-ui</media:title>
		</media:content>
	</item>
		<item>
		<title>OCaml 1-page &#8220;cheat sheets&#8221;</title>
		<link>http://rwmj.wordpress.com/2011/06/06/ocaml-1-page-cheat-sheets/</link>
		<comments>http://rwmj.wordpress.com/2011/06/06/ocaml-1-page-cheat-sheets/#comments</comments>
		<pubDate>Mon, 06 Jun 2011 18:41:31 +0000</pubDate>
		<dc:creator>rich</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[ocaml]]></category>
		<category><![CDATA[ocamlpro]]></category>

		<guid isPermaLink="false">http://rwmj.wordpress.com/?p=3166</guid>
		<description><![CDATA[OCamlPro, the commercial company set up earlier this year to promote and support the OCaml language, have made some nice 1-page cheat sheets for the language and tools.<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rwmj.wordpress.com&#038;blog=6840703&#038;post=3166&#038;subd=rwmj&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p><a href="http://www.ocamlpro.com/">OCamlPro</a>, the commercial company set up earlier this year to promote and support the <a href="http://caml.inria.fr/">OCaml language</a>, have made some nice <a href="http://www.ocamlpro.com/code/2011-06-03-cheatsheets.html">1-page cheat sheets for the language and tools</a>.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/rwmj.wordpress.com/3166/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/rwmj.wordpress.com/3166/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rwmj.wordpress.com&#038;blog=6840703&#038;post=3166&#038;subd=rwmj&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://rwmj.wordpress.com/2011/06/06/ocaml-1-page-cheat-sheets/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/e3ec39948aca0fe41ac29e3e9f8a2649?s=96&#38;d=http%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">rich</media:title>
		</media:content>
	</item>
		<item>
		<title>OCaml User Meeting, April 2011</title>
		<link>http://rwmj.wordpress.com/2011/03/08/ocaml-user-meeting-april-2011/</link>
		<comments>http://rwmj.wordpress.com/2011/03/08/ocaml-user-meeting-april-2011/#comments</comments>
		<pubDate>Tue, 08 Mar 2011 12:03:50 +0000</pubDate>
		<dc:creator>rich</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[libguestfs]]></category>
		<category><![CDATA[ocaml]]></category>

		<guid isPermaLink="false">http://rwmj.wordpress.com/?p=2922</guid>
		<description><![CDATA[The announcement and details are up on the ocamlforge wiki here. I will be giving a short (10 min) talk about how we use OCaml to generate 198,278 lines of C in libguestfs.<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rwmj.wordpress.com&#038;blog=6840703&#038;post=2922&#038;subd=rwmj&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>The <a href="https://forge.ocamlcore.org/plugins/mediawiki/wiki/ocaml-meeting/index.php/OCamlMeeting2011">announcement and details are up on the ocamlforge wiki here</a>.  I will be giving a short (10 min) talk about how we use OCaml to generate 198,278 lines of C in <a href="http://libguestfs.org">libguestfs</a>.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/rwmj.wordpress.com/2922/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/rwmj.wordpress.com/2922/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rwmj.wordpress.com&#038;blog=6840703&#038;post=2922&#038;subd=rwmj&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://rwmj.wordpress.com/2011/03/08/ocaml-user-meeting-april-2011/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/e3ec39948aca0fe41ac29e3e9f8a2649?s=96&#38;d=http%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">rich</media:title>
		</media:content>
	</item>
		<item>
		<title>Tip: Using libguestfs from Perl</title>
		<link>http://rwmj.wordpress.com/2011/02/03/tip-using-libguestfs-from-perl/</link>
		<comments>http://rwmj.wordpress.com/2011/02/03/tip-using-libguestfs-from-perl/#comments</comments>
		<pubDate>Thu, 03 Feb 2011 20:00:47 +0000</pubDate>
		<dc:creator>rich</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[c++]]></category>
		<category><![CDATA[libguestfs]]></category>
		<category><![CDATA[ocaml]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[tip]]></category>
		<category><![CDATA[virt-tools]]></category>

		<guid isPermaLink="false">http://rwmj.wordpress.com/?p=2888</guid>
		<description><![CDATA[I translated the standard libguestfs examples (already available in C/C++, OCaml, Python, Ruby) into Perl. If you want to call libguestfs from Perl, you have to use Sys::Guestfs. All 300+ libguestfs API calls are available to all language bindings equally &#8230; <a href="http://rwmj.wordpress.com/2011/02/03/tip-using-libguestfs-from-perl/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rwmj.wordpress.com&#038;blog=6840703&#038;post=2888&#038;subd=rwmj&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>I translated the <a href="http://libguestfs.org/guestfs-examples.3.html">standard libguestfs examples</a> (already available in <a href="http://libguestfs.org/guestfs-examples.3.html">C/C++</a>, <a href="http://libguestfs.org/guestfs-ocaml.3.html">OCaml</a>, <a href="http://libguestfs.org/guestfs-python.3.html">Python</a>, <a href="http://libguestfs.org/guestfs-ruby.3.html">Ruby</a>) into <b><a href="http://libguestfs.org/guestfs-perl.3.html">Perl</a></b>.</p>
<p>If you want to call libguestfs from Perl, you have to <code>use Sys::Guestfs</code>.</p>
<p>All 300+ <a href="http://libguestfs.org/guestfs.3.html#api_overview">libguestfs API</a> calls are available to all language bindings equally because we generate the bindings.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/rwmj.wordpress.com/2888/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/rwmj.wordpress.com/2888/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rwmj.wordpress.com&#038;blog=6840703&#038;post=2888&#038;subd=rwmj&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://rwmj.wordpress.com/2011/02/03/tip-using-libguestfs-from-perl/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/e3ec39948aca0fe41ac29e3e9f8a2649?s=96&#38;d=http%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">rich</media:title>
		</media:content>
	</item>
		<item>
		<title>Packrat parser with left recursion</title>
		<link>http://rwmj.wordpress.com/2010/12/29/packrat-parser-with-left-recursion/</link>
		<comments>http://rwmj.wordpress.com/2010/12/29/packrat-parser-with-left-recursion/#comments</comments>
		<pubDate>Wed, 29 Dec 2010 22:15:04 +0000</pubDate>
		<dc:creator>rich</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[ocaml]]></category>
		<category><![CDATA[packrat]]></category>
		<category><![CDATA[packrat parser]]></category>
		<category><![CDATA[parsing]]></category>
		<category><![CDATA[parsing expression grammar]]></category>
		<category><![CDATA[PEG]]></category>

		<guid isPermaLink="false">http://rwmj.wordpress.com/?p=2739</guid>
		<description><![CDATA[Traditional bottom-up LALR(1) parsers like yacc are both complex to implement and limited in what they can parse. In contrast, top-down packrat parsers (good Wikipedia intro) are simple to write from scratch &#8212; you can write a parser in a &#8230; <a href="http://rwmj.wordpress.com/2010/12/29/packrat-parser-with-left-recursion/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rwmj.wordpress.com&#038;blog=6840703&#038;post=2739&#038;subd=rwmj&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Traditional <a href="https://secure.wikimedia.org/wikipedia/en/wiki/Bottom-up_parsing">bottom-up</a> LALR(1) parsers like <a href="http://www.gnu.org/software/bison/">yacc</a> are both complex to implement and limited in what they can parse.  In contrast, <a href="https://secure.wikimedia.org/wikipedia/en/wiki/Top-down_parsing">top-down</a> <a href="http://pdos.csail.mit.edu/~baford/packrat/">packrat parsers</a> (<a href="https://secure.wikimedia.org/wikipedia/en/wiki/Parsing_expression_grammar">good Wikipedia intro</a>) are simple to write from scratch &#8212; you can write a parser in a few dozen lines of code without needing any tool like yacc &#8212; and they are just about as powerful.</p>
<p>One remaining issue with packrat parsers is that they don&#8217;t natively support left recursion, making it hard to translate yacc-style parsers.  However a couple of years ago an interesting paper was published, <a href="http://www.tinlizzie.org/~awarth/papers/pepm08.pdf">Packrat Parsers Can Support Left Recursion (PDF)</a> which shows how to modify the memoization to support left recursion.</p>
<p>This really works, but unfortunately the pseudocode used in the paper is obscure and it&#8217;s hard to find example code, so I implemented this packrat parser with support for left recursion in OCaml.</p>
<p>Compile with:</p>
<pre>
$ ocamlfind opt -package extlib -linkpkg \
    testparse.ml -o testparse
</pre>
<p>and run it like this:</p>
<pre>
$ cat input
( fun a -&gt; a + 1 ) (a + b)
$ ./testparse &lt; input
</pre>
<p><span id="more-2739"></span></p>
<pre>
<b><font color="#000080">open</font></b> <font color="#009900">Printf</font>

<b><font color="#0000FF">type</font></b> grammar <font color="#990000">=</font> production <font color="#009900">list</font>
<b><font color="#0000FF">and</font></b> production <font color="#990000">=</font> <font color="#009900">string</font> <font color="#990000">*</font> choice <font color="#009900">list</font>   <i><font color="#9A1900">(* rule name -&gt; e1 | e2 | ... *)</font></i>
<b><font color="#0000FF">and</font></b> choice <font color="#990000">=</font> <font color="#009900">string</font> <font color="#990000">*</font> <font color="#009900">string</font> <font color="#990000">*</font> parsing <font color="#009900">list</font> <i><font color="#9A1900">(* choice name, comment, sequence *)</font></i>
<b><font color="#0000FF">and</font></b> parsing <font color="#990000">=</font>
  <font color="#990000">|</font> <font color="#009900">Z</font> <b><font color="#0000FF">of</font></b> parsing                        <i><font color="#9A1900">(* e* *)</font></i>
  <font color="#990000">|</font> <font color="#009900">P</font> <b><font color="#0000FF">of</font></b> parsing                        <i><font color="#9A1900">(* e+ *)</font></i>
  <font color="#990000">|</font> <font color="#009900">Opt</font> <b><font color="#0000FF">of</font></b> parsing                      <i><font color="#9A1900">(* e? *)</font></i>
<i><font color="#9A1900">(*  | Lookahead of parsing                (* &amp;e *)</font></i>
<i><font color="#9A1900">  | Not of parsing                      (* !e *) *)</font></i>
  <font color="#990000">|</font> <font color="#009900">NT</font> <b><font color="#0000FF">of</font></b> <font color="#009900">string</font>                        <i><font color="#9A1900">(* nonterminal 'name' *)</font></i>
  <font color="#990000">|</font> <font color="#009900">T</font> <b><font color="#0000FF">of</font></b> <font color="#009900">string</font>                         <i><font color="#9A1900">(* terminal *)</font></i>
  <font color="#990000">|</font> <font color="#009900">Chars</font> <b><font color="#0000FF">of</font></b> <font color="#009900">char</font> <font color="#990000">*</font> <font color="#009900">char</font>                <i><font color="#9A1900">(* [a-z] *)</font></i>
  <font color="#990000">|</font> <font color="#009900">Empty</font>                               <i><font color="#9A1900">(* epsilon *)</font></i>

<b><font color="#0000FF">let</font></b> grammar <font color="#990000">:</font> grammar <font color="#990000">=</font> <font color="#990000">[</font>
  <i><font color="#9A1900">(*</font></i>
<i><font color="#9A1900">    start -&gt; expr</font></i>
<i><font color="#9A1900">  *)</font></i>
  <font color="#FF0000">"start"</font><font color="#990000">,</font> <font color="#990000">[</font>
    <font color="#FF0000">""</font><font color="#990000">,</font> <font color="#FF0000">""</font><font color="#990000">,</font> <font color="#990000">[</font><font color="#009900">NT</font> <font color="#FF0000">"expr"</font><font color="#990000">]</font>
  <font color="#990000">];</font>

  <i><font color="#9A1900">(*</font></i>
<i><font color="#9A1900">    expr -&gt;</font></i>
<i><font color="#9A1900">          | expr expr</font></i>
<i><font color="#9A1900">          | "fun" patt "-&gt;" expr = "fundecl" ; function</font></i>
<i><font color="#9A1900">          | "(" expr ")"</font></i>
<i><font color="#9A1900">          | expr "+" expr</font></i>
<i><font color="#9A1900">          | ident</font></i>
<i><font color="#9A1900">          | int64</font></i>
<i><font color="#9A1900">  *)</font></i>
  <font color="#FF0000">"expr"</font><font color="#990000">,</font> <font color="#990000">[</font>
    <font color="#FF0000">"funappl"</font><font color="#990000">,</font> <font color="#FF0000">""</font><font color="#990000">,</font> <font color="#990000">[</font><font color="#009900">NT</font><font color="#FF0000">"expr"</font><font color="#990000">;</font> <font color="#009900">NT</font><font color="#FF0000">"sp"</font><font color="#990000">;</font> <font color="#009900">NT</font><font color="#FF0000">"expr"</font><font color="#990000">];</font>
    <font color="#FF0000">"fundecl"</font><font color="#990000">,</font> <font color="#FF0000">"function declaration"</font><font color="#990000">,</font>
      <font color="#990000">[</font><font color="#009900">T</font><font color="#FF0000">"fun"</font><font color="#990000">;</font> <font color="#009900">NT</font><font color="#FF0000">"sp"</font><font color="#990000">;</font> <font color="#009900">NT</font><font color="#FF0000">"patt"</font><font color="#990000">;</font> <font color="#009900">NT</font><font color="#FF0000">"osp"</font><font color="#990000">;</font> <font color="#009900">T</font><font color="#FF0000">"-&gt;"</font><font color="#990000">;</font> <font color="#009900">NT</font><font color="#FF0000">"sp"</font><font color="#990000">;</font> <font color="#009900">NT</font><font color="#FF0000">"expr"</font><font color="#990000">];</font>
    <font color="#FF0000">"paren"</font><font color="#990000">,</font> <font color="#FF0000">""</font><font color="#990000">,</font> <font color="#990000">[</font><font color="#009900">T</font><font color="#FF0000">"("</font><font color="#990000">;</font> <font color="#009900">NT</font><font color="#FF0000">"osp"</font><font color="#990000">;</font> <font color="#009900">NT</font><font color="#FF0000">"expr"</font><font color="#990000">;</font> <font color="#009900">NT</font><font color="#FF0000">"osp"</font><font color="#990000">;</font> <font color="#009900">T</font><font color="#FF0000">")"</font><font color="#990000">];</font>
    <font color="#FF0000">"addition"</font><font color="#990000">,</font> <font color="#FF0000">""</font><font color="#990000">,</font> <font color="#990000">[</font><font color="#009900">NT</font><font color="#FF0000">"expr"</font><font color="#990000">;</font> <font color="#009900">NT</font><font color="#FF0000">"osp"</font><font color="#990000">;</font> <font color="#009900">T</font><font color="#FF0000">"+"</font><font color="#990000">;</font> <font color="#009900">NT</font><font color="#FF0000">"osp"</font><font color="#990000">;</font> <font color="#009900">NT</font><font color="#FF0000">"expr"</font><font color="#990000">];</font>
    <font color="#FF0000">"ident"</font><font color="#990000">,</font> <font color="#FF0000">""</font><font color="#990000">,</font> <font color="#990000">[</font><font color="#009900">NT</font><font color="#FF0000">"ident"</font><font color="#990000">];</font>
    <font color="#FF0000">"int64"</font><font color="#990000">,</font> <font color="#FF0000">""</font><font color="#990000">,</font> <font color="#990000">[</font><font color="#009900">NT</font><font color="#FF0000">"int64"</font><font color="#990000">];</font>
  <font color="#990000">];</font>

  <i><font color="#9A1900">(*</font></i>
<i><font color="#9A1900">    patt -&gt; ident</font></i>
<i><font color="#9A1900">  *)</font></i>
  <font color="#FF0000">"patt"</font><font color="#990000">,</font> <font color="#990000">[</font>
    <font color="#FF0000">""</font><font color="#990000">,</font> <font color="#FF0000">""</font><font color="#990000">,</font> <font color="#990000">[</font><font color="#009900">NT</font> <font color="#FF0000">"ident"</font><font color="#990000">]</font>
  <font color="#990000">];</font>

  <i><font color="#9A1900">(*</font></i>
<i><font color="#9A1900">    int64 -&gt; digit19 digit*</font></i>
<i><font color="#9A1900">           | digit</font></i>
<i><font color="#9A1900">    digit -&gt; [0-9]</font></i>
<i><font color="#9A1900">    digit19 -&gt; [1-9]</font></i>
<i><font color="#9A1900">  *)</font></i>
  <font color="#FF0000">"int64"</font><font color="#990000">,</font> <font color="#990000">[</font>
    <i><font color="#9A1900">(*"", "", [NT"digit19"; Z(NT"digit")]; XXX *)</font></i>
    <font color="#FF0000">""</font><font color="#990000">,</font> <font color="#FF0000">""</font><font color="#990000">,</font> <font color="#990000">[</font><font color="#009900">NT</font><font color="#FF0000">"digit"</font><font color="#990000">];</font>
  <font color="#990000">];</font>
  <font color="#FF0000">"digit"</font><font color="#990000">,</font> <font color="#990000">[</font>
    <font color="#FF0000">""</font><font color="#990000">,</font> <font color="#FF0000">""</font><font color="#990000">,</font> <font color="#990000">[</font><font color="#009900">Chars</font> <font color="#990000">(</font>'<font color="#993399">0</font>'<font color="#990000">,</font> '<font color="#993399">9</font>'<font color="#990000">)];</font>
  <font color="#990000">];</font>
  <font color="#FF0000">"digit19"</font><font color="#990000">,</font> <font color="#990000">[</font>
    <font color="#FF0000">""</font><font color="#990000">,</font> <font color="#FF0000">""</font><font color="#990000">,</font> <font color="#990000">[</font><font color="#009900">Chars</font> <font color="#990000">(</font>'<font color="#993399">1</font>'<font color="#990000">,</font> '<font color="#993399">9</font>'<font color="#990000">)];</font>
  <font color="#990000">];</font>

  <i><font color="#9A1900">(*</font></i>
<i><font color="#9A1900">    ident -&gt; alpha+</font></i>
<i><font color="#9A1900">    alpha -&gt; [a-z]</font></i>
<i><font color="#9A1900">  *)</font></i>
  <font color="#FF0000">"ident"</font><font color="#990000">,</font> <font color="#990000">[</font>
    <font color="#FF0000">""</font><font color="#990000">,</font> <font color="#FF0000">""</font><font color="#990000">,</font> <font color="#990000">[</font><font color="#009900">P</font> <font color="#990000">(</font><font color="#009900">NT</font><font color="#FF0000">"alpha"</font><font color="#990000">)];</font>
  <font color="#990000">];</font>
  <font color="#FF0000">"alpha"</font><font color="#990000">,</font> <font color="#990000">[</font>
    <font color="#FF0000">""</font><font color="#990000">,</font> <font color="#FF0000">""</font><font color="#990000">,</font> <font color="#990000">[</font><font color="#009900">Chars</font> <font color="#990000">(</font>'a'<font color="#990000">,</font> 'z'<font color="#990000">)];</font>
  <font color="#990000">];</font>

  <i><font color="#9A1900">(*</font></i>
<i><font color="#9A1900">    sp -&gt; " "+</font></i>
<i><font color="#9A1900">    osp -&gt; " "*</font></i>
<i><font color="#9A1900">  *)</font></i>
  <font color="#FF0000">"sp"</font><font color="#990000">,</font> <font color="#990000">[</font>
    <font color="#FF0000">""</font><font color="#990000">,</font> <font color="#FF0000">""</font><font color="#990000">,</font> <font color="#990000">[</font><font color="#009900">P</font> <font color="#990000">(</font><font color="#009900">T</font><font color="#FF0000">" "</font><font color="#990000">)];</font>
  <font color="#990000">];</font>
  <font color="#FF0000">"osp"</font><font color="#990000">,</font> <font color="#990000">[</font>
    <font color="#FF0000">""</font><font color="#990000">,</font> <font color="#FF0000">""</font><font color="#990000">,</font> <font color="#990000">[</font><font color="#009900">Z</font> <font color="#990000">(</font><font color="#009900">T</font><font color="#FF0000">" "</font><font color="#990000">)];</font>
  <font color="#990000">];</font>
<font color="#990000">]</font>

<b><font color="#0000FF">let</font></b> initial_state <font color="#990000">=</font> <font color="#FF0000">"start"</font>

<i><font color="#9A1900">(* To support backtracking, need to read all input. *)</font></i>
<b><font color="#0000FF">let</font></b> input <font color="#990000">=</font>
  <b><font color="#0000FF">let</font></b> lines <font color="#990000">=</font> <font color="#009900">ref</font> <font color="#990000">[]</font> <b><font color="#0000FF">in</font></b>
  <font color="#990000">(</font><b><font color="#0000FF">try</font></b>
     <b><font color="#0000FF">while</font></b> <b><font color="#0000FF">true</font></b> <b><font color="#0000FF">do</font></b>
       lines <font color="#990000">:=</font> read_line <font color="#990000">()</font> <font color="#990000">::</font> <font color="#990000">!</font>lines
     <b><font color="#0000FF">done</font></b>
   <b><font color="#0000FF">with</font></b>
     <font color="#009900">End_of_file</font> <font color="#990000">-&gt;</font> <font color="#990000">()</font>
  <font color="#990000">);</font>
  <b><font color="#0000FF">let</font></b> lines <font color="#990000">=</font> <b><font color="#000080">List</font></b><font color="#990000">.</font>rev <font color="#990000">!</font>lines <b><font color="#0000FF">in</font></b>
  <b><font color="#000080">String</font></b><font color="#990000">.</font>concat <font color="#FF0000">" "</font> lines

<b><font color="#0000FF">let</font></b> len <font color="#990000">=</font> <b><font color="#000080">String</font></b><font color="#990000">.</font>length input

<i><font color="#9A1900">(* Parser.</font></i>
<i><font color="#9A1900"> * Packrat parser with left recursion, see:</font></i>
<i><font color="#9A1900"> * "Packrat Parsers Can Support Left Recursion"</font></i>
<i><font color="#9A1900"> * Alessandro Warth, James R. Douglass, Todd Millstein</font></i>
<i><font color="#9A1900"> *)</font></i>
<b><font color="#0000FF">module</font></b> <font color="#009900">StringSet</font> <font color="#990000">=</font> <b><font color="#000080">Set</font></b><font color="#990000">.</font><font color="#009900">Make</font> <font color="#990000">(</font><font color="#009900">String</font><font color="#990000">)</font>
<b><font color="#0000FF">exception</font></b> <font color="#009900">Found</font> <b><font color="#0000FF">of</font></b> <font color="#009900">int</font>

<b><font color="#0000FF">type</font></b> lr <font color="#990000">=</font> <font color="#FF0000">{</font>
  <b><font color="#0000FF">mutable</font></b> seed <font color="#990000">:</font> ans<font color="#990000">;</font>
  <b><font color="#0000FF">mutable</font></b> rulename <font color="#990000">:</font> <font color="#009900">string</font><font color="#990000">;</font>
  <b><font color="#0000FF">mutable</font></b> head <font color="#990000">:</font> head <font color="#009900">option</font><font color="#990000">;</font>
<font color="#FF0000">}</font>
<b><font color="#0000FF">and</font></b> memoentry <font color="#990000">=</font> <font color="#FF0000">{</font> <b><font color="#0000FF">mutable</font></b> ans <font color="#990000">:</font> ans_or_lr<font color="#990000">;</font> <b><font color="#0000FF">mutable</font></b> pos <font color="#990000">:</font> <font color="#009900">int</font> <font color="#FF0000">}</font>
<b><font color="#0000FF">and</font></b> ans_or_lr <font color="#990000">=</font> <font color="#009900">Answer</font> <b><font color="#0000FF">of</font></b> ans <font color="#990000">|</font> <font color="#009900">LR</font> <b><font color="#0000FF">of</font></b> lr
<b><font color="#0000FF">and</font></b> ans <font color="#990000">=</font> <font color="#009900">int</font>
<b><font color="#0000FF">and</font></b> head <font color="#990000">=</font> <font color="#FF0000">{</font>
  <b><font color="#0000FF">mutable</font></b> hrule <font color="#990000">:</font> <font color="#009900">string</font><font color="#990000">;</font>
  <b><font color="#0000FF">mutable</font></b> involved_set <font color="#990000">:</font> <b><font color="#000080">StringSet</font></b><font color="#990000">.</font>t<font color="#990000">;</font>
  <b><font color="#0000FF">mutable</font></b> eval_set <font color="#990000">:</font> <b><font color="#000080">StringSet</font></b><font color="#990000">.</font>t<font color="#990000">;</font>
<font color="#FF0000">}</font>

<b><font color="#0000FF">let</font></b> lrstack <font color="#990000">=</font> <font color="#009900">ref</font> <font color="#990000">[]</font>
<b><font color="#0000FF">let</font></b> memo <font color="#990000">=</font> <b><font color="#000080">Hashtbl</font></b><font color="#990000">.</font>create <font color="#993399">13</font>
<b><font color="#0000FF">let</font></b> pos <font color="#990000">=</font> <font color="#009900">ref</font> <font color="#993399">0</font>
<b><font color="#0000FF">let</font></b> heads <font color="#990000">=</font> <b><font color="#000080">Hashtbl</font></b><font color="#990000">.</font>create <font color="#993399">13</font>

<i><font color="#9A1900">(* Apply rule 'rulename' at position 'i' in the input.  Returns the new</font></i>
<i><font color="#9A1900"> * position if the rule can be applied, else -1 if fails.</font></i>
<i><font color="#9A1900"> *)</font></i>
<b><font color="#0000FF">let</font></b> <b><font color="#0000FF">rec</font></b> apply_rule rulename i <font color="#990000">=</font>
  <b><font color="#0000FF">match</font></b> recall rulename i <b><font color="#0000FF">with</font></b>
  <font color="#990000">|</font> <font color="#009900">None</font> <font color="#990000">-&gt;</font>
      <b><font color="#0000FF">let</font></b> lr <font color="#990000">=</font> <font color="#FF0000">{</font> seed <font color="#990000">=</font> <font color="#990000">-</font><font color="#993399">1</font><font color="#990000">;</font> rulename <font color="#990000">=</font> rulename<font color="#990000">;</font> head <font color="#990000">=</font> <font color="#009900">None</font> <font color="#FF0000">}</font> <b><font color="#0000FF">in</font></b>
      lrstack <font color="#990000">:=</font> lr <font color="#990000">::</font> <font color="#990000">!</font>lrstack<font color="#990000">;</font>
      <b><font color="#0000FF">let</font></b> m <font color="#990000">=</font> <font color="#FF0000">{</font> ans <font color="#990000">=</font> <font color="#009900">LR</font> lr<font color="#990000">;</font> pos <font color="#990000">=</font> i <font color="#FF0000">}</font> <b><font color="#0000FF">in</font></b>
      <b><font color="#000080">Hashtbl</font></b><font color="#990000">.</font>add memo <font color="#990000">(</font>rulename<font color="#990000">,</font> i<font color="#990000">)</font> m<font color="#990000">;</font>
      <b><font color="#0000FF">let</font></b> r <font color="#990000">=</font> parse rulename i <b><font color="#0000FF">in</font></b>
      lrstack <font color="#990000">:=</font> <b><font color="#000080">List</font></b><font color="#990000">.</font>tl <font color="#990000">!</font>lrstack<font color="#990000">;</font>
      m<font color="#990000">.</font>pos <font color="#990000">&lt;-</font> <font color="#990000">!</font>pos<font color="#990000">;</font>
      <b><font color="#0000FF">if</font></b> lr<font color="#990000">.</font>head <font color="#990000">&lt;&gt;</font> <font color="#009900">None</font> <b><font color="#0000FF">then</font></b> <font color="#990000">(</font>
        lr<font color="#990000">.</font>seed <font color="#990000">&lt;-</font> r<font color="#990000">;</font>
        lr_answer rulename i m
      <font color="#990000">)</font> <b><font color="#0000FF">else</font></b> <font color="#990000">(</font>
        m<font color="#990000">.</font>ans <font color="#990000">&lt;-</font> <font color="#009900">Answer</font> r<font color="#990000">;</font>
        r
      <font color="#990000">)</font>
  <font color="#990000">|</font> <font color="#009900">Some</font> m <font color="#990000">-&gt;</font>
      pos <font color="#990000">:=</font> m<font color="#990000">.</font>pos<font color="#990000">;</font>
      <b><font color="#0000FF">match</font></b> m<font color="#990000">.</font>ans <b><font color="#0000FF">with</font></b>
      <font color="#990000">|</font> <font color="#009900">LR</font> lr <font color="#990000">-&gt;</font> setup_lr rulename lr<font color="#990000">;</font> lr<font color="#990000">.</font>seed
      <font color="#990000">|</font> <font color="#009900">Answer</font> r <font color="#990000">-&gt;</font> r

<b><font color="#0000FF">and</font></b> setup_lr rulename lr <font color="#990000">=</font>
  <b><font color="#0000FF">if</font></b> lr<font color="#990000">.</font>head <font color="#990000">=</font> <font color="#009900">None</font> <b><font color="#0000FF">then</font></b>
    lr<font color="#990000">.</font>head <font color="#990000">&lt;-</font> <font color="#009900">Some</font> <font color="#FF0000">{</font> hrule <font color="#990000">=</font> rulename<font color="#990000">;</font>
                      involved_set <font color="#990000">=</font> <b><font color="#000080">StringSet</font></b><font color="#990000">.</font>empty<font color="#990000">;</font>
                      eval_set <font color="#990000">=</font> <b><font color="#000080">StringSet</font></b><font color="#990000">.</font>empty <font color="#FF0000">}</font><font color="#990000">;</font>
  <b><font color="#0000FF">let</font></b> lr_head <font color="#990000">=</font> <b><font color="#000080">Option</font></b><font color="#990000">.</font>get lr<font color="#990000">.</font>head <b><font color="#0000FF">in</font></b>
  <b><font color="#0000FF">let</font></b> <b><font color="#0000FF">rec</font></b> loop <font color="#990000">=</font> <b><font color="#0000FF">function</font></b>
    <font color="#990000">|</font> <font color="#990000">[]</font> <font color="#990000">-&gt;</font> <b><font color="#0000FF">assert</font></b> <b><font color="#0000FF">false</font></b>
    <font color="#990000">|</font> l<font color="#990000">::</font>_ <b><font color="#0000FF">when</font></b> l<font color="#990000">.</font>head <font color="#990000">=</font> <font color="#009900">Some</font> lr_head <font color="#990000">-&gt;</font> <font color="#990000">()</font>
    <font color="#990000">|</font> l<font color="#990000">::</font>ls <font color="#990000">-&gt;</font>
        l<font color="#990000">.</font>head <font color="#990000">&lt;-</font> <font color="#009900">Some</font> lr_head<font color="#990000">;</font>
        lr_head<font color="#990000">.</font>involved_set <font color="#990000">&lt;-</font> <b><font color="#000080">StringSet</font></b><font color="#990000">.</font>add l<font color="#990000">.</font>rulename lr_head<font color="#990000">.</font>involved_set<font color="#990000">;</font>
        loop ls
  <b><font color="#0000FF">in</font></b>
  loop <font color="#990000">!</font>lrstack

<b><font color="#0000FF">and</font></b> lr_answer rulename i m <font color="#990000">=</font>
  <b><font color="#0000FF">let</font></b> lr <font color="#990000">=</font> <b><font color="#0000FF">match</font></b> m<font color="#990000">.</font>ans <b><font color="#0000FF">with</font></b>
    <font color="#990000">|</font> <font color="#009900">Answer</font> _ <font color="#990000">-&gt;</font> <b><font color="#0000FF">assert</font></b> <b><font color="#0000FF">false</font></b>
    <font color="#990000">|</font> <font color="#009900">LR</font> lr <font color="#990000">-&gt;</font> lr <b><font color="#0000FF">in</font></b>
  <b><font color="#0000FF">let</font></b> h <font color="#990000">=</font> <b><font color="#0000FF">match</font></b> lr<font color="#990000">.</font>head <b><font color="#0000FF">with</font></b>
    <font color="#990000">|</font> <font color="#009900">None</font> <font color="#990000">-&gt;</font> <b><font color="#0000FF">assert</font></b> <b><font color="#0000FF">false</font></b>
    <font color="#990000">|</font> <font color="#009900">Some</font> h <font color="#990000">-&gt;</font> h <b><font color="#0000FF">in</font></b>
  <b><font color="#0000FF">if</font></b> h<font color="#990000">.</font>hrule <font color="#990000">&lt;&gt;</font> rulename <b><font color="#0000FF">then</font></b>
    lr<font color="#990000">.</font>seed
  <b><font color="#0000FF">else</font></b> <font color="#990000">(</font>
    m<font color="#990000">.</font>ans <font color="#990000">&lt;-</font> <font color="#009900">Answer</font> lr<font color="#990000">.</font>seed<font color="#990000">;</font>
    <b><font color="#0000FF">if</font></b> lr<font color="#990000">.</font>seed <font color="#990000">=</font> <font color="#990000">-</font><font color="#993399">1</font> <b><font color="#0000FF">then</font></b> <font color="#990000">-</font><font color="#993399">1</font>
    <b><font color="#0000FF">else</font></b> grow_lr rulename i m h
  <font color="#990000">)</font>

<b><font color="#0000FF">and</font></b> recall rulename i <font color="#990000">=</font>
  <b><font color="#0000FF">let</font></b> m <font color="#990000">=</font> <b><font color="#0000FF">try</font></b> <font color="#009900">Some</font> <font color="#990000">(</font><b><font color="#000080">Hashtbl</font></b><font color="#990000">.</font>find memo <font color="#990000">(</font>rulename<font color="#990000">,</font> i<font color="#990000">))</font> <b><font color="#0000FF">with</font></b> <font color="#009900">Not_found</font> <font color="#990000">-&gt;</font> <font color="#009900">None</font> <b><font color="#0000FF">in</font></b>
  <b><font color="#0000FF">let</font></b> h <font color="#990000">=</font> <b><font color="#0000FF">try</font></b> <font color="#009900">Some</font> <font color="#990000">(</font><b><font color="#000080">Hashtbl</font></b><font color="#990000">.</font>find heads i<font color="#990000">)</font> <b><font color="#0000FF">with</font></b> <font color="#009900">Not_found</font> <font color="#990000">-&gt;</font> <font color="#009900">None</font> <b><font color="#0000FF">in</font></b>
  <b><font color="#0000FF">match</font></b> h <b><font color="#0000FF">with</font></b>
  <font color="#990000">|</font> <font color="#009900">None</font> <font color="#990000">-&gt;</font> m
  <font color="#990000">|</font> <font color="#009900">Some</font> h <font color="#990000">-&gt;</font>
      <b><font color="#0000FF">if</font></b> m <font color="#990000">=</font> <font color="#009900">None</font> <font color="#990000">&amp;&amp;</font> not <font color="#990000">(</font><b><font color="#000080">StringSet</font></b><font color="#990000">.</font>mem rulename
                            <font color="#990000">(</font><b><font color="#000080">StringSet</font></b><font color="#990000">.</font>add h<font color="#990000">.</font>hrule h<font color="#990000">.</font>involved_set<font color="#990000">))</font> <b><font color="#0000FF">then</font></b>
        <font color="#009900">Some</font> <font color="#FF0000">{</font> ans <font color="#990000">=</font> <font color="#009900">Answer</font> <font color="#990000">(-</font><font color="#993399">1</font><font color="#990000">);</font> pos <font color="#990000">=</font> i <font color="#FF0000">}</font>
      <b><font color="#0000FF">else</font></b> <font color="#990000">(</font>
        <b><font color="#0000FF">if</font></b> <b><font color="#000080">StringSet</font></b><font color="#990000">.</font>mem rulename h<font color="#990000">.</font>eval_set <b><font color="#0000FF">then</font></b> <font color="#990000">(</font>
          h<font color="#990000">.</font>eval_set <font color="#990000">&lt;-</font> <b><font color="#000080">StringSet</font></b><font color="#990000">.</font>remove rulename h<font color="#990000">.</font>eval_set<font color="#990000">;</font>
          <b><font color="#0000FF">let</font></b> r <font color="#990000">=</font> parse rulename i <b><font color="#0000FF">in</font></b>
          <i><font color="#9A1900">(* Original paper RECALL function seems to have a bug ... *)</font></i>
          <b><font color="#0000FF">let</font></b> m <font color="#990000">=</font> <b><font color="#000080">Option</font></b><font color="#990000">.</font>get m <b><font color="#0000FF">in</font></b>
          m<font color="#990000">.</font>ans <font color="#990000">&lt;-</font> <font color="#009900">Answer</font> r<font color="#990000">;</font>
          m<font color="#990000">.</font>pos <font color="#990000">&lt;-</font> <font color="#990000">!</font>pos
        <font color="#990000">);</font>
        m
      <font color="#990000">)</font>

<b><font color="#0000FF">and</font></b> grow_lr rulename i m h <font color="#990000">=</font>
  <b><font color="#000080">Hashtbl</font></b><font color="#990000">.</font>replace heads i h<font color="#990000">;</font> <i><font color="#9A1900">(* A *)</font></i>
  <b><font color="#0000FF">let</font></b> <b><font color="#0000FF">rec</font></b> loop <font color="#990000">()</font> <font color="#990000">=</font>
    pos <font color="#990000">:=</font> i<font color="#990000">;</font>
    h<font color="#990000">.</font>eval_set <font color="#990000">&lt;-</font> h<font color="#990000">.</font>involved_set<font color="#990000">;</font> <i><font color="#9A1900">(* B *)</font></i>
    <b><font color="#0000FF">let</font></b> ans <font color="#990000">=</font> parse rulename i <b><font color="#0000FF">in</font></b>
    <b><font color="#0000FF">if</font></b> ans <font color="#990000">=</font> <font color="#990000">-</font><font color="#993399">1</font> <font color="#990000">||</font> <font color="#990000">!</font>pos <font color="#990000">&lt;=</font> m<font color="#990000">.</font>pos <b><font color="#0000FF">then</font></b> <font color="#990000">()</font>
    <b><font color="#0000FF">else</font></b> <font color="#990000">(</font>
      m<font color="#990000">.</font>ans <font color="#990000">&lt;-</font> <font color="#009900">Answer</font> ans<font color="#990000">;</font>
      m<font color="#990000">.</font>pos <font color="#990000">&lt;-</font> <font color="#990000">!</font>pos<font color="#990000">;</font>
      loop <font color="#990000">()</font>
    <font color="#990000">)</font>
  <b><font color="#0000FF">in</font></b>
  loop <font color="#990000">();</font>
  <b><font color="#000080">Hashtbl</font></b><font color="#990000">.</font>remove heads i<font color="#990000">;</font> <i><font color="#9A1900">(* C *)</font></i>
  pos <font color="#990000">:=</font> m<font color="#990000">.</font>pos<font color="#990000">;</font>
  <b><font color="#0000FF">match</font></b> m<font color="#990000">.</font>ans <b><font color="#0000FF">with</font></b>
  <font color="#990000">|</font> <font color="#009900">Answer</font> r <font color="#990000">-&gt;</font> r
  <font color="#990000">|</font> <font color="#009900">LR</font> _ <font color="#990000">-&gt;</font> <b><font color="#0000FF">assert</font></b> <b><font color="#0000FF">false</font></b>

<b><font color="#0000FF">and</font></b> parse rulename i <font color="#990000">=</font>
  printf <font color="#FF0000">"parse %s %d\n"</font> rulename i<font color="#990000">;</font>
  <b><font color="#0000FF">let</font></b> choices <font color="#990000">=</font>
    <b><font color="#0000FF">try</font></b> <b><font color="#000080">List</font></b><font color="#990000">.</font>assoc rulename grammar
    <b><font color="#0000FF">with</font></b> <font color="#009900">Not_found</font> <font color="#990000">-&gt;</font>
      eprintf <font color="#FF0000">"error in grammar: unknown rulename '%s'\n"</font> rulename<font color="#990000">;</font>
      exit <font color="#993399">1</font> <b><font color="#0000FF">in</font></b>
  <i><font color="#9A1900">(* Try each choice in turn until one matches. *)</font></i>
  <b><font color="#0000FF">try</font></b>
    <b><font color="#000080">List</font></b><font color="#990000">.</font>iter <font color="#990000">(</font>
      <b><font color="#0000FF">fun</font></b> <font color="#990000">(</font>name<font color="#990000">,</font> comment<font color="#990000">,</font> rs<font color="#990000">)</font> <font color="#990000">-&gt;</font>
        printf <font color="#FF0000">"parse %s \"%s\" %d\n"</font> rulename name i<font color="#990000">;</font>
        <b><font color="#0000FF">let</font></b> <b><font color="#0000FF">rec</font></b> loop i <font color="#990000">=</font> <b><font color="#0000FF">function</font></b>
          <font color="#990000">|</font> <font color="#009900">Empty</font> <font color="#990000">::</font> rest <font color="#990000">-&gt;</font>
              loop i rest
          <font color="#990000">|</font> <font color="#009900">NT</font> n <font color="#990000">::</font> rest <font color="#990000">-&gt;</font>
              <b><font color="#0000FF">let</font></b> i' <font color="#990000">=</font> apply_rule n i <b><font color="#0000FF">in</font></b>
              <b><font color="#0000FF">if</font></b> i' <font color="#990000">&gt;=</font> i <b><font color="#0000FF">then</font></b> loop i' rest <b><font color="#0000FF">else</font></b> <font color="#990000">(-</font><font color="#993399">1</font><font color="#990000">)</font>
          <font color="#990000">|</font> <font color="#009900">T</font> str <font color="#990000">::</font> rest <font color="#990000">-&gt;</font>
              <b><font color="#0000FF">let</font></b> slen <font color="#990000">=</font> <b><font color="#000080">String</font></b><font color="#990000">.</font>length str <b><font color="#0000FF">in</font></b>
              <b><font color="#0000FF">if</font></b> i <font color="#990000">+</font> slen <font color="#990000">&gt;</font> len <b><font color="#0000FF">then</font></b> <font color="#990000">(-</font><font color="#993399">1</font><font color="#990000">)</font>
              <b><font color="#0000FF">else</font></b> <font color="#990000">(</font>
                <b><font color="#0000FF">let</font></b> sub <font color="#990000">=</font> <b><font color="#000080">String</font></b><font color="#990000">.</font>sub input i slen <b><font color="#0000FF">in</font></b>
                <b><font color="#0000FF">if</font></b> sub <font color="#990000">=</font> str <b><font color="#0000FF">then</font></b> loop <font color="#990000">(</font>i<font color="#990000">+</font>slen<font color="#990000">)</font> rest
                <b><font color="#0000FF">else</font></b> <font color="#990000">(-</font><font color="#993399">1</font><font color="#990000">)</font>
              <font color="#990000">)</font>
          <font color="#990000">|</font> <font color="#009900">Chars</font> <font color="#990000">(</font>c1<font color="#990000">,</font> c2<font color="#990000">)</font> <font color="#990000">::</font> rest <font color="#990000">-&gt;</font>
              <b><font color="#0000FF">if</font></b> i <font color="#990000">&gt;=</font> len <b><font color="#0000FF">then</font></b> <font color="#990000">(-</font><font color="#993399">1</font><font color="#990000">)</font>
              <b><font color="#0000FF">else</font></b> <b><font color="#0000FF">if</font></b> input<font color="#990000">.[</font>i<font color="#990000">]</font> <font color="#990000">&gt;=</font> c1 <font color="#990000">&amp;&amp;</font> input<font color="#990000">.[</font>i<font color="#990000">]</font> <font color="#990000">&lt;=</font> c2 <b><font color="#0000FF">then</font></b>
                loop <font color="#990000">(</font>i<font color="#990000">+</font><font color="#993399">1</font><font color="#990000">)</font> rest
              <b><font color="#0000FF">else</font></b> <font color="#990000">(-</font><font color="#993399">1</font><font color="#990000">)</font>
          <font color="#990000">|</font> <font color="#009900">Z</font> subr <font color="#990000">::</font> rest <font color="#990000">-&gt;</font>
              <b><font color="#0000FF">let</font></b> i' <font color="#990000">=</font> greedy <font color="#993399">0</font> <font color="#009900">None</font> subr i <b><font color="#0000FF">in</font></b>
              <b><font color="#0000FF">if</font></b> i' <font color="#990000">&gt;=</font> i <b><font color="#0000FF">then</font></b> loop i' rest <b><font color="#0000FF">else</font></b> <font color="#990000">(-</font><font color="#993399">1</font><font color="#990000">)</font>
          <font color="#990000">|</font> <font color="#009900">P</font> subr <font color="#990000">::</font> rest <font color="#990000">-&gt;</font>
              <b><font color="#0000FF">let</font></b> i' <font color="#990000">=</font> greedy <font color="#993399">1</font> <font color="#009900">None</font> subr i <b><font color="#0000FF">in</font></b>
              <b><font color="#0000FF">if</font></b> i' <font color="#990000">&gt;=</font> i <b><font color="#0000FF">then</font></b> loop i' rest <b><font color="#0000FF">else</font></b> <font color="#990000">(-</font><font color="#993399">1</font><font color="#990000">)</font>
          <font color="#990000">|</font> <font color="#009900">Opt</font> subr <font color="#990000">::</font> rest <font color="#990000">-&gt;</font>
              <b><font color="#0000FF">let</font></b> i' <font color="#990000">=</font> greedy <font color="#993399">0</font> <font color="#990000">(</font><font color="#009900">Some</font> <font color="#993399">1</font><font color="#990000">)</font> subr i <b><font color="#0000FF">in</font></b>
              <b><font color="#0000FF">if</font></b> i' <font color="#990000">&gt;=</font> i <b><font color="#0000FF">then</font></b> loop i' rest <b><font color="#0000FF">else</font></b> <font color="#990000">(-</font><font color="#993399">1</font><font color="#990000">)</font>
          <font color="#990000">|</font> <font color="#990000">[]</font> <font color="#990000">-&gt;</font> i
        <b><font color="#0000FF">and</font></b> greedy min max subr i <font color="#990000">=</font> <i><font color="#9A1900">(* implements e* e+ e? *)</font></i>
          printf <font color="#FF0000">"greedy %d %s %d\n"</font> min
            <font color="#990000">(</font><b><font color="#0000FF">match</font></b> max <b><font color="#0000FF">with</font></b> <font color="#009900">None</font> <font color="#990000">-&gt;</font> <font color="#FF0000">"None"</font> <font color="#990000">|</font> <font color="#009900">Some</font> n <font color="#990000">-&gt;</font> sprintf <font color="#FF0000">"Some %d"</font> n<font color="#990000">)</font>
            i<font color="#990000">;</font>
          <b><font color="#0000FF">match</font></b> max <b><font color="#0000FF">with</font></b>
          <font color="#990000">|</font> <font color="#009900">Some</font> <font color="#993399">0</font> <font color="#990000">-&gt;</font> i
          <font color="#990000">|</font> _ <font color="#990000">-&gt;</font>
              <b><font color="#0000FF">if</font></b> min <font color="#990000">&gt;</font> <font color="#993399">0</font> <b><font color="#0000FF">then</font></b> <font color="#990000">(</font>
                <i><font color="#9A1900">(* we must match at least min or fail *)</font></i>
                <b><font color="#0000FF">let</font></b> i' <font color="#990000">=</font> loop i <font color="#990000">[</font>subr<font color="#990000">]</font> <b><font color="#0000FF">in</font></b>
                <b><font color="#0000FF">if</font></b> i' <font color="#990000">&gt;=</font> i <b><font color="#0000FF">then</font></b> greedy <font color="#990000">(</font>min<font color="#990000">-</font><font color="#993399">1</font><font color="#990000">)</font> max subr i'
                <b><font color="#0000FF">else</font></b> <font color="#990000">(-</font><font color="#993399">1</font><font color="#990000">)</font>
              <font color="#990000">)</font> <b><font color="#0000FF">else</font></b> <font color="#990000">(</font>
                <i><font color="#9A1900">(* try matching, doesn't matter if we fail *)</font></i>
                <b><font color="#0000FF">let</font></b> i' <font color="#990000">=</font> loop i <font color="#990000">[</font>subr<font color="#990000">]</font> <b><font color="#0000FF">in</font></b>
                <b><font color="#0000FF">if</font></b> i' <font color="#990000">&gt;=</font> i <b><font color="#0000FF">then</font></b> <font color="#990000">(</font>
                  <b><font color="#0000FF">let</font></b> max <font color="#990000">=</font>
                    <b><font color="#0000FF">match</font></b> max <b><font color="#0000FF">with</font></b> <font color="#009900">None</font> <font color="#990000">-&gt;</font> <font color="#009900">None</font> <font color="#990000">|</font> <font color="#009900">Some</font> n <font color="#990000">-&gt;</font> <font color="#009900">Some</font> <font color="#990000">(</font>n<font color="#990000">-</font><font color="#993399">1</font><font color="#990000">)</font> <b><font color="#0000FF">in</font></b>
                  greedy <font color="#993399">0</font> max subr i'
                <font color="#990000">)</font>
                <b><font color="#0000FF">else</font></b> i <i><font color="#9A1900">(* don't fail, return longest match *)</font></i>
              <font color="#990000">)</font>
        <b><font color="#0000FF">in</font></b>
        <b><font color="#0000FF">let</font></b> i' <font color="#990000">=</font> loop i rs <b><font color="#0000FF">in</font></b>
        <b><font color="#0000FF">if</font></b> i' <font color="#990000">&gt;=</font> i <b><font color="#0000FF">then</font></b> <font color="#990000">(</font>
          printf <font color="#FF0000">"match %s \"%s\" [%d..%d]\n"</font> rulename name i <font color="#990000">(</font>i'<font color="#990000">-</font><font color="#993399">1</font><font color="#990000">);</font>
          raise <font color="#990000">(</font><font color="#009900">Found</font> i'<font color="#990000">)</font>
        <font color="#990000">)</font>
    <font color="#990000">)</font> choices<font color="#990000">;</font>
    <font color="#990000">(-</font><font color="#993399">1</font><font color="#990000">)</font>
  <b><font color="#0000FF">with</font></b>
    <font color="#009900">Found</font> i <font color="#990000">-&gt;</font> i

<b><font color="#0000FF">let</font></b> <font color="#990000">()</font> <font color="#990000">=</font>
  <b><font color="#0000FF">let</font></b> i <font color="#990000">=</font> apply_rule initial_state <font color="#993399">0</font> <b><font color="#0000FF">in</font></b>
  <b><font color="#0000FF">if</font></b> i <font color="#990000">=</font> <font color="#990000">-</font><font color="#993399">1</font> <b><font color="#0000FF">then</font></b> <font color="#990000">(</font>
    eprintf <font color="#FF0000">"parse error: parsing failed\n"</font><font color="#990000">;</font>
    exit <font color="#993399">1</font>
  <font color="#990000">)</font>
  <b><font color="#0000FF">else</font></b> <b><font color="#0000FF">if</font></b> i <font color="#990000">&lt;</font> len <b><font color="#0000FF">then</font></b> <font color="#990000">(</font>
    eprintf <font color="#FF0000">"parse error: extra characters after end of input\n"</font><font color="#990000">;</font>
    exit <font color="#993399">1</font>
  <font color="#990000">)</font>
  <b><font color="#0000FF">else</font></b>
    printf <font color="#FF0000">"parsed OK\n"</font>
</pre>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/rwmj.wordpress.com/2739/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/rwmj.wordpress.com/2739/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rwmj.wordpress.com&#038;blog=6840703&#038;post=2739&#038;subd=rwmj&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://rwmj.wordpress.com/2010/12/29/packrat-parser-with-left-recursion/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/e3ec39948aca0fe41ac29e3e9f8a2649?s=96&#38;d=http%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">rich</media:title>
		</media:content>
	</item>
		<item>
		<title>Tip: libguestfs API: Get the mounted device from a path</title>
		<link>http://rwmj.wordpress.com/2010/12/17/tip-libguestfs-api-get-the-mounted-device-from-a-path/</link>
		<comments>http://rwmj.wordpress.com/2010/12/17/tip-libguestfs-api-get-the-mounted-device-from-a-path/#comments</comments>
		<pubDate>Fri, 17 Dec 2010 11:05:52 +0000</pubDate>
		<dc:creator>rich</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[guestfs]]></category>
		<category><![CDATA[libguestfs]]></category>
		<category><![CDATA[ocaml]]></category>
		<category><![CDATA[tip]]></category>
		<category><![CDATA[virt-tools]]></category>

		<guid isPermaLink="false">http://rwmj.wordpress.com/?p=2700</guid>
		<description><![CDATA[This useful libguestfs API tip shows you how to get the device name that contains a mounted path. You can use this if you want to find out the filesystem type of a path (eg. is this directory mounted on &#8230; <a href="http://rwmj.wordpress.com/2010/12/17/tip-libguestfs-api-get-the-mounted-device-from-a-path/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rwmj.wordpress.com&#038;blog=6840703&#038;post=2700&#038;subd=rwmj&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>This useful <a href="http://libguestfs.org/guestfs.3.html">libguestfs API tip</a> shows you how to get the device name that contains a mounted path.  You can use this if you want to find out the filesystem type of a path (eg. is this directory mounted on ext4?).</p>
<p>What you do is call <a href="http://libguestfs.org/guestfs.3.html#guestfs_mountpoints">guestfs_mountpoints</a> which returns a hash of device name to mount point, eg:</p>
<pre>
/dev/sda1 -&gt; /boot
/dev/sda2 -&gt; /
/dev/sda3 -&gt; /usr
</pre>
<p>Then compare the pathname (&#8220;/boot/grub&#8221;) to each entry in the hash.  If the mountpoint is a string prefix of the path, give this entry a score which is the length of the mountpoint string.  If it is not a prefix, give the entry a score 0.  So:</p>
<pre>
/dev/sda1 -&gt; /boot (score: 5)
/dev/sda2 -&gt; / (score: 1)
/dev/sda3 -&gt; /usr (score: 0)
</pre>
<p>Then sort the entries to pick the highest score.  If the hash is empty or the highest score is 0, then return an error, otherwise return the device with the highest score.</p>
<p>Here is the code to implement this in OCaml:</p>
<pre>
open Printf
open ExtString
open ExtList

let get_mounted_device g path =
  let mps = g#mountpoints () in
  let mps = List.map (
    fun (dev, mp) -&gt;
      if String.starts_with path mp then
        dev, String.length mp
      else
        dev, 0
  ) mps in
  let cmp (_,n1) (_,n2) = compare n2 n1 in
  let mps = List.sort ~cmp mps in
  match mps with
  | [] -&gt;
      invalid_arg (sprintf "%s: not mounted" path)
  | (_,0) :: _ -&gt;
      invalid_arg (sprintf "%s: not found on any filesystem" path)
  | (dev,_) :: _ -&gt; dev
</pre>
<p>To answer the question <i>&#8220;is this directory mounted on ext4?&#8221;</i> you would then call <a href="http://libguestfs.org/guestfs.3.html#guestfs_vfs_type">guestfs_vfs_type</a> on the result of this, eg:</p>
<pre>
if g#vfs_type (get_mounted_device g "/boot/grub") = "ext4" then
  (* do something based on ext4 *)
</pre>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/rwmj.wordpress.com/2700/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/rwmj.wordpress.com/2700/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rwmj.wordpress.com&#038;blog=6840703&#038;post=2700&#038;subd=rwmj&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://rwmj.wordpress.com/2010/12/17/tip-libguestfs-api-get-the-mounted-device-from-a-path/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/e3ec39948aca0fe41ac29e3e9f8a2649?s=96&#38;d=http%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">rich</media:title>
		</media:content>
	</item>
		<item>
		<title>Guest filesystem browser update 5</title>
		<link>http://rwmj.wordpress.com/2010/12/16/guest-filesystem-browser-update-5/</link>
		<comments>http://rwmj.wordpress.com/2010/12/16/guest-filesystem-browser-update-5/#comments</comments>
		<pubDate>Thu, 16 Dec 2010 15:39:30 +0000</pubDate>
		<dc:creator>rich</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[guestfs-browser]]></category>
		<category><![CDATA[libguestfs]]></category>
		<category><![CDATA[ocaml]]></category>
		<category><![CDATA[screenshots]]></category>
		<category><![CDATA[virt-tools]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://rwmj.wordpress.com/?p=2692</guid>
		<description><![CDATA[Update: A Koji scratch build is available here. You can now browse into the Registry on Windows guests:<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rwmj.wordpress.com&#038;blog=6840703&#038;post=2692&#038;subd=rwmj&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p><i>Update: A <a href="http://koji.fedoraproject.org/koji/taskinfo?taskID=2669884">Koji scratch build is available here</a>.</i></p>
<p>You can now browse into the Registry on Windows guests:</p>
<p><a href="http://rwmj.files.wordpress.com/2010/12/screenshot-guest-filesystem-browser-5.png"><img src="http://rwmj.files.wordpress.com/2010/12/screenshot-guest-filesystem-browser-5.png?w=500"></a></p>
<p><a href="http://rwmj.files.wordpress.com/2010/12/screenshot-guest-filesystem-browser-6.png"><img src="http://rwmj.files.wordpress.com/2010/12/screenshot-guest-filesystem-browser-6.png?w=500"></a></p>
<p><a href="http://rwmj.files.wordpress.com/2010/12/screenshot-guest-filesystem-browser-7.png"><img src="http://rwmj.files.wordpress.com/2010/12/screenshot-guest-filesystem-browser-7.png?w=500"></a></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/rwmj.wordpress.com/2692/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/rwmj.wordpress.com/2692/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rwmj.wordpress.com&#038;blog=6840703&#038;post=2692&#038;subd=rwmj&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://rwmj.wordpress.com/2010/12/16/guest-filesystem-browser-update-5/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/e3ec39948aca0fe41ac29e3e9f8a2649?s=96&#38;d=http%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">rich</media:title>
		</media:content>

		<media:content url="http://rwmj.files.wordpress.com/2010/12/screenshot-guest-filesystem-browser-5.png" medium="image" />

		<media:content url="http://rwmj.files.wordpress.com/2010/12/screenshot-guest-filesystem-browser-6.png" medium="image" />

		<media:content url="http://rwmj.files.wordpress.com/2010/12/screenshot-guest-filesystem-browser-7.png" medium="image" />
	</item>
		<item>
		<title>Guest filesystem browser update 4</title>
		<link>http://rwmj.wordpress.com/2010/12/15/guest-filesystem-browser-update-4/</link>
		<comments>http://rwmj.wordpress.com/2010/12/15/guest-filesystem-browser-update-4/#comments</comments>
		<pubDate>Wed, 15 Dec 2010 22:02:52 +0000</pubDate>
		<dc:creator>rich</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[guestfs-browser]]></category>
		<category><![CDATA[libguestfs]]></category>
		<category><![CDATA[ocaml]]></category>
		<category><![CDATA[screenshots]]></category>
		<category><![CDATA[virt-tools]]></category>

		<guid isPermaLink="false">http://rwmj.wordpress.com/?p=2688</guid>
		<description><![CDATA[Grab the latest version from Koji.<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rwmj.wordpress.com&#038;blog=6840703&#038;post=2688&#038;subd=rwmj&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Grab the <a href="http://koji.fedoraproject.org/koji/taskinfo?taskID=2667782">latest version from Koji</a>.</p>
<p><a href="http://rwmj.files.wordpress.com/2010/12/screenshot-guest-filesystem-browser-4.png"><img src="http://rwmj.files.wordpress.com/2010/12/screenshot-guest-filesystem-browser-4.png?w=500"></a></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/rwmj.wordpress.com/2688/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/rwmj.wordpress.com/2688/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rwmj.wordpress.com&#038;blog=6840703&#038;post=2688&#038;subd=rwmj&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://rwmj.wordpress.com/2010/12/15/guest-filesystem-browser-update-4/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/e3ec39948aca0fe41ac29e3e9f8a2649?s=96&#38;d=http%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">rich</media:title>
		</media:content>

		<media:content url="http://rwmj.files.wordpress.com/2010/12/screenshot-guest-filesystem-browser-4.png" medium="image" />
	</item>
		<item>
		<title>Tip: Audit virtual machine for setuid files</title>
		<link>http://rwmj.wordpress.com/2010/12/15/tip-audit-virtual-machine-for-setuid-files/</link>
		<comments>http://rwmj.wordpress.com/2010/12/15/tip-audit-virtual-machine-for-setuid-files/#comments</comments>
		<pubDate>Wed, 15 Dec 2010 13:43:16 +0000</pubDate>
		<dc:creator>rich</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[libguestfs]]></category>
		<category><![CDATA[ocaml]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[tip]]></category>
		<category><![CDATA[virt-tools]]></category>

		<guid isPermaLink="false">http://rwmj.wordpress.com/?p=2681</guid>
		<description><![CDATA[The script after the fold searches for setuid and setgid files on a disk image or in a virtual machine. When you run it you will see output like this: # chmod +x findsuid.ml # ./findsuid.ml RHEL60 /dev/vg_rhel6brewx64/lv_root:/sbin/mount.nfs is setuid &#8230; <a href="http://rwmj.wordpress.com/2010/12/15/tip-audit-virtual-machine-for-setuid-files/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rwmj.wordpress.com&#038;blog=6840703&#038;post=2681&#038;subd=rwmj&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>The script after the fold searches for setuid and setgid files on a disk image or in a virtual machine.  When you run it you will see output like this:</p>
<pre>
# <b>chmod +x findsuid.ml</b>
# <b>./findsuid.ml RHEL60</b>
/dev/vg_rhel6brewx64/lv_root:/sbin/mount.nfs is setuid file
/dev/vg_rhel6brewx64/lv_root:/sbin/netreport is setgid file
/dev/vg_rhel6brewx64/lv_root:/sbin/pam_timestamp_check is setuid file
/dev/vg_rhel6brewx64/lv_root:/sbin/unix_chkpwd is setuid file
/dev/vg_rhel6brewx64/lv_root:/usr/bin/Xorg is setuid file
/dev/vg_rhel6brewx64/lv_root:/usr/bin/at is setuid file
/dev/vg_rhel6brewx64/lv_root:/usr/bin/chage is setuid file
/dev/vg_rhel6brewx64/lv_root:/usr/bin/chfn is setuid file
/dev/vg_rhel6brewx64/lv_root:/usr/bin/chsh is setuid file
<i>etc</i>
</pre>
<p>You could make simple adaptions to this script to audit for all sorts of things of interest: public writeable directories, unusual SELinux labels, hard links to setuid files, over-sized files.  With more work you could look for files with unusual/changed checksums, infected files and so on.</p>
<p><span id="more-2681"></span></p>
<pre>
#<font color="#990000">!/</font>usr<font color="#990000">/</font>bin<font color="#990000">/</font>ocamlrun <font color="#990000">/</font>usr<font color="#990000">/</font>bin<font color="#990000">/</font>ocaml
#load <font color="#FF0000">"unix.cma"</font><font color="#990000">;;</font>
#directory <font color="#FF0000">"+guestfs"</font><font color="#990000">;;</font>
#load <font color="#FF0000">"mlguestfs.cma"</font><font color="#990000">;;</font>

<b><font color="#000080">open</font></b> <font color="#009900">Printf</font>

<b><font color="#0000FF">let</font></b> <font color="#990000">(//)</font> <font color="#990000">=</font> <b><font color="#000080">Filename</font></b><font color="#990000">.</font>concat

<b><font color="#0000FF">let</font></b> <font color="#990000">()</font> <font color="#990000">=</font>
  <b><font color="#0000FF">let</font></b> prog <font color="#990000">=</font> <b><font color="#000080">Filename</font></b><font color="#990000">.</font>basename <b><font color="#000080">Sys</font></b><font color="#990000">.</font>executable_name <b><font color="#0000FF">in</font></b>
  <b><font color="#0000FF">if</font></b> <b><font color="#000080">Array</font></b><font color="#990000">.</font>length <b><font color="#000080">Sys</font></b><font color="#990000">.</font>argv <font color="#990000">&lt;</font> <font color="#993399">2</font> <b><font color="#0000FF">then</font></b> <font color="#990000">(</font>
    eprintf <font color="#FF0000">"Usage: %s guest\n"</font> prog<font color="#990000">;</font>
    exit <font color="#993399">1</font>
  <font color="#990000">);</font>

  <i><font color="#9A1900">(* Open guest domain. *)</font></i>
  <b><font color="#0000FF">let</font></b> g <font color="#990000">=</font> <b><font color="#0000FF">new</font></b> <b><font color="#000080">Guestfs</font></b><font color="#990000">.</font>guestfs <font color="#990000">()</font> <b><font color="#0000FF">in</font></b>
  ignore <font color="#990000">(</font>g#add_domain <font color="#990000">~</font>readonly<font color="#990000">:</font><b><font color="#0000FF">true</font></b> <b><font color="#000080">Sys</font></b><font color="#990000">.</font>argv<font color="#990000">.(</font><font color="#993399">1</font><font color="#990000">));</font>
  g#launch <font color="#990000">();</font>

  <i><font color="#9A1900">(* If VMs could be encrypted you would have to</font></i>
<i><font color="#9A1900">   * add additional calls to luks* here.</font></i>
<i><font color="#9A1900">   * See fish/inspect.c:inspect_do_decrypt()</font></i>
<i><font color="#9A1900">   *)</font></i>

  <i><font color="#9A1900">(* Useful functions to test file types.  Note</font></i>
<i><font color="#9A1900">   * can't use the regular stat functions, because</font></i>
<i><font color="#9A1900">   * these modes are the ones defined in the Linux</font></i>
<i><font color="#9A1900">   * ABI, not the host OS.</font></i>
<i><font color="#9A1900">   *)</font></i>
  <b><font color="#0000FF">let</font></b> <b><font color="#0000FF">rec</font></b> file_type mask mode <font color="#990000">=</font>
    <b><font color="#000080">Int64</font></b><font color="#990000">.</font>logand mode 0o170000L <font color="#990000">=</font> mask
  <i><font color="#9A1900">(*and is_socket mode =</font></i>
<i><font color="#9A1900">    file_type 0o140000L mode</font></i>
<i><font color="#9A1900">  and is_symlink mode =</font></i>
<i><font color="#9A1900">    file_type 0o120000L mode*)</font></i>
  <b><font color="#0000FF">and</font></b> is_regular_file mode <font color="#990000">=</font>
    file_type 0o100000L mode
  <i><font color="#9A1900">(*and is_block mode =</font></i>
<i><font color="#9A1900">    file_type 0o060000L mode*)</font></i>
  <b><font color="#0000FF">and</font></b> is_directory mode <font color="#990000">=</font>
    file_type 0o040000L mode
  <i><font color="#9A1900">(*and is_char mode =</font></i>
<i><font color="#9A1900">    file_type 0o020000L mode</font></i>
<i><font color="#9A1900">  and is_fifo mode =</font></i>
<i><font color="#9A1900">    file_type 0o010000L mode*)</font></i>

  <b><font color="#0000FF">and</font></b> is_suid mode <font color="#990000">=</font> test_bit 0o4000L mode
  <b><font color="#0000FF">and</font></b> is_sgid mode <font color="#990000">=</font> test_bit 0o2000L mode
  <i><font color="#9A1900">(*and is_svtx mode = test_bit 0o1000L mode*)</font></i>

  <b><font color="#0000FF">and</font></b> test_bit mask mode <font color="#990000">=</font>
    <b><font color="#000080">Int64</font></b><font color="#990000">.</font>logand mode mask <font color="#990000">=</font> mask
  <b><font color="#0000FF">in</font></b>

  <i><font color="#9A1900">(* Visit each file in the mounted filesystem.</font></i>
<i><font color="#9A1900">   * TODO: Add libguestfs APIs to make this simpler</font></i>
<i><font color="#9A1900">   * and faster.</font></i>
<i><font color="#9A1900">   *)</font></i>
  <b><font color="#0000FF">let</font></b> <b><font color="#0000FF">rec</font></b> visit f dir <font color="#990000">=</font>
    <b><font color="#0000FF">let</font></b> names <font color="#990000">=</font> g#ls dir <b><font color="#0000FF">in</font></b>
    <b><font color="#0000FF">let</font></b> stats <font color="#990000">=</font> lstatlist dir names <b><font color="#0000FF">in</font></b>
    <b><font color="#0000FF">let</font></b> entries <font color="#990000">=</font> <b><font color="#000080">List</font></b><font color="#990000">.</font>combine <font color="#990000">(</font><b><font color="#000080">Array</font></b><font color="#990000">.</font>to_list names<font color="#990000">)</font> stats <b><font color="#0000FF">in</font></b>
    <b><font color="#000080">List</font></b><font color="#990000">.</font>iter <font color="#990000">(</font>f dir<font color="#990000">)</font> entries<font color="#990000">;</font>
    <b><font color="#0000FF">let</font></b> dirs <font color="#990000">=</font> <b><font color="#000080">List</font></b><font color="#990000">.</font>filter entry_is_dir entries <b><font color="#0000FF">in</font></b>
    <b><font color="#000080">List</font></b><font color="#990000">.</font>iter <font color="#990000">(</font>
      <b><font color="#0000FF">fun</font></b> <font color="#990000">(</font>name<font color="#990000">,</font> stat<font color="#990000">)</font> <font color="#990000">-&gt;</font>
        visit f <font color="#990000">(</font>dir <font color="#990000">//</font> name<font color="#990000">)</font>
    <font color="#990000">)</font> dirs
  <b><font color="#0000FF">and</font></b> entry_is_dir <font color="#990000">(</font>_<font color="#990000">,</font> <font color="#FF0000">{</font> <b><font color="#000080">Guestfs</font></b><font color="#990000">.</font>mode <font color="#990000">=</font> mode <font color="#FF0000">}</font><font color="#990000">)</font> <font color="#990000">=</font>
    is_directory mode
  <b><font color="#0000FF">and</font></b> lstatlist dir <font color="#990000">=</font> <b><font color="#0000FF">function</font></b>
    <font color="#990000">|</font> <font color="#990000">[|</font> <font color="#990000">|]</font> <font color="#990000">-&gt;</font> <font color="#990000">[]</font>
    <font color="#990000">|</font> names <font color="#990000">-&gt;</font>
        <i><font color="#9A1900">(* Split large requests so we don't overrun</font></i>
<i><font color="#9A1900">         * the libguestfs protocol limit.</font></i>
<i><font color="#9A1900">         *)</font></i>
        <b><font color="#0000FF">let</font></b> len <font color="#990000">=</font> <b><font color="#000080">Array</font></b><font color="#990000">.</font>length names <b><font color="#0000FF">in</font></b>
        <b><font color="#0000FF">let</font></b> first<font color="#990000">,</font> rest <font color="#990000">=</font>
          <b><font color="#0000FF">if</font></b> len <font color="#990000">&lt;=</font> <font color="#993399">1000</font> <b><font color="#0000FF">then</font></b> names<font color="#990000">,</font> <font color="#990000">[|</font> <font color="#990000">|]</font>
          <b><font color="#0000FF">else</font></b> <font color="#990000">(</font>
            <b><font color="#000080">Array</font></b><font color="#990000">.</font>sub names <font color="#993399">0</font> <font color="#993399">1000</font><font color="#990000">,</font>
            <b><font color="#000080">Array</font></b><font color="#990000">.</font>sub names <font color="#993399">1000</font> <font color="#990000">(</font>len<font color="#990000">-</font><font color="#993399">1000</font><font color="#990000">)</font>
          <font color="#990000">)</font> <b><font color="#0000FF">in</font></b>
        <b><font color="#0000FF">let</font></b> stats <font color="#990000">=</font> g#lstatlist dir first <b><font color="#0000FF">in</font></b>
        <b><font color="#000080">Array</font></b><font color="#990000">.</font>to_list stats @ lstatlist dir rest
  <b><font color="#0000FF">in</font></b>

  <i><font color="#9A1900">(* Test each file, printing those that match</font></i>
<i><font color="#9A1900">   * the criteria.</font></i>
<i><font color="#9A1900">   *)</font></i>
  <b><font color="#0000FF">let</font></b> search dev dir <font color="#990000">(</font>name<font color="#990000">,</font> <font color="#FF0000">{</font> <b><font color="#000080">Guestfs</font></b><font color="#990000">.</font>mode <font color="#990000">=</font> mode <font color="#FF0000">}</font><font color="#990000">)</font> <font color="#990000">=</font>
    <b><font color="#0000FF">if</font></b> is_regular_file mode <font color="#990000">&amp;&amp;</font> is_suid mode <b><font color="#0000FF">then</font></b>
      printf <font color="#FF0000">"%s:%s is setuid file\n%!"</font> dev <font color="#990000">(</font>dir <font color="#990000">//</font> name<font color="#990000">)</font>
    <b><font color="#0000FF">else</font></b> <b><font color="#0000FF">if</font></b> is_regular_file mode <font color="#990000">&amp;&amp;</font> is_sgid mode <b><font color="#0000FF">then</font></b>
      printf <font color="#FF0000">"%s:%s is setgid file\n%!"</font> dev <font color="#990000">(</font>dir <font color="#990000">//</font> name<font color="#990000">)</font>
  <b><font color="#0000FF">in</font></b>

  <i><font color="#9A1900">(* Search every mountable filesystem. *)</font></i>
  <b><font color="#0000FF">let</font></b> fses <font color="#990000">=</font> g#list_filesystems <font color="#990000">()</font> <b><font color="#0000FF">in</font></b>
  <b><font color="#000080">List</font></b><font color="#990000">.</font>iter <font color="#990000">(</font>
    <b><font color="#0000FF">fun</font></b> <font color="#990000">(</font>dev<font color="#990000">,</font> _<font color="#990000">)</font> <font color="#990000">-&gt;</font>
      g#umount_all <font color="#990000">();</font>
      <b><font color="#0000FF">let</font></b> mounted_ok <font color="#990000">=</font>
        <b><font color="#0000FF">try</font></b> g#mount_ro dev <font color="#FF0000">"/"</font><font color="#990000">;</font> <b><font color="#0000FF">true</font></b>
        <b><font color="#0000FF">with</font></b> <font color="#009900">exn</font> <font color="#990000">-&gt;</font> <b><font color="#0000FF">false</font></b> <b><font color="#0000FF">in</font></b>
      <b><font color="#0000FF">if</font></b> mounted_ok <b><font color="#0000FF">then</font></b>
        visit <font color="#990000">(</font>search dev<font color="#990000">)</font> <font color="#FF0000">"/"</font>
  <font color="#990000">)</font> fses
</pre>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/rwmj.wordpress.com/2681/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/rwmj.wordpress.com/2681/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rwmj.wordpress.com&#038;blog=6840703&#038;post=2681&#038;subd=rwmj&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://rwmj.wordpress.com/2010/12/15/tip-audit-virtual-machine-for-setuid-files/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/e3ec39948aca0fe41ac29e3e9f8a2649?s=96&#38;d=http%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">rich</media:title>
		</media:content>
	</item>
		<item>
		<title>libguestfs examples in C, OCaml, Python and Ruby</title>
		<link>http://rwmj.wordpress.com/2010/11/24/libguestfs-examples-in-c-ocaml-python-and-ruby/</link>
		<comments>http://rwmj.wordpress.com/2010/11/24/libguestfs-examples-in-c-ocaml-python-and-ruby/#comments</comments>
		<pubDate>Wed, 24 Nov 2010 22:40:07 +0000</pubDate>
		<dc:creator>rich</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[c++]]></category>
		<category><![CDATA[libguestfs]]></category>
		<category><![CDATA[ocaml]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[virt-tools]]></category>

		<guid isPermaLink="false">http://rwmj.wordpress.com/?p=2589</guid>
		<description><![CDATA[I took two example C programs (one appeared on this blog earlier) and translated them precisely into OCaml, Python and Ruby: C/C++ example OCaml example Python example Ruby example<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rwmj.wordpress.com&#038;blog=6840703&#038;post=2589&#038;subd=rwmj&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>I took two example C programs (one <a href="https://rwmj.wordpress.com/2010/11/17/example-using-the-libguestfs-api-from-c/">appeared on this blog earlier</a>) and translated them precisely into OCaml, Python and Ruby:</p>
<ol>
<li> <a href="http://libguestfs.org/guestfs-examples.3.html">C/C++ example</a>
<li> <a href="http://libguestfs.org/guestfs-ocaml.3.html">OCaml example</a>
<li> <a href="http://libguestfs.org/guestfs-python.3.html">Python example</a>
<li> <a href="http://libguestfs.org/guestfs-ruby.3.html">Ruby example</a>
</ol>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/rwmj.wordpress.com/2589/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/rwmj.wordpress.com/2589/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rwmj.wordpress.com&#038;blog=6840703&#038;post=2589&#038;subd=rwmj&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://rwmj.wordpress.com/2010/11/24/libguestfs-examples-in-c-ocaml-python-and-ruby/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/e3ec39948aca0fe41ac29e3e9f8a2649?s=96&#38;d=http%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">rich</media:title>
		</media:content>
	</item>
	</channel>
</rss>