BindRules(7)

๐Ÿ’– BindRules(7) โ€” ShapeTools ๐Ÿ’–

okay bestie, gather round, because we're about to talk about version bind rules from ShapeTools and honestly? it's giving iconic. this is the BindRules(7) manual page, and i'm gonna walk you through it like we're texting at 2am. no cap. โœจ


๐ŸŒธ NAME ๐ŸŒธ

BindRules โ€” the ShapeTools version bind rules. that's the whole vibe. ๐Ÿ’…


โœจ DESCRIPTION โœจ

so the ShapeTools version binding subsystem (peep vbind(1) for that one, iykyk) gives you a whole mechanism for expressing general version bind rules. and what even are those? they describe version properties on an abstract level, and then those properties get matched against the properties of concrete versions during the version bind procedure. the goal? pick one or more versions out of a named history so you can actually access them. ๐ŸŽ€

lowkey important: a version bind operation always happens for exactly one history at a time. one. history. periodt.

a version bind rule is basically expressing something like:

Select the most recent saved version.
If there is no saved version, select the busy version.

but ShapeTools is not a mind reader, bestie, so it needs rules in a more formal notation to interpret them. let's see how that rule above gets translated, shall we? ๐Ÿฆ‹

version bind rules consist of a list of attribute expressions, evaluated one after another until one of the expressions leads to a unique version identification. the expressions are separated by semicolons, and the last expression ends with a period. so the rule from above now reads:

Select the most recent saved version ;
Select the busy version .

each attribute expression consists of a list of predicates, separated by commas. the predicates get evaluated from left to right, resulting in a hit set โ€” a set of versions fulfilling all predicates evaluated so far. the initial hit set for an attribute expression contains all versions of the name to be bound. each predicate potentially narrows the hit set. the predicates in our rule are:

all saved versions , most recent version ;
busy version .

remember (this is the part people always forget ๐Ÿ˜ญ) that each predicate bases its selection on the hit set left by the predicate before it. so swapping the two predicates in the first attribute expression may totally lead to different results. we'll spill more tea on this in the section about the evaluation algorithm below. ๐Ÿ‘€

now we reach the final form of ShapeTools version bind rules. the predicates must be taken from a list of predefined names and be equipped with arguments:

ge (status, saved) , max (stime) ;
eq (status, busy) .

and that's it so far. this is a rule how ShapeTools understands it. it does, however, illustrate just a small piece of the world of version bind rules. so we're going on in this manual page with a detailed description, divided into these sections:

  • RULE HEAD โ€” description of the structure of rule heads.
  • EVALUATION ALGORITHM โ€” the algorithm how version bind rules are evaluated.
  • NAME PATTERNS โ€” name patterns as first predicate in attribute expressions.
  • PREDICATES โ€” list of valid predicates.
  • ATTRIBUTES โ€” a list of predefined attribute names and some words about the ordering relationship between attribute values.
  • EXPANSION โ€” description of the various types of expansion such as parameter substitution, attribute and macro expansion, and command substitution.
  • LEXICAL STRUCTURE โ€” lexical constraints for names and strings in version bind rules.
  • TIPS, TRICKS, AND TRAPS โ€” some common problems.
  • GRAMMAR โ€” a complete grammar for version bind rules.

๐Ÿ‘‘ RULE HEAD ๐Ÿ‘‘

a version bind rule consists of a rule head and a rule body. the example above only shows the rule body (rude of it, honestly). the rule head defines a name for the rule and optionally a parameter list.

the name is a string consisting of any printable non-whitespace character except colon and parentheses. it's followed by an optional parameter list in parentheses and a colon, which delimits the rule head. multiple parameters in the list are separated by comma. examples, bestie:

most_recently_released:

from_release (release_name):

last_released (library_path, include_path):

see? cute, clean, slay. ๐Ÿ’–


๐Ÿ”ฅ EVALUATION ALGORITHM ๐Ÿ”ฅ

the basic idea of the rule evaluation algorithm is that in every state of processing a hit set exists โ€” a set of versions reflecting the current rule evaluation result. the hit set gets initialized with all versions of the given name at the beginning of each attribute expression. ๐Ÿซถ

the attribute expression's predicates are processed from left to right in the order they occur. each predicate imposes requirements on the versions in the hit set and eliminates all versions not fulfilling those requirements. so the hit set gets smaller and smaller as the attribute expression evaluates. the following figure illustrates this process together with the rule most_recently_released defined above and the file foo existing as busy version and as versions 1.0 through 1.2:

Initial hit set:    ( foo[busy], foo[1.0], foo[1.1], foo[1.2] )

Evaluate Predicate: ge (status, saved),

New hit set:        ( foo[1.0], foo[1.1], foo[1.2] )

Evaluate Predicate: max (stime);

Final hit set:      ( foo[1.2] )

when the hit set becomes empty โ€” like, when no version meets all the predicates evaluated so far โ€” the attribute expression fails and processing is finished immediately. all remaining predicates will not be evaluated. even remaining predicates without influence on the hit set (for example message predicates) will not be processed. processing continues with the next attribute expression. and if all attribute expressions finish prematurely, the whole version binding fails. ๐Ÿ’€

in the following example, the first attribute expression fails and the second alternative leads to success:

Initial hit set:    ( bar[busy] )

Evaluate Predicate: ge (status, saved),

New hit set (empty):( )

Evaluate next attribute expression
starting with initial hit set again:( bar[busy] )

Evaluate Predicate: eq (status, busy);

Final hit set:      ( bar[busy] )

when evaluation reaches the end of an attribute expression without the hit set being empty, two cases are possible:

  1. the hit set contains exactly one version and everything is fine. this is usually the desired state, and rule evaluation returns the remaining version as the bind result. ๐ŸŽ‰
  2. the hit set may contain more than one version. in this case, the evaluation algorithm depends on the expected result. when a unique version binding is expected, this is treated as failure and evaluation goes on with the next attribute expression. non-unique version binding regards this as success and returns the whole hit set.

extending the hit set during evaluation of an attribute expression is not possible. that would be against the nature of the version bind rules and would make them much more difficult to understand. hit set extension may only happen by letting the current attribute expression fail and begin with a new one and the maximum hit set. no shortcuts, bestie. ๐Ÿ™ˆ

failure of an attribute expression must not necessarily be caused by an empty hit set. it may also be caused by user interaction or by external constraints. the following rules exemplify user interaction:

eq (state, busy), confirm (select busy version ?, y);
ge (state, busy), max (version).

where the user will be asked for confirmation to select the busy version, and external constraints:

exists (otto, 1.0), eq (state, busy);
ge (state, busy), max (version).

where selection of the busy version happens only when version 1.0 of otto exists (this example is, and i quote, somewhat silly ๐Ÿ’…). predicates like confirm and exists don't care about the hit set. they provide the possibility to impose external control on the evaluation of version bind rules. an attribute expression may be finished prematurely and control switches to the next one.

there is another operator โ€” the cut operator โ€” that forces the whole bind operation to finish (and fail). typically the cut operator stands at the end of an attribute expression that should never succeed. the following is a typical example for use of this. version binding fails if there is an update lock set on the most recent version:

max (version), hasattr (locker), cut (history is locked !);
max (version).

the cut operator accepts a string argument that will be written to the standard output. ๐Ÿ‘€

๐ŸŒธ NAME PATTERNS ๐ŸŒธ

okay so this is where it gets fun. every attribute expression can start with a pattern, and the name you're trying to bind gets matched against it. if the name matches the pattern? slay, the attribute expression gets evaluated. if it doesn't match? skipped, no thoughts, no notes. and when you just... don't write a pattern at all (like in the example we did earlier), then the expression is evaluated for every single name. generous queen.

these patterns are literally the exact same ones sh(1) recognizes for filename generation on the command line. the magic cookies are:

  • * โ€” matches any string, including the empty string โœจ
  • ? โ€” matches any single character
  • [c...] โ€” matches any one of the characters chillin' inside the square brackets
  • [l-r] โ€” matches any character lexically between the left (l) and the right (r) character, inclusive ๐Ÿซถ
  • [!c...]
  • [!l-r] โ€” matches any character that their counterparts above do not recognize

a rule with name patterns looks, like, exactly like this:

xyyz.h, eq (version, 1.3);
*.c,    eq (generation, 2), max (revision);
*.h,    eq (generation, 3), max (revision).

so in this example the version binding for C source files (most recent version from generation 2) is different from the version binding for header files (most recent version from generation 3). and on top of that, the name xyyz.h will always be bound to version 1.3. periodt.


now, if the name to be bound shows up together with a (absolute or relative) pathname, bestie, that pathname does not get cut off. the match is always performed lexically for the whole name given. so yeah, the name pattern can absolutely contain path names too, like:

variant1/*, eq (alias, var1-1.4);
variant2/*, eq (alias, var2-1.2);
/usr/sample/include/*.h,max (revision).

usually the version bind subsystem does not check whether different path prefixes in the name pattern and the given name to be bound lead to the same location. the match is done lexically and it has to fit exactly. no vibes-based leniency.

an exception tho ๐Ÿ’… โ€” when the name pattern is given as a network path name, like in atnetwork(3).

a network pathname is made of the name of the host controlling the device where a version is stored, the canonical pathname to the version, and a version binding (so: version number, version alias, or date) either in brackets or separated from the name by an at (@) sign. examples:

desaster:/usr/sample/project/foo.c[1.0];
desaster:/usr/sample/project/variant1/bar.c[var1-1.4];
desaster:/usr/sample/project/xyyz.h@1.3;
desaster:/usr/sample/project/bar.c@Fri Jun 18 13:40:58 MET DST 1993.

network pathnames get mapped to canonical local pathnames before being processed, and in this case the given name to be bound will also get mapped to a canonical local pathname. mutual glow-up โœจ

the technique using network pathnames is especially useful when you're storing the result of a successful version selection persistently. it makes the version selection easily reproducible from anywhere in the local areas network. shape(1) uses this mechanism when generating its bound configuration threads, iykyk. ๐Ÿ‘‘


๐Ÿ”ฎ PREDICATES ๐Ÿ”ฎ

this is the complete list of valid predicate names and a lil synopsis of their arguments. the list is divided into several parts, each one describing a certain class of predicates. no skipping, we're doing all of them.

๐Ÿงš The first class: single-version predicates

these work independently on each element of the current hit set. they impose certain requirements on the attributes of each version and eliminate the ones that don't fulfill those requirements. it's giving talent show audition.

  • eq (attrName,attrValue) โ€” the named attribute must exist in the version's attribute list and it must have exactly the given value. when the corresponding version attribute has multiple values, at least one of the values must match exactly.
  • hasattr (attrName) โ€” the named attribute must exist in the version's attribute list. when applied to a standard attribute, hasattr requires a value to be associated with the standard attribute. in the case of user defined attributes, the attribute value is not regarded.
  • ne (attrName,attrValue) โ€” the named attribute, when it exists in the version's attribute buffer, must not have the given attribute value. when the attribute doesn't exist, everything is fine, we're chill. if the attribute has multiple values, it's required that none of the values matches the given attrValue.
  • {ge,gt,le,lt} (attrName,attrValue) โ€” the named version attribute must have a value that is greater or equal / greater than / less or equal / less than the given attribute value. the named attribute must exist in the version's attribute buffer, otherwise the version gets eliminated from the hit set. for attributes with multiple values, only one of the values has to meet the required property.

๐Ÿฆ‹ The second class: hit-set-wide predicates

these do not operate on a single version but rather on the complete hit set. they express relations between different versions in the hit set and base their selection on comparisons between different versions. usually they're used to get a unique version binding, by ordering the hit set and selecting one of the extremes. main character selection energy, honestly.

  • min (attrName) โ€” retain the version(s) with the lowest value for the named attribute in the hit set. string values are compared literally, others "naturally" (see the list of known attributes below for an explanation of that). versions not carrying the named attribute, or having no value associated with the attribute name, get eliminated from the hit set.
  • max (attrName) โ€” retain the version(s) with the highest value for the named attribute in the hit set. string values are compared literally, others "naturally" (see the list of known attributes below for an explanation of that). versions not carrying the named attribute, or having no value associated with the attribute name, get eliminated from the hit set.

๐Ÿ’€ The next two predicate groups

these have no direct influence on the hit set. they can invalidate the hit set and cause the rule evaluation to go on with the next attribute expression, but they never, ever modify the hit set. no cap. these predicates get activated when the evaluation of the attribute expression reaches them, i.e. when the hit set is not empty.

  • msg (msgString) โ€” print the given message to standard output and retain the current hit set.
  • cut (msgString) โ€” force the current rule binding to fail and print the given message to standard output. printing is omitted when the message string is empty. rule processing is stopped immediately and the returned hit set is empty. it's giving slamming the door.
  • confirm (msgString,expectedAnswer) โ€” ask the user for confirmation to go on with the evaluation of the current attribute expression. the given message string is printed to standard output with the expected answer appended in square brackets. after that, user input is read. when the user confirms the expected answer (empty input), or their input matches the expected answer, evaluation of the current attribute expression continues. otherwise the current hit set is invalidated and processing goes on with the next attribute expression.
  • bindrule (ruleName) โ€” abort evaluation of the current attribute expression and switch to another version bind rule. this predicate only makes sense as the last predicate in an attribute expression, since following predicates will never be evaluated. evaluation of the target rule (ruleName) happens as if the rule had been invoked directly, no influence on the initial hit set is taken. when the target rule fails, the evaluation algorithm switches back to the source rule and goes on with the next attribute expression. plot twist, we're back ๐ŸŽ€

๐ŸŒˆ The last predicate group: external constraints

their whole task is to influence the evaluation process by examining conditions outside the handled version history. each of the following predicates has either a positive or a negative result. positive results have no effect on the hit set and the evaluation process, while negative results invalidate the hit set and cause evaluation to go on with the next attribute expression.

  • exists (name[binding]) โ€” version binding with the given name (usually another one than the current target name) and the given version binding must lead to at least one version. the result is not required to be unique.
  • existsnot (name[binding]) โ€” version binding with the given name and rule must fail.
  • existsuniq (name[binding]) โ€” version binding with the given name and rule must lead to a unique selection.
  • condexpr (program,expression) โ€” an external program, named in the program argument, is activated to evaluate the given expression. the expression string is written to the standard input of the external program. a zero result code is considered to be positive, all others negative.

๐Ÿ’€ OBSOLETE PREDICATE NAMES ๐Ÿ’€

so there are a bunch of known predicate names from former versions of the bind rules machinery. they're internally mapped to the new predicate names. these names are obsolete and should not be used any longer. bestie, please, retire them, they've served their time ๐Ÿ™ˆ

the raw mapping table looks like this:

Obsolete name   mapped to -   cut attr            eq
attrex          hasattr attrge          ge attrgt          gt
attrle          le attrlt          lt attrmax         max
attrmin         min attrnot         ne condex          exists
condnot         existsnot conduniq        existsuniq

read it as pairs, and it's giving:

  • attr โ†’ eq
  • attrex โ†’ hasattr
  • attrge โ†’ ge
  • attrgt โ†’ gt
  • attrle โ†’ le
  • attrlt โ†’ lt
  • attrmax โ†’ max
  • attrmin โ†’ min
  • attrnot โ†’ ne
  • condex โ†’ exists
  • condnot โ†’ existsnot
  • conduniq โ†’ existsuniq

โœจ ATTRIBUTES โœจ

okay so bestie, listen ๐Ÿ’– โ€” every predicate that messes with the contents of the hit set is out here operating on version attributes. Those attributes are either standard attributes (they have a defined meaning, iconic, no notes) or user defined attributes (you made them, you name them, slay). Here's the list of names that get recognized as standard. Literally anything else? Considered a user defined attribute, periodt.

  • alias โ€” Version alias name (the symbolic version identification name).
  • atime โ€” The date of last access (read or write) to the version's contents.
  • author โ€” The version author, written as username@domain.
  • cachekey โ€” A unique key for cached versions, built from the creation date, the id of the creating process and a serial number (like 740148430.18469.6).
  • ctime โ€” The date of the last status change. This gets updated whenever an attribute is added or deleted, or when an attribute value is changed.
  • generation โ€” The generation number. The value here is plain numeric.
  • host โ€” The name of the host the version was accessed from. Heads up: this attribute can have different values at one time, when the version is being accessed from different hosts. ๐Ÿ™ˆ
  • locker โ€” The user who has set a lock on the version in question. This attribute is empty when no lock is active. The value comes in the form username@domain.
  • ltime โ€” The date of last lock change (set or give up update lock). This one has an empty value when there was never a lock set on the version.
  • mtime โ€” The date of the last modification of the version's contents.
  • name โ€” The name (without suffix) of the version. For example foo for foo.c.
  • owner โ€” The version owner, in the form username@domain.
  • revision โ€” The revision number. Same deal as generation โ€” only numeric values are accepted.
  • size โ€” The size of the version's contents in bytes.
  • status โ€” The version status. It's one of busy, saved, proposed, published, accessed, or frozen.
  • stime โ€” The save date. This attribute is empty for busy versions.
  • syspath โ€” The absolute pathname through which the version was accessed. Like host, this one can have different values at one time when the version is accessed via different pathnames (symbolic links, looking at you ๐Ÿซถ).
  • type โ€” The suffix part of the version's name. For example fc for foo.c.
  • version โ€” The version number in the form generation.revision. Special value alert ๐Ÿšจ: the string busy instead of a version number. Since busy versions have no version number, this value is what identifies the busy version of a history.

okay now some predicates (like ge or max, iykyk) need an ordering relationship between attribute values. For user defined attributes, the ordering is based on alphabetical (ASCII) comparison of the values. And user defined attributes with multiple values get compared by their first values โ€” if those are identical, by their second values, and so on. No value is considered smaller than any other value. For example:

attr1 = anton                  attr2 = berta
        berta   is smaller than        anton
        karl

but:

attr1 = anton                  attr2 = anton
        berta   is bigger than         berta
        karl

For some of the standard attributes listed above, we need special regulations. So here they are, bestie:

  • Version numbers (generation.revision) โ€” ordered by generation number first, revision number secondary (so 1.2 is smaller than 2.1). And busy is smaller than any version number.
  • Alias Names โ€” ordered by the version numbers (see above) of the identified versions.
  • Cache keys โ€” ordered by simple text comparison. Effect of this: the youngest cache key is considered the biggest.
  • Version states โ€” ordered in the sequence as listed above. busy is the lowest state and frozen is the highest.
  • User attributes โ€” the order of user attributes is based on alphabetical comparison of the string username@domain.
  • Time attributes โ€” time comparison assumes older dates are smaller than newer ones.

๐ŸŒ€ EXPANSION ๐ŸŒ€

During evaluation of version bind rules, four different kinds of expansion can happen, and yes we're listing all of them ๐Ÿ’…:

  1. parameter substitution
  2. attribute expansion
  3. external macro expansion
  4. command substitution

Expansion kicks in when a magic pattern shows up in the rule text, starting with either a dollar sign ($) or, in the case of command substitution, with a backward quote character (`).

Generally, expansion in version bind rules happens only within patterns and within predicate arguments. Bind rule syntax or predicate names cannot be introduced by substituted strings โ€” no sneaking stuff in like that. ๐Ÿ™…โ€โ™€๏ธ Expansions outside patterns and predicate arguments are ignored and usually lead to an error message.

Parameter Substitution

A parameter substitution string is usually introduced by the pattern $_ followed by the parameter name (an exception is $+, shown below). The parameter name is optionally delimited by a dollar sign. That's necessary when there's no whitespace character following it. The parameter name can be any of the names specified in the rule head, or one of these predefined names:

  • $_rule$ โ€” The current rule name.
  • $_target$ or $+ โ€” The current target file name to be bound.
  • $_parameter$ โ€” Any other parameter.

A parameter may have the same name as a citeable attribute (see below). In that case, the parameter citation hides the attribute citation. So there is literally no way to cite the value of an attribute when there's an equally named rule parameter. Also: the reserved names rule, target, and hits are not allowed as parameter names. ๐Ÿšซ

Attribute Expansion

An attribute expansion string looks exactly like a parameter substitution string. It's introduced by the pattern $_ followed by the attribute name, which is optionally delimited by a dollar sign when a non-whitespace character follows immediately. Attribute names may be built of any printable characters except '#'. Besides, it makes no sense to cite attributes with an equal sign ('=') in the attribute name, since the Attributed Filesystem (AtFS) doesn't allow that.

The value that replaces the attribute expansion string depends on the current state of processing. So yeah, this may cause different values to be inserted for the same citation in different processing states โ€” it's giving main character energy that shifts per scene. โœจ Attribute expansion happens as late as possible, right before the evaluation of the concerned pattern or predicate. With one exception, $_hits$, attribute expansions will only be substituted if the current hit set cardinality is 1.

  • $_hits$ or $= โ€” The number of versions satisfying the binding conditions expressed so far (the cardinality of the hit set). This value continuously changes during rule evaluation.
  • $_attribute$ โ€” The value of any attribute of a uniquely selected version.

Attribute citations may be overloaded by parameter citations (see above).

External Macro Expansion

External macros are evaluated by an external macro processor. If no such macro processor is available, external macros stay unchanged, fr fr. They have this form:

  • $C โ€” where C is any printable non-whitespace character except '+', '=', '_', ':', or '#'.
  • $(macroName) or ${macroName} โ€” Macro names may not contain '#' characters. Other limitations may be imposed by the external macro definition and processing facility.

Command Substitution

A command enclosed in back quotes occurring in a bind rule quotes will be replaced by its output. No modifications are done to the command output, so heads up: it may contain newline characters. ๐Ÿ˜ญ


๐Ÿ”ค LEXICAL STRUCTURE ๐Ÿ”ค

Some characters have special meaning when they show up in version bind rules. Iconic little guys, all of them:

  • the syntactical characters colon (:), comma (,), semicolon (;), period (.), and parentheses (( and ))
  • the comment symbol (#)
  • the dollar sign ($) or the back quote (`) introducing expansion strings ($)
  • quotes (" and ')
  • and the escape symbol (\)

Comments are handled somewhat rigorously. A comment symbol (#) occurring anywhere in the rule name or rule body has effect as long as it is not escaped by a backslash (\) character. Comments range from the comment symbol (inclusive) to the end of the line. Newline characters within comments may also be escaped by a backslash character, which continues the comment on the next line.

Nesting of parentheses and quotes is not supported. Just so you know. ๐Ÿ’€

The following is a list of lexical constraints for each part of a version bind rule.

Rule names and rule parameters

Rule names may consist of any printable non-whitespace character except colon and parentheses. The leftmost colon or opening parentheses delimits the rule name.

Rule parameter names follow the same lexical rule, but additionally must not contain comma characters, since that's the delimiter between parameters.

Patterns

In principle, name patterns may consist of any printable character. Comma and semicolon characters occurring in a name pattern must be escaped by a backslash character. A period occurring in a name pattern needs not to be escaped as long as it is not the last character (ignoring trailing whitespace) in the rule body. Period as last character is always considered to be the end of rule sign. Name patterns may contain macro or parameter citations and command substitutions.

Predicates

Each predicate name must be one of the reserved names listed previously in this paper. Predicate arguments consist of any printable character including whitespace. Comma, parenthesis or quoting characters must be escaped. Any argument may be quoted by single or double quotes. Quoting exceeds line limits.

Predicate arguments may contain macro, attribute or parameter citations leaded by a dollar sign, or command substitutions enclosed in back quotes. When quoted in single quotes, dollar signs and back quotes occurring in a predicate argument are not taken by their special meaning and no citations happen. Double quotes do not hide citations. ๐Ÿซถ

๐Ÿ’… TIPS, TRICKS, AND TRAPS ๐Ÿ’…

So you're asking โ€œwhy doesn't the bind rule select version xyz although I think it should??โ€ ๐Ÿ˜ญ The trace option from the vbind(1) command is literally your main character moment here โ€” it shows the evolution of the hit set during rule evaluation. ๐Ÿ‘‘

Typing errors in standard attribute names? Oof. They can lead to confusing situations, and the evaluation machinery cannot recognize them, because any unknown attribute name is considered to be an user defined attribute. So spell-check those attribute names, fr fr. ๐Ÿ™ˆ

A minus sign (-) as the first character in an alternative is considered as part of the pattern and not as the (old style) cut operator. Hence:

-; (- as pattern)

and

,-; (default pattern followed by cut)

make a big difference. We recommend the use of cut() in any case. The short form (-) is supported only for compatibility with older versions.


๐Ÿ“œ GRAMMAR ๐Ÿ“œ

Here's the whole grammar, bestie. Do not skip a single character, okay? ๐Ÿ’–

bind_rule ::= bind_rule_head :[-] bind_rule_body .

bind_rule_head ::= rule_name | rule_name ( rule_arg_list ) .

rule_arg_list: rule_name { , arg_name }* .

bind_rule_body ::= attr_expression { ; attr_expression}* . .

attr_expression ::=name_pattern { , predicate }* |
                 predicate { , predicate }* | .

name_pattern ::= { <any printable character or whitespace> }+

predicate ::=   attr_value_predicate ( attr_name , string ) |
         attr_name_predicate ( attr_name ) |
         bind_rule_predicate ( rule_name ) |
         msg_predicate ( string ) |
         msg_answer_predicate ( string , string ) |
         cond_rule_predicate ( string , bind_rule_head ) |
         cond_expr_predicate ( string , string ) |
         cut_predicate.

attr_value_predicate ::= eq | ge | gt | le | lt | ne .

attr_name_predicate ::= hasattr | max | min .

bind_rule_predicate ::= bindrule .

msg_predicate ::= cut | msg .

msg_answer_predicate ::= confirm .

cond_rule_predicate ::= exists | existsnot | existsuniq .

cond_expr_predicate ::= condexpr .

cut_predicate ::= - .

attr_name ::=   arg_name | author | atime | ctime | generation |
                locker | ltime | mtime | owner |
                revision | size | state | stime | version .

rule_name ::= { <any printable character except colon and parentheses }+ .

arg_name ::= { <any printable character except comma, colon and parentheses }+ .

string ::= { <any printable character or whitespace> } .

๐Ÿ“ FILES ๐Ÿ“

  • $SHAPETOOLS/BindRules โ€” the one and only file path, periodt. ๐Ÿ’…

๐Ÿ‘€ SEE ALSO ๐Ÿ‘€

Go give these a read too, bestie:


๐Ÿ’– AUTHOR ๐Ÿ’–

Andreas.Lampen@cs.tu-berlin.de โ€” thank you for your service, icon. ๐Ÿซถ


This BindRules(7) page came from AtFStk-1.12, dated Tue Jun 29 16:16:30 1993. Byeee! ๐ŸŒˆโœจ