OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [expect/] [example/] [autoexpect] - Rev 1765

Compare with Previous | Blame | View Log

#!../expect --
# Name: autoexpect - generate an Expect script from watching a session
#
# Description:
#
# Given a program name, autoexpect will run that program.  Otherwise
# autoexpect will start a shell.  Interact as desired.  When done, exit
# the program or shell.  Autoexpect will create a script that reproduces
# your interactions.  By default, the script is named script.exp.
# See the man page for more info.
#
# Author: Don Libes, NIST
# Date: June 30 1995
# Version: 1.4b

set filename "script.exp"
set verbose 1
set conservative 0
set promptmode 0
set option_keys ""

proc check_for_following {type} {
        if ![llength [uplevel set argv]] {
                puts "autoexpect: [uplevel set flag] requires following $type"
                exit 1
        }
}       

while {[llength $argv]>0} {
        set flag [lindex $argv 0]
        if 0==[regexp "^-" $flag] break
        set argv [lrange $argv 1 end]
        switch -- $flag \
          "-c" {
                set conservative 1
        } "-C" {
                check_for_following character
                lappend option_keys [lindex $argv 0] ctoggle
                set argv [lrange $argv 1 end]
        } "-p" {
                set promptmode 1
        } "-P" {
                check_for_following character
                lappend option_keys [lindex $argv 0] ptoggle
                set argv [lrange $argv 1 end]
        } "-Q" {
                check_for_following character
                lappend option_keys [lindex $argv 0] quote
                set argv [lrange $argv 1 end]
        } "-f" {
                check_for_following filename
                set filename [lindex $argv 0]
                set argv [lrange $argv 1 end]
        } "-quiet" {
                set verbose 0
        } default {
                break
        }
}

#############################################################
# Variables     Descriptions
#############################################################
# userbuf       buffered characters from user
# procbuf       buffered characters from process
# lastkey       last key pressed by user
#               if undefined, last key came from process
# echoing       if the process is echoing
#############################################################

# Handle a character that came from user input (i.e., the keyboard)
proc input {c} {
        global userbuf lastkey

        send -- $c
        append userbuf $lastkey
        set lastkey $c
}

# Handle a null character from the keyboard
proc input_null {} {
        global lastkey userbuf procbuf echoing

        send -null

        if {$lastkey == ""} {
                if $echoing {
                        sendcmd "$userbuf"
                }
                if {$procbuf != ""} {
                        expcmd "$procbuf"
                }
        } else {
                sendcmd "$userbuf"
                if $echoing {
                        expcmd "$procbuf"
                        sendcmd "$lastkey"
                }                       
        }
        cmd "send -null"
        set userbuf ""
        set procbuf ""
        set lastkey ""
        set echoing 0
}

# Handle a character that came from the process
proc output {s} {
        global lastkey procbuf userbuf echoing

        send_user -raw -- $s

        if {$lastkey == ""} {
                if !$echoing {
                        append procbuf $s
                } else {
                        sendcmd "$userbuf"
                        expcmd "$procbuf"
                        set echoing 0
                        set userbuf ""
                        set procbuf $s
                }
                return
        }

        regexp (.)(.*) $s dummy c tail
        if {$c == $lastkey} {
                if $echoing {
                        append userbuf $lastkey
                        set lastkey ""
                } else {
                        if {$procbuf != ""} {
                                expcmd "$procbuf"
                                set procbuf ""
                        }
                        set echoing 1
                }
                append procbuf $s

                if [string length $tail] {
                        sendcmd "$userbuf$lastkey"
                        set userbuf ""
                        set lastkey ""
                        set echoing 0
                }
        } else {
                if !$echoing {
                        expcmd "$procbuf"
                }
                sendcmd "$userbuf$lastkey"
                set procbuf $s
                set userbuf ""
                set lastkey ""
                set echoing 0
        }
}

# rewrite raw strings so that can appear as source code but still reproduce
# themselves.
proc expand {s} {
        regsub -all "\\\\" $s "\\\\\\\\" s
        regsub -all "\r" $s "\\r"  s
        regsub -all "\"" $s "\\\"" s
        regsub -all "\\\[" $s "\\\[" s
        regsub -all "\\\]" $s "\\\]" s
        regsub -all "\\\$" $s "\\\$" s

        return $s
}

# generate an expect command
proc expcmd {s} {
        global promptmode

        if $promptmode {
                regexp ".*\[\r\n]+(.*)" $s dummy s
        }

        cmd "expect -exact \"[expand $s]\""
}

# generate a send command
proc sendcmd {s} {
        global send_style conservative

        if {$conservative} {
                cmd "sleep .1"
        }

        cmd "send$send_style -- \"[expand $s]\""
}

# generate any command
proc cmd {s} {
        global fd
        puts $fd "$s"
}

proc verbose_send_user {s} {
        global verbose

        if $verbose {
                send_user -- $s
        }
}

proc ctoggle {} {
        global conservative send_style

        if $conservative {
                cmd "# conservative mode off - adding no delays"
                verbose_send_user "conservative mode off\n"
                set conservative 0
                set send_style ""
        } else {
                cmd "# prompt mode on - adding delays"
                verbose_send_user "conservative mode on\n"
                set conservative 1
                set send_style " -s"
        }
}

proc ptoggle {} {
        global promptmode

        if $promptmode {
                cmd "# prompt mode off - now looking for complete output"
                verbose_send_user "prompt mode off\n"
                set promptmode 0
        } else {
                cmd "# prompt mode on - now looking only for prompts"
                verbose_send_user "prompt mode on\n"
                set promptmode 1
        }
}

# quote the next character from the user
proc quote {} {
        expect_user -re .
        send -- $expect_out(buffer)
}
        

if [catch {set fd [open $filename w]} msg] {
        puts $msg
        exit
}
exec chmod +x $filename
verbose_send_user "autoexpect started, file is $filename\n"

# calculate a reasonable #! line
set expectpath /usr/local/bin           ;# prepare default
foreach dir [split $env(PATH) :] {      ;# now look for real location
        if [file executable $dir/expect] {
                set expectpath $dir
                break
        }
}

cmd "#![set expectpath]/expect -f
#
# This Expect script was generated by autoexpect on [timestamp -format %c]
# Expect and autoexpect were both written by Don Libes, NIST."
cmd {#
# Note that autoexpect does not guarantee a working script.  It
# necessarily has to guess about certain things.  Two reasons a script
# might fail are:
#
# 1) timing - A surprising number of programs (rn, ksh, zsh, telnet,
# etc.) and devices discard or ignore keystrokes that arrive "too
# quickly" after prompts.  If you find your new script hanging up at
# one spot, try adding a short sleep just before the previous send.
# Setting "force_conservative" to 1 (see below) makes Expect do this
# automatically - pausing briefly before sending each character.  This
# pacifies every program I know of.  The -c flag makes the script do
# this in the first place.  The -C flag allows you to define a
# character to toggle this mode off and on.

set force_conservative 0  ;# set to 1 to force conservative mode even if
                          ;# script wasn't run conservatively originally
if {$force_conservative} {
        set send_slow {1 .1}
        proc send {ignore arg} {
                sleep .1
                exp_send -s -- $arg
        }
}

#
# 2) differing output - Some programs produce different output each time
# they run.  The "date" command is an obvious example.  Another is
# ftp, if it produces throughput statistics at the end of a file
# transfer.  If this causes a problem, delete these patterns or replace
# them with wildcards.  An alternative is to use the -p flag (for
# "prompt") which makes Expect only look for the last line of output
# (i.e., the prompt).  The -P flag allows you to define a character to
# toggle this mode off and on.
#
# Read the man page for more info.
#
# -Don

}

cmd "set timeout -1"
if $conservative {
        set send_style " -s"
        cmd "set send_slow {1 .1}"
} else {
        set send_style ""
}

if [llength $argv]>0 {
        eval spawn -noecho $argv
        cmd "spawn $argv"
} else {
        spawn -noecho $env(SHELL)
        cmd "spawn \$env(SHELL)"
}

cmd "match_max 100000"

set lastkey ""
set procbuf ""
set userbuf ""
set echoing 0

remove_nulls 0

eval interact $option_keys {
        -re . {
                input $interact_out(0,string)
        } null {
                input_null
        } \
        -o \
        -re .+ {
                output $interact_out(0,string)
        } eof {
                cmd "expect eof"
                return
        } null {
        }
}

close $fd
verbose_send_user "autoexpect done, file is $filename\n"

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.