@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