[augeas-devel] [PATCH 02/11] Notes on new XPath grammar

David Lutterkort lutter at redhat.com
Mon Jan 26 05:41:15 UTC 2009


---
 doc/xpath.txt |  488 +++++++++++++++++++++++++++++++++++++--------------------
 1 files changed, 320 insertions(+), 168 deletions(-)

diff --git a/doc/xpath.txt b/doc/xpath.txt
index 0d419f1..92d9814 100644
--- a/doc/xpath.txt
+++ b/doc/xpath.txt
@@ -1,169 +1,321 @@
-From http://www.w3.org/TR/2007/REC-xpath20-20070123/#id-grammar
-
-[ 1] XPath    ::= Expr
-[ 2] Expr     ::= ExprSingle ("," ExprSingle)*
-[ 3] ExprSingle ::= ForExpr | QuantifiedExpr | IfExpr | OrExpr
-[ 4] ForExpr     ::= SimpleForClause "return" ExprSingle
-[ 5] SimpleForClause ::= "for" "$" VarName "in" ExprSingle ("," "$" VarName "in" ExprSingle)*
-[ 6] QuantifiedExpr ::= ("some" | "every") "$" VarName "in" ExprSingle ("," "$" VarName "in" ExprSingle)* "satisfies" ExprSingle
-[ 7] IfExpr ::= "if" "(" Expr ")" "then" ExprSingle "else" ExprSingle
-[ 8] OrExpr ::= AndExpr ( "or" AndExpr )*
-[ 9] AndExpr ::= ComparisonExpr ( "and" ComparisonExpr )*
-[10] ComparisonExpr ::= RangeExpr ( (ValueComp | GeneralComp | NodeComp) RangeExpr )?
-[11] RangeExpr ::= AdditiveExpr ( "to" AdditiveExpr )?
-[12] AdditiveExpr ::= MultiplicativeExpr ( ("+" | "-") MultiplicativeExpr )*
-[13] MultiplicativeExpr ::= UnionExpr ( ("*" | "div" | "idiv" | "mod") UnionExpr )*
-[14] UnionExpr ::= IntersectExceptExpr ( ("union" | "|") IntersectExceptExpr )*
-[15] IntersectExceptExpr ::= InstanceofExpr ( ("intersect" | "except") InstanceofExpr )*
-[16] InstanceofExpr ::= TreatExpr ( "instance" "of" SequenceType )?
-[17] TreatExpr      ::= CastableExpr ( "treat" "as" SequenceType )?
-[18] CastableExpr   ::= CastExpr ( "castable" "as" SingleType )?
-[19] CastExpr       ::= UnaryExpr ( "cast" "as" SingleType )?
-[20] UnaryExpr      ::= ("-" | "+")* ValueExpr
-[21] ValueExpr      ::= PathExpr
-[22] GeneralComp    ::= "=" | "!=" | "<" | "<=" | ">" | ">="
-[23] ValueComp      ::= "eq" | "ne" | "lt" | "le" | "gt" | "ge"
-[24] NodeComp       ::= "is" | "<<" | ">>"
-[25] PathExpr       ::= ("/" RelativePathExpr?) | ("//" RelativePathExpr)
-| RelativePathExpr  /* xgs: leading-lone-slash */
-[26] RelativePathExpr ::= StepExpr (("/" | "//") StepExpr)*
-[27] StepExpr     ::= FilterExpr | AxisStep
-[28] AxisStep     ::= (ReverseStep | ForwardStep) PredicateList
-[29] ForwardStep  ::= (ForwardAxis NodeTest) | AbbrevForwardStep
-[30] ForwardAxis  ::= ("child" "::")
-                    | ("descendant" "::")
-                    | ("attribute" "::")
-                    | ("self" "::")
-                    | ("descendant-or-self" "::")
-                    | ("following-sibling" "::")
-                    | ("following" "::")
-                    | ("namespace" "::")
-[31] AbbrevForwardStep ::= "@"? NodeTest
-[32] ReverseStep ::= (ReverseAxis NodeTest) | AbbrevReverseStep
-[33] ReverseAxis ::= ("parent" "::")
-                   | ("ancestor" "::")
-                   | ("preceding-sibling" "::")
-                   | ("preceding" "::")
-                   | ("ancestor-or-self" "::")
-[34] AbbrevReverseStep ::= ".."
-[35] NodeTest ::= KindTest | NameTest
-[36] NameTest ::= QName | Wildcard
-[37] Wildcard ::= "*" | (NCName ":" "*") | ("*" ":" NCName)  /* ws: explicit */
-[38] FilterExpr ::= PrimaryExpr PredicateList
-[39] PredicateList ::= Predicate*
-[40] Predicate ::= "[" Expr "]"
-[41] PrimaryExpr ::= Literal | VarRef | ParenthesizedExpr | ContextItemExpr | FunctionCall
-[42] Literal ::= NumericLiteral | StringLiteral
-[43] NumericLiteral ::= IntegerLiteral | DecimalLiteral | DoubleLiteral
-[44] VarRef ::= "$" VarName
-[45] VarName ::= QName
-[46] ParenthesizedExpr ::= "(" Expr? ")"
-[47] ContextItemExpr ::= "."
-[48] FunctionCall    ::= QName "(" (ExprSingle ("," ExprSingle)*)? ")"  /* xgs: reserved-function-names */
-    /* gn: parens */
-[49] SingleType      ::= AtomicType "?"?
-[50] SequenceType    ::= ("empty-sequence" "(" ")")
-                       | (ItemType OccurrenceIndicator?)
-[51] OccurrenceIndicator ::= "?" | "*" | "+"  /* xgs: occurrence-indicators */
-[52] ItemType            ::= KindTest | ("item" "(" ")") | AtomicType
-[53] AtomicType          ::= QName
-[54] KindTest            ::= DocumentTest
-                           | ElementTest
-                           | AttributeTest
-                           | SchemaElementTest
-                           | SchemaAttributeTest
-                           | PITest
-                           | CommentTest
-                           | TextTest
-                           | AnyKindTest
-[55] AnyKindTest  ::= "node" "(" ")"
-[56] DocumentTest ::= "document-node" "(" (ElementTest | SchemaElementTest)? ")"
-[57] TextTest     ::= "text" "(" ")"
-[58] CommentTest  ::= "comment" "(" ")"
-[59] PITest       ::= "processing-instruction" "(" (NCName | StringLiteral)? ")"
-[60] AttributeTest::= "attribute" "(" (AttribNameOrWildcard ("," TypeName)?)? ")"
-[61] AttribNameOrWildcard ::= AttributeName | "*"
-[62] SchemaAttributeTest  ::= "schema-attribute" "(" AttributeDeclaration ")"
-[63] AttributeDeclaration ::= AttributeName
-[64] ElementTest ::= "element" "(" (ElementNameOrWildcard ("," TypeName "?"?)?)? ")"
-[65] ElementNameOrWildcard ::= ElementName | "*"
-[66] SchemaElementTest ::= "schema-element" "(" ElementDeclaration ")"
-[67] ElementDeclaration ::= ElementName
-[68] AttributeName ::= QName
-[69] ElementName ::= QName
-[70] TypeName ::= QName
-
-Reduced grammar for Augeas:
-
-[ 1] XPath    ::= Expr
-[ 2] Expr     ::= ExprSingle ("," ExprSingle)*
-[ 3] ExprSingle ::= OrExpr
-[ 8] OrExpr ::= AndExpr ( "or" AndExpr )*
-[ 9] AndExpr ::= ComparisonExpr ( "and" ComparisonExpr )*
-[10] ComparisonExpr ::= AdditiveExpr ((ValueComp | GeneralComp | NodeComp) AdditiveExpr)?
-[12] AdditiveExpr ::= MultiplicativeExpr ( ("+" | "-") MultiplicativeExpr )*
-[13] MultiplicativeExpr ::= UnaryExpr ( ("*" | "div" | "idiv" | "mod") UnaryExpr )*
-[20] UnaryExpr      ::= ("-" | "+")* PathExpr
-[22] GeneralComp    ::= "=" | "!=" | "<" | "<=" | ">" | ">="
-[23] ValueComp      ::= "eq" | "ne" | "lt" | "le" | "gt" | "ge"
-[24] NodeComp       ::= "is"
-[25] PathExpr       ::= ("/" RelativePathExpr?) | ("//" RelativePathExpr)
-                      | RelativePathExpr  /* xgs: leading-lone-slash */
-[26] RelativePathExpr ::= StepExpr (("/" | "//") StepExpr)*
-[27] StepExpr     ::= FilterExpr | AxisStep
-[28] AxisStep     ::= (ReverseStep | ForwardStep) PredicateList
-[29] ForwardStep  ::= (ForwardAxis NodeTest) | AbbrevForwardStep
-[30] ForwardAxis  ::= ("child" "::")
-                    | ("descendant" "::")
-                    | ("attribute" "::")
-                    | ("self" "::")
-                    | ("descendant-or-self" "::")
-                    | ("following-sibling" "::")
-                    | ("following" "::")
-                    | ("namespace" "::")
-[31] AbbrevForwardStep ::= "@"? NodeTest
-[32] ReverseStep ::= (ReverseAxis NodeTest) | AbbrevReverseStep
-[33] ReverseAxis ::= ("parent" "::")
-                   | ("ancestor" "::")
-                   | ("preceding-sibling" "::")
-                   | ("preceding" "::")
-                   | ("ancestor-or-self" "::")
-[34] AbbrevReverseStep ::= ".."
-[35] NodeTest ::= KindTest | NameTest
-[36] NameTest ::= QName | Wildcard
-[37] Wildcard ::= "*" | (NCName ":" "*") | ("*" ":" NCName)  /* ws: explicit */
-[38] FilterExpr ::= PrimaryExpr PredicateList
-[39] PredicateList ::= Predicate*
-[40] Predicate ::= "[" Expr "]"
-[41] PrimaryExpr ::= Literal | VarRef | ParenthesizedExpr | ContextItemExpr | FunctionCall
-[42] Literal ::= NumericLiteral | StringLiteral
-[43] NumericLiteral ::= IntegerLiteral | DecimalLiteral | DoubleLiteral
-[44] VarRef ::= "$" VarName
-[45] VarName ::= QName
-[46] ParenthesizedExpr ::= "(" Expr? ")"
-[47] ContextItemExpr ::= "."
-[48] FunctionCall    ::= QName "(" (ExprSingle ("," ExprSingle)*)? ")"  /* xgs: reserved-function-names */
-    /* gn: parens */
-[51] OccurrenceIndicator ::= "?" | "*" | "+"  /* xgs: occurrence-indicators */
-[54] KindTest            ::= TextTest | AnyKindTest
-[55] AnyKindTest  ::= "node" "(" ")"
-[57] TextTest     ::= "text" "(" ")"
-[61] AttribNameOrWildcard ::= AttributeName | "*"
-[68] AttributeName ::= QName
-
-Really needed:
-
- /files/etc/hosts/*[ipaddr = "127.0.0.1"]
- /files/etc/hosts/*[ipaddr = "127.0.0.1"]/alias[last() - 1]
- /augeas/files//error
- /files/etc/puppet/puppet.conf/section[value() = "main"]/vardir
-
-PathExpr     ::= (("/" | "//") StepExpr)+
-StepExpr     ::= (Name | "*") PredicateList
-RedicateList ::= "[" PredExpr "]" *
-PredExpr     ::= ValueTest | PositionTest
-ValueTest    ::= (Name | "value()") "=" ValueLiteral
-PositionTest ::= Number | "last()" ( "-" Number )
-Name         ::= /[^/\[]+/
-ValueLiteral ::= '"' /[^"]*/ '"' | "'" /[^']*/ "'" | "nil"
+Path expressions
+================
+
+In the public API, especially for aug_match and aug_get, tree nodes can be
+identified with a powerful syntax, that is modelled on the XPath syntax for
+XML documents.
+
+In the simplest case, a path expression just lists a path to some node in
+the tree, for example,
+
+   /files/etc/hosts/1/ipaddr
+
+If multiple nodes have the same label, one of them can be picked out by
+providing its position, either counting from the first such node (at
+position 1) or counting from the end. For example, the second alias of the
+first host entry is
+
+   /files/etc/hosts/1/alias[2]
+
+and the penultimate alias is
+
+   /files/etc/hosts/1/alias[last() - 1]
+
+For /etc/hosts, each entry can be thought of as a primary key (the ipaddr)
+and additional attributes relating to that primary key, namely the
+canonical host name and its aliases. It is therefore natural to refer to
+host entries by their ipaddr, not by the synthetic sequence number in their
+path. The canonical name of the host entry with ipaddr 127.0.0.1 can be
+found with
+
+   /files/etc/hosts/*[ipaddr = "127.0.0.1"]/canonical
+
+or, equivalently, with
+
+   /files/etc/hosts/*/canonical[../ipaddr = "127.0.0.1"]
+
+The canonical names of all hosts that have at least one alias:
+
+   /files/etc/hosts/*/canonical[../alias]
+
+It is also possible to search bigger parts of the tree by using '//'. For
+example, all nodes called 'ipaddr' underneath /files/etc can be found with
+
+   /files/etc//ipaddr
+
+This is handy for finding errors reported by Augeas underneath /augeas:
+
+   /augeas//error
+
+A lazy way to find localhost is
+
+  /files/etc//ipaddr[. = '127.0.0.1']
+
+The vardir entry in the main section of puppet.conf is at
+
+  /files/etc/puppet/puppet.conf/section[. = "main"]/vardir
+
+All pam entries that use the system-auth module:
+
+  /files/etc/pam.d/*[.//module = "system-auth"]
+
+More examples can be found in tests/xpath.tests
+
+One further extension that might be useful is to add boolean operators for
+predicates, so that we can write
+
+ /files/etc/hosts/ipaddr[../alias = 'localhost' or ../canonical = 'localhost']
+
+Grammar for path expressions
+============================
+
+Formally, path expressions are generated by this grammar. The grammar uses
+nonterminals from the XPath 1.0 grammar to point out the similarities
+between XPath and Augeas path expressions.
+
+Unfortunately, the production for PathExpr is ambiguous, since Augeas is
+too liberal in what it allows as labels for tree nodes: the expression '42'
+can either be the number 42 (a PrimaryExpr) or the RelativeLocationPath
+'child::42'. The reason for this ambiguity is that we allow node names like
+'42' in the tree; rather than forbid them, we resolve the ambiguity by
+always parsing '42' as a number, and requiring that the user write the
+RelativeLocationPath in a different form, e.g. 'child::42' or './42'.
+
+LocationPath ::= RelativeLocationPath | AbsoluteLocationPath
+
+AbsoluteLocationPath ::= '/' RelativeLocationPath?
+                       | AbbreviatedAbsoluteLocationPath
+AbbreviatedAbsoluteLocationPath ::= '//' RelativeLocationPath
+
+RelativeLocationPath ::= Step
+                       | RelativeLocationPath '/' Step
+                       | AbbreviatedRelativeLocationPath
+AbbreviatedRelativeLocationPath ::= RelativeLocationPath '//' Step
+
+Step ::= AxisSpecifier NameTest Predicate* | '.' | '..'
+AxisSpecifier ::= AxisName '::' | <epsilon>
+AxisName ::= 'ancestor'
+           | 'ancestor-or-self'
+           | 'child'
+           | 'descendant'
+           | 'descendant-or-self'
+           | 'parent'
+           | 'self'
+           | 'root'
+NameTest     ::= '*' | Name
+Predicate    ::= "[" Expr "]" *
+
+PathExpr ::= LocationPath | PrimaryExpr
+PrimaryExpr ::= Literal
+              | Number
+              | FunctionCall
+FunctionCall ::= Name '(' ( Expr ( ',' Expr )* )? ')'
+
+Expr ::= EqualityExpr
+EqualityExpr ::= AdditiveExpr (EqualityOp AdditiveExpr)?
+EqualityOp ::= "=" | "!="
+AdditiveExpr ::= MultiplicativeExpr (AdditiveOp MultiplicativeExpr)*
+AdditiveOp   ::= '+' | '-'
+MultiplicativeExpr ::= PathExpr ('*' PathExpr)*
+
+Literal ::= '"' /[^"]* / '"' | "'" /[^']* / "'"
 Number       ::= /[0-9]+/
+Name ::= /[^/\[ \t\n]+/
+
+
+Additional stuff
+================
+
+Just for reference, not really interesting as documentation
+
+XPath 1.0 (from http://www.w3.org/TR/xpath)
+-------------------------------------------
+
+[ 1] LocationPath ::= RelativeLocationPath | AbsoluteLocationPath
+[ 2] AbsoluteLocationPath ::= '/' RelativeLocationPath?
+                            | AbbreviatedAbsoluteLocationPath
+[ 3] RelativeLocationPath ::= Step
+			    | RelativeLocationPath '/' Step
+			    | AbbreviatedRelativeLocationPath
+[ 4] Step ::= AxisSpecifier NodeTest Predicate*
+            | AbbreviatedStep
+[ 5] AxisSpecifier ::= AxisName '::'
+                     | AbbreviatedAxisSpecifier
+[ 6] AxisName ::= 'ancestor'
+                | 'ancestor-or-self'
+                | 'attribute'
+                | 'child'
+                | 'descendant'
+                | 'descendant-or-self'
+                | 'following'
+                | 'following-sibling'
+                | 'namespace'
+                | 'parent'
+                | 'preceding'
+                | 'preceding-sibling'
+                | 'self'
+[ 7] NodeTest ::= NameTest
+                | NodeType '(' ')'
+                | 'processing-instruction' '(' Literal ')'
+[ 8] Predicate ::= '[' PredicateExpr ']'
+[ 9] PredicateExpr ::= Expr
+[10] AbbreviatedAbsoluteLocationPath ::= '//' RelativeLocationPath
+[11] AbbreviatedRelativeLocationPath ::= RelativeLocationPath '//' Step
+[12] AbbreviatedStep ::= '.' | '..'
+[13] AbbreviatedAxisSpecifier ::= '@'?
+[14] Expr ::= OrExpr
+[15] PrimaryExpr ::= VariableReference
+                   | '(' Expr ')'
+                   | Literal
+                   | Number
+                   | FunctionCall
+[16] FunctionCall ::= FunctionName '(' ( Argument ( ',' Argument )* )? ')'
+[17] Argument ::= Expr
+[18] UnionExpr ::= PathExpr
+                 | UnionExpr '|' PathExpr
+[19] PathExpr ::= LocationPath
+                | FilterExpr
+                | FilterExpr '/' RelativeLocationPath
+                | FilterExpr '//' RelativeLocationPath
+[20] FilterExpr ::= PrimaryExpr
+                  | FilterExpr Predicate
+[21] OrExpr ::= AndExpr | OrExpr 'or' AndExpr
+[22] AndExpr ::= EqualityExpr | AndExpr 'and' EqualityExpr
+[23] EqualityExpr ::= RelationalExpr
+                    | EqualityExpr '=' RelationalExpr
+                    | EqualityExpr '!=' RelationalExpr
+[24] RelationalExpr ::= AdditiveExpr
+                      | RelationalExpr '<' AdditiveExpr
+                      | RelationalExpr '>' AdditiveExpr
+                      | RelationalExpr '<=' AdditiveExpr
+                      | RelationalExpr '>=' AdditiveExpr
+
+[25] AdditiveExpr ::= MultiplicativeExpr
+                    | AdditiveExpr '+' MultiplicativeExpr
+                    | AdditiveExpr '-' MultiplicativeExpr
+[26] MultiplicativeExpr ::= UnaryExpr
+                        | MultiplicativeExpr MultiplyOperator UnaryExpr
+                        | MultiplicativeExpr 'div' UnaryExpr
+                        | MultiplicativeExpr 'mod' UnaryExpr
+[27] UnaryExpr ::= UnionExpr
+                 | '-' UnaryExpr
+[28] ExprToken ::= '(' | ')' | '[' | ']' | '.' | '..' | '@' | ',' | '::'
+                 | NameTest
+                 | NodeType
+                 | Operator
+                 | FunctionName
+                 | AxisName
+                 | Literal
+                 | Number
+                 | VariableReference
+[29] Literal ::= '"' [^"]* '"'
+               | "'" [^']* "'"
+[30] Number ::= Digits ('.' Digits?)? | '.' Digits
+[31] Digits ::= [0-9]+
+[32] Operator ::= OperatorName
+                | MultiplyOperator
+                | '/' | '//' | '|' | '+' | '-' | '=' | '!=' | '<' | '<=' | '>' | '>='
+[33] OperatorName ::= 'and' | 'or' | 'mod' | 'div'
+[34] MultiplyOperator ::= '*'
+[35] FunctionName ::= QName - NodeType
+[36] VariableReference ::= '$' QName
+[37] NameTest ::= '*' | NCName ':' '*' | QName
+[38] NodeType ::= 'comment' | 'text'
+                | 'processing-instruction'
+                | 'node'
+[39] ExprWhitespace ::= (#x20 | #x9 | #xD | #xA)+
+
+Useful subset
+-------------
+
+Big swath of XPath 1.0 that might be interesting for Augeas
+
+start symbol [14] Expr
+
+[14] Expr ::= OrExpr
+[21] OrExpr ::= AndExpr ('or' AndExpr)*
+[22] AndExpr ::= EqualityExpr ('and' EqualityExpr)*
+[23] EqualityExpr ::= RelationalExpr
+                    | EqualityExpr '=' RelationalExpr
+                    | EqualityExpr '!=' RelationalExpr
+[24] RelationalExpr ::= AdditiveExpr
+                      | RelationalExpr '<' AdditiveExpr
+                      | RelationalExpr '>' AdditiveExpr
+                      | RelationalExpr '<=' AdditiveExpr
+                      | RelationalExpr '>=' AdditiveExpr
+[25] AdditiveExpr ::= MultiplicativeExpr
+                    | AdditiveExpr '+' MultiplicativeExpr
+                    | AdditiveExpr '-' MultiplicativeExpr
+[26] MultiplicativeExpr ::= UnaryExpr
+                        | MultiplicativeExpr MultiplyOperator UnaryExpr
+[27] UnaryExpr ::= UnionExpr | '-' UnaryExpr
+[18] UnionExpr ::= PathExpr ('|' PathExpr)*
+
+[19] PathExpr ::= LocationPath
+                | FilterExpr
+                | FilterExpr '/' RelativeLocationPath
+                | FilterExpr '//' RelativeLocationPath
+
+[ 1] LocationPath ::= RelativeLocationPath | AbsoluteLocationPath
+[ 3] RelativeLocationPath ::= Step
+			    | RelativeLocationPath '/' Step
+			    | AbbreviatedRelativeLocationPath
+[11] AbbreviatedRelativeLocationPath ::= RelativeLocationPath '//' Step
+[ 2] AbsoluteLocationPath ::= '/' RelativeLocationPath?
+                            | AbbreviatedAbsoluteLocationPath
+[10] AbbreviatedAbsoluteLocationPath ::= '//' RelativeLocationPath
+
+[ 4] Step ::= AxisSpecifier NameTest Predicate* | '.' | '..'
+[ 5] AxisSpecifier ::= AxisName '::' | <epsilon>
+
+[ 6] AxisName ::= 'ancestor'
+                | 'ancestor-or-self'
+                | 'attribute'
+                | 'child'
+                | 'descendant'
+                | 'descendant-or-self'
+                | 'following'
+                | 'following-sibling'
+                | 'namespace'
+                | 'parent'
+                | 'preceding'
+                | 'preceding-sibling'
+                | 'self'
+
+[ 8] Predicate ::= '[' Expr ']'
+
+[20] FilterExpr ::= PrimaryExpr Predicate*
+[15] PrimaryExpr ::= '(' Expr ')'
+                   | Literal
+                   | Number
+                   | FunctionCall
+[16] FunctionCall ::= FunctionName '(' ( Argument ( ',' Argument )* )? ')'
+[17] Argument ::= Expr
+
+Lexical structure
+
+[28] ExprToken ::= '(' | ')' | '[' | ']' | '.' | '..' | '@' | ',' | '::'
+                 | NameTest
+                 | NodeType
+                 | Operator
+                 | FunctionName
+                 | AxisName
+                 | Literal
+                 | Number
+                 | VariableReference
+[29] Literal ::= '"' [^"]* '"'
+               | "'" [^']* "'"
+[30] Number ::= Digits ('.' Digits?)? | '.' Digits
+[31] Digits ::= [0-9]+
+[32] Operator ::= OperatorName
+                | MultiplyOperator
+                | '/' | '//' | '|' | '+' | '-' | '=' | '!=' | '<' | '<=' | '>' | '>='
+[33] OperatorName ::= 'and' | 'or' | 'mod' | 'div'
+[34] MultiplyOperator ::= '*'
+[35] FunctionName ::= QName - NodeType
+[36] VariableReference ::= '$' QName
+[37] NameTest ::= '*' | QName
+[38] NodeType ::= 'comment' | 'text'
+                | 'processing-instruction'
+                | 'node'
+[39] ExprWhitespace ::= (#x20 | #x9 | #xD | #xA)+
-- 
1.6.0.6




More information about the augeas-devel mailing list