123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 |
- @node Other Unix
- @chapter Other Unix-specific facilities
- @menu
- * Expect:: Expect, for pattern matching from a port.
- @end menu
- @node Expect
- @section Expect: Pattern Matching from a Port
- @code{expect} is a macro for selecting actions based on the output from
- a port. The name comes from a tool of similar functionality by Don Libes.
- Actions can be taken when a particular string is matched, when a timeout
- occurs, or when end-of-file is seen on the port. The @code{expect} macro
- is described below; @code{expect-strings} is a front-end to @code{expect}
- based on regexec @xref{Regular expressions}.
- Using these macros requires for now:
- @smalllisp
- (load-from-path "ice-9/expect")
- @end smalllisp
- @defun expect-strings clause @dots{}
- By default, @code{expect-strings} will read from the current input port.
- The first term in each clause consists of an expression evaluating to
- a string pattern (regular expression). As characters
- are read one-by-one from the port, they are accumulated in a buffer string
- which is matched against each of the patterns. When a
- pattern matches, the remaining expression(s) in
- the clause are evaluated and the value of the last is returned. For example:
- @smalllisp
- (with-input-from-file "/etc/passwd"
- (lambda ()
- (expect-strings
- ("^nobody" (display "Got a nobody user.\n")
- (display "That's no problem.\n"))
- ("^daemon" (display "Got a daemon user.\n")))))
- @end smalllisp
- The regular expression is compiled with the @code{REG_NEWLINE} flag, so
- that the @code{^} and @code{$} anchors will match at any newline, not
- just at the start
- and end of the string.
- There are two other ways to write a clause:
- The expression(s) to evaluate on a match
- can be omitted, in which case the result of the match
- (converted to strings, as obtained from regexec with @var{match-pick}
- set to @code{""}) will be returned if the pattern matches.
- The symbol @code{=>} can be used to indicate that there is a single
- expression to evaluate on a match, which must be a
- procedure which will accept the result of a successful match (converted
- to strings, as obtained from regexec with @var{match-pick} set to
- @code{""}). E.g.,
- @smalllisp
- ("^daemon" => write)
- ("^d\\(aemon\\)" => (lambda args (map write args)))
- ("^da\\(em\\)on" => (lambda (all sub)
- (write all)
- (write sub)))
- @end smalllisp
- The order of the substrings corresponds to the order in which the
- opening brackets occur in the regular expression.
- A number of variables can be used to control the behaviour
- of @code{expect} (and @code{expect-strings}).
- By default they are all bound at the top level to
- the value @code{#f}, which produces the default behaviour.
- They can be redefined at the
- top level or locally bound in a form enclosing the @code{expect} expression.
- @table @code
- @item expect-port
- A port to read characters from, instead of the current input port.
- @item expect-timeout
- @code{expect} will terminate after this number of
- seconds, returning @code{#f} or the value returned by
- @code{expect-timeout-proc}.
- @item expect-timeout-proc
- A procedure called if timeout occurs. The procedure takes a single argument:
- the accumulated string.
- @item expect-eof-proc
- A procedure called if end-of-file is detected on the input port. The
- procedure takes a single argument: the accumulated string.
- @item expect-char-proc
- A procedure to be called every time a character is read from the
- port. The procedure takes a single argument: the character which was read.
- @end table
- Here's an example using all of the variables:
- @smalllisp
- (let ((expect-port (open-input-file "/etc/passwd"))
- (expect-timeout 1)
- (expect-timeout-proc
- (lambda (s) (display "Times up!\n")))
- (expect-eof-proc
- (lambda (s) (display "Reached the end of the file!\n")))
- (expect-char-proc display))
- (expect-strings
- ("^nobody" (display "Got a nobody user\n"))))
- @end smalllisp
- @end defun
- @defun expect clause @dots{}
- @code{expect} is used in the same way as @code{expect-strings},
- but tests are specified not as patterns, but as procedures. The
- procedures are called in turn after each character is read from the
- port, with the value of the accumulated string as the argument. The
- test is successful if the procedure returns a non-false value.
- If the @code{=>} syntax is used, then if the test succeeds it must return
- a list containing the arguments to be provided to the corresponding
- expression.
- In the following example, a string will only be matched at the beginning
- of the file:
- @smalllisp
- (let ((expect-port (open-input-file "/etc/passwd")))
- (expect
- ((lambda (s) (string=? s "fnord!"))
- (display "Got a nobody user!\n"))))
- @end smalllisp
- The control variables described for @code{expect-strings} can also
- be used with @code{expect}.
- @end defun
|