.\" As its sole author, I explicitly place this file in the public domain. .\" It may be used by anyone in any way for any purpose, though I would .\" appreciate credit where it's due. .\" der Mouse, mouse@rodents-montreal.org, 2021-07-29 .Dd July 29, 2021 .Dt EXPECT 1 .Os NetBSD 1.4T .Sh NAME .Nm expect .Nd automate interaction with serial lines .Sh SYNOPSIS .Nm .Op options .Ar script .Sh DESCRIPTION .Nm is designed for automated interaction with something on the other end of a serial-line connection. .Pp It takes a .Ar script which describes how the interaction is to proceed. This script is essentially a small language designed for the purpose. This language is strictly line-oriented; except for comments, each line is executed in order (though a few line types can affect control flow). .Pp Comments consist of entirely blank lines, lines containing only whitespace, and lines whose first non-whitespace character is .Sq \&; or .Sq # . .Pp Non-comment lines must begin with one of a handful of identifiers, identifying which kind of line it is. Before giving the list of lines, there are a few important concepts to explain. .Pp There are five types of values in the language, though one of them occurs in only a restricted set of places. Those five types are number, string, array, tag, and boolean. Numbers are usually integers, but can be floating-point (though exponential notation is supported in only a few restricted places). Strings are surrounded with double quotes and support the usual set of backslash escapes. Arrays are associative, rather like .Xr awk 1 Ap s arrays, though subscripts can be any type, not just small integers (as in C) or numbers or strings (as in awk). Booleans are either true or false and result from the comparison operators such as .Sq \&< . Finally, tags are a special type that occurs in only a few places: .Sq on lines and the first argument to .Sq expect lines, and .Sq loop , .Sq break , and .Sq continue lines. They are written as simple identifiers. (If you want to use an identifier as a variable in such a place, using it for its value rather than as a tag, put parens around it.) A tag is not equal to any non-tag value; they exist so that simple tags can be meaningful to humans without needing to have quotes around them. .Pp Expressions are built up from numbers and strings in the usual way, with parens for grouping, unary .Sq \&- (arithmetic negation) and .Sq \&! (logical negation) operators, binary .Sq + , .Sq \&- , .Sq \&* , .Sq / , .Sq \&& , .Sq \&| , .Sq \&^ , .Sq \&< , .Sq \&> , .Sq \&<= , .Sq \&>= , .Sq == , .Sq != , .Sq \&&& , .Sq \&|| , .Sq \&^^ , and ternary .Sq \&?\ : operators, subscripting, and function calls. There are also a few more operators which are spelled like identifiers but with an at-sign at the beginning; they are described below. There are no array constants; an empty array is created with a niladic operator .Sq \&[] and array elements get values by subscript expressions appearing on the left-hand side of a .Sq set assignment line. .Pp One important concept is the so-called .Sq found value . This is an internal value, set by .Sq await lines to either an internally-generated value or a value from an .Sq expect line, used by the .Sq @found operator. .Pp Interaction with the serial line is built around sending strings (with .Sq send lines) and waiting for strings to arrive (with .Sq expect and/or .Sq await lines). Conditional-execution constructs indicate their bodies by indenting the body further than the controlling line; a false conditional skips all following lines which are indented deeper than the controlling line (ie, until one indented no deeper than the controlling line), while a true conditional executes those lines. .Pp Execution continues until control flow falls off the end of the script or an .Sq exit line is executed. .Pp .Bl -tag -width indent .It print Ar EXPR .Ar EXPR is an expression which must evaluate to a string. This string is printed to .Nm Ap s standard output. .It send Ar EXPR .Ar EXPR is an expression which must evaluate to a string. This string is sent to the serial-line connection. .It expect Ar EXPR1 No , Ar EXPR2 .Ar EXPR1 is a tag (see below); .Ar EXPR2 must evaluate to a string. This adds an expectation, for use by the next .Sq await line. See .Sq await for more. .It await Ar EXPR1 Oo .No , .Ar EXPR2 .Oc .Ar EXPR1 must evaluate to a number, or something that can be converted to a number. It specifies a timeout, in seconds (which may include a fractional part). .Pp If .Ar EXPR2 is not present, there must have been at least one .Sq expect line executed since the last .Sq await (or the beginning of the script if no previous .Sq await has been executed), and this waits until one of the expected strings is received. If one is received before the timeout expires, the found value is set to the .Ar EXPR1 from the corresponding .Sq expect line; if not, it is set to the tag .Sq timeout (whether or not any .Sq expect line specifies that tag). .Pp If .Ar EXPR2 is present, it must evaluate to a string, and the .Sq await waits for that string to be received on the serial line. If it is received before the timeout expires, the found value is set to integer zero; if not, to the tag .Sq timeout . (This is effectively the same as .Sq expect 0 Ar EXPR2 and then .Sq await Ar EXPR1 except that it doesn't disturb the actual list of expectations.) .It delay Ar EXPR This simply delays for .Ar EXPR seconds. It is like .Sq await with the same timeout, except that it never reads anything from the serial line and has nothing to do with the list of .Sq expect strings. .It set Ar EXPR1 = Ar EXPR2 .Ar EXPR1 must be either a variable name or an array subscript reference. This evaluates .Ar EXPR2 and stores the result in the variable or the array element. .It if Ar EXPR .Ar EXPR must evaluate to a boolean value. If that value is true, this is a true conditional; otherwise, a false conditional. See also .Sq elif and .Sq else ; there is no .Sq endif , since the end of the controlled lines is indicated by indentation. .It elif Ar EXPR This must be the first line after a .Sq if line that is indented the same as it. If the .Sq if was false, then .Ar EXPR is evaluated and the result controls execution as if this were a .Sq if line; otherwise (if the .Sq if was true), .Xr EXPR is not evaluated and this acts like a false .Sq if . .It else This is like .Sq elif with an expression that always evaluates true. .It loop Op Ar EXPR This evaluates following lines, like a true conditional, but, at the end of the controlled lines, rather than continuing, it returns to the line just after the .Sq loop . The only way out is a .Sq break line. The .Ar EXPR , if specified, can be used by .Sq break and .Sq continue lines to refer to this loop from within a nested loop. .It break Op Ar EXPR This breaks out of a loop (see the .Sq loop line). If .Ar EXPR is given, it breaks out of the smallest enclosing loop whose .Ar EXPR equals this one; it is an error if there is no such loop. If no .Ar EXPR is specified, this breaks out of the smallest enclosing loop, whether or not that loop has an .Ar EXPR specified. .It continue Op Ar EXPR This continues a loop, like C's .Sq continue statement. The loop is identified based on .Ar EXPR in the same way as for .Sq break , but instead of breaking out of the located loop, this aborts the rest of the current iteration and immediately returns to the first line of the relevant loop's body. .It exit Op Ar EXPR Exits .Nm entirely. If .Ar EXPR is given, it must evaluate to an integer, which is used as the exit code (see .Xr exit 2 ) ; if not, exit code 0 is used, which most contexts take to indicate success. .It param Ar PARAM \&= Ar EXPR Sets internal parameter PARAM to the value of EXPR. What values are permitted depends on which parameter is being set: .Bl -tag -width indent .It interchar Value is a floating-point number, which is a time delay (in seconds) between sending each character and sending the next. If this is zero, or if it is less than the time taken to send a character at the current speed, characters are sent back-to-back. The timeout specified for .Sq await lines does not start until all characters have been sent (which here means being sent to the hardware; this usually is within a character or two of being actually sent out the port). .Pp The default value is 0. .El .El .Pp The operators spelled as at-sign-prefixed identifiers: .Bl -tag -width indent .It @found Ar EXPR If the found value equals .Ar EXPR , this returns true, otherwise false. Unlike most operators, .Ar EXPR may be a tag. .El .Pp Function calls take the form of an identifier (the function name) followed by zero or more parameters, separated by commas, in parens. The supported functions, with their arguments and semantics: .Pp .Bl -tag -width indent .It \&$int Ns ( Ar val ) Converts .Ar val to an integer. Integers are unchanged. Floating-point numbers are truncated to integers. Strings are converted as if with .Xr strtoll 3 . Booleans convert false to 0 and true to 1. Other types are errors. .It \&$len Ns ( Ar val ) Returns .Ar val Ap s length. For strings, the is the number of characters in the string. For arrays, it is the number of subscripts for which the array contains anything. Other types are errors. .It \&$float Ns ( Ar val ) Converts .Ar val to floating-point. Floats are unchanged. Integers are converted. Strings are converted as if with .Xr strtod 3 . Booleans convert false to 0 and true to 1. Other types are errors. .Sm off .It Xo \&$substr ( Ar str , Ar skip .Op Ns No , Ar len .No Ns ) .Xc .Sm on Extracts a substring of a string. .Ar str is the string. .Ar skip is the number of characters to skip at the beginning of the string (but see below). If .Ar len is specified, it is the length of the string to extract (but see below); if not, everything from the selected starting point to the end of the string is extracted. .Pp If .Ar skip is negative, it has the length of the string added to it (making it effectively count backwards from the end of the string); if it is still negative after that, it is increased to zero, with .Ar len , if provided, decreased by an equal amount (except that, if .Ar len is negative after being decreased, it is set to zero, regardless of whether it was negative before being decreased). If .Ar len is provided and is negative, it is increased by the length of the portion after the selected start point; if it is still negative after that, zero is used. Then the selected substring is extracted and returned. .El .Sh BUGS There is no form of user-defined functions. .Pp There is no way to remove an entry from an array. .Sh AUTHOR der Mouse, .Aq mouse@rodents-montreal.org .