[augeas-devel] Hash-like entries across multiple lines

Free Ekanayaka free at 64studio.com
Mon Aug 25 08:22:49 UTC 2008


Hi,

I am working on a lens to parse /etc/dhclient.conf (you find the
current code below), and I would like to parse a sequence of
statements like:

send fqdn.fqdn \"grosse.fugue.com.\";
send fqdn.encoded on;

into a tree like:

{ "send" 
     { "fqdn.fqdn" = "\"grosse.fugue.com.\"" }
     { "fqdn.encoded" = "on" } }

Note that the two statements could also be in different positions in
the file, not only one right after the other, for example:

send fqdn.fqdn \"grosse.fugue.com.\";
some statement;
more statements at will;
send fqdn.encoded on;

So the problem I am facing is how to add subnodes to a tree node which
was created before. I'm not sure if this is possible/acceptable..

Currently I'm creating different tree nodes for the two statements (see
test_dhclient.aug), like:

    { "send" 
       { "fqdn.fqdn" = "\"grosse.fugue.com.\"" } }
    { "send" 
       { "fqdn.encoded" = "on" } }

However I'd like to be able to have a single /send node with all its
hashed key/values pairs.

Ciao,

Free

================================ dhclient.aug =================================

(* Intefraces module for Augeas
 Author: Free Ekanayaka <free at 64studio.com>

 Reference: man dhclient.conf
 The only difference with the reference syntax is that this lens assumes
 that statements end with a new line, while the reference syntax allows
 new statements to be started right after the trailing ";" of the previous
 statement. This should not be a problem in real-life configuration files
 as statements get usually splitted across several lines, rather than merged
 in a single one.

*)

module Dhclient =

   autoload xfm

(************************************************************************
 *                           USEFUL PRIMITIVES
 *************************************************************************)

let eol     = Util.eol
let spc     = Util.del_ws_spc
let comment = Util.comment
let empty   = Util.empty

(* Define basic types *)
let comma  = del /[ \t\n]*,[ \t\n]*/ ","
let scolon = del /[ \t]*;/ ";"
let word   = /[A-Za-z0-9_.-]+(\[[0-9]+\])?/
let value  = store /[^\\#,; \t\n]+/
let sep    = del /[ \t\n]*/ " "
let indent = del /\n?[ \t]/ " "

(************************************************************************
 *                          ARRAY STATEMENTS
 *************************************************************************)

let array (t:string) = del t t . label t . indent .
     [ sep   . seq t . value ] .
     [ comma . seq t . value ]* .
     scolon . (eol|comment)
let a_statement_key  = /request|require/
let a_statement = (
     [ array "request" ] |
     [ array "require" ] )

(************************************************************************
 *                          HASH STATEMENTS
 *************************************************************************)

let hash (t:string) = 
     del t t . label t .
     indent .
     [ sep . key word . indent . sep . value ]
let h_statement_key  = /send/
let h_statement = (
     [ hash "send" . scolon . (eol|comment) ] )

(************************************************************************
 *                         SIMPLE STATEMENTS
 *************************************************************************)

let s_statement_key  = word - (a_statement_key | h_statement_key)
let s_statement = [
     key s_statement_key .
     indent . sep .
     value .
     scolon . (eol|comment) ]

let statement = (a_statement|s_statement |h_statement )

let lns = (empty | comment | statement)*

let filter = incl "/etc/dhcp3/dhclient.conf"
            . Util.stdexcl

let xfm = transform lns filter

========================= test_dhclient.aug ===============================

module Test_dhclient = 

    let conf ="# Sample dhclient.conf
#

# Protocol timing
timeout 3; # Expect a fast server
retry 
      10;

# Lease requirements and requests
request
	subnet-mask, 
  broadcast-address,
	ntp-servers;
require subnet-mask, domain-name-servers; # We want these

# Dynamic DNS
send
	fqdn.fqdn 
	  \"grosse.fugue.com.\";
send fqdn.encoded on;
"

    test Dhclient.lns get conf =
        { "#comment" = "Sample dhclient.conf" }
        {}
        {}
        { "#comment" = "Protocol timing" }
        { "timeout" = "3"
           { "#comment" = "Expect a fast server" } }
        { "retry" = "10" }
        {}
        { "#comment" = "Lease requirements and requests" }
        { "request" 
           { "1" = "subnet-mask" }
           { "2" = "broadcast-address" }
           { "3" = "ntp-servers" } }
        { "require" 
           { "1" = "subnet-mask" }
           { "2" = "domain-name-servers" }
           { "#comment" = "We want these" } } 
        {}
        { "#comment" = "Dynamic DNS" }
        { "send" 
           { "fqdn.fqdn" = "\"grosse.fugue.com.\"" } }
        { "send" 
           { "fqdn.encoded" = "on" } }




More information about the augeas-devel mailing list