I am trying to control a simple Fortran program via Expect under
Windows (using ActiveTcl 8.4.12).
The Fortran program merely prints a text, the user is expected to type
in a short string and then
the program prints it out. Of course I am not very interested in this
program in particular, it is
just a simple example.
The Fortran program looks like this:
program echo
character(len=60) :: text
integer :: count
count = 0
do
! write(*,'(a)', advance='no') 'Your text (Q=stop):'
write(*,'(a)') 'Your text (Q=stop):'
read(*,'(a)') text
if ( text == 'Q' ) exit
write(*,'(a)') text
count = count + 1
if ( count > 100 ) exit
enddo
end program
Note there are two variations of the write statement.
The Tcl program I use is this:
# echo_exp.tcl --
# Program ad hoc: use Expect to drive a Fortran program
#
package require Expect
set pid [exp_spawn echo.exe]
set count 0
while {1} {
incr count
expect $pid -re {.+\r} {
puts $expect_out(buffer)
exp_send $pid "Oho"
} -re {Y.*} {
puts "Y -- $expect_out(buffer)"
exp_send -i $pid "Oho $count\n"
} timeout {
puts "Timeout!"
} eof {
exp_close $pid
break
}
}
puts Done
(I am a mere beginner with Expect, so I have kept it simple)
The problem is this (running tclsh in a DOS-box for simplicity):
- If I use the write statement without advance='no', then the Tcl
program will
show the text "?????4?????Y -- Your text (Q=stop):" and then
"Timeout!"
is printed.
I can finish the Tcl program via a control-C
But there appears to be no output sent to the Fortran echo program.
(I also tried with \r instead of \n)
- If I use the write statement _with_ advance='no', then all I get to
see
is "??????4?????".
tclsh has to be killed via the task manager.
(The ?????4????? is strange of course, but it is not my main problem at
the moment).
I tried something similar with pipes and that worked without any
problems
except that with advance='no' (to keep the cursor on the same line when
the user is typing a string) there is no text shown until the echo
program
has received a string.
Does anyone have a suggestion as to how to proceed here? What am I
doing wrong?
Regards,
Arjen
Bruce
Shouldn't you either set G95_UNBUFFERED_ALL, or call flush() fre-
quently, on the Fortran side?
Does autoexpect <URL: http://wiki.tcl.tk/autoexpect > help you?
Do you want advice on using it?
There are several more issues to raise. Let's settle a few of
the loose ends first, though.
> In article <1152073047....@l70g2000cwa.googlegroups.com>,
> Arjen Markus <arjen....@wldelft.nl> wrote:
> >Hello,
> >
> >I am trying to control a simple Fortran program via Expect under
> >Windows (using ActiveTcl 8.4.12).
> .
> .
> .
> I definitely recommend you "send ...\r" rather than "send ...\n".
Right, I will do that.
I realised one reason for the timeout of the first version:
the first pattern never matches (which is why I introduced the second
one)
>
> Shouldn't you either set G95_UNBUFFERED_ALL, or call flush() fre-
> quently, on the Fortran side?
>
That is necessary with some compilers/platforms, but not in this case.
> Does autoexpect <URL: http://wiki.tcl.tk/autoexpect > help you?
> Do you want advice on using it?
>
> There are several more issues to raise. Let's settle a few of
> the loose ends first, though.
Hm, autoexpect ... I will try that first and report my findings.
Regards,
Arjen
>
> Hm, autoexpect ... I will try that first and report my findings.
>
Alas, I am out of luck:
After obtaining the autoexpect script, I had to remove the line "exec
chmod +x ..." and
add a "package require Expect". Then I found out that the interact
command
is not implemented in the Windows version.
Okay, back to some basic experimentation then.
Regards,
Arjen
I used "exp_internal 1" to get a log from Expect's actions:
expect: does "" (spawn_id exp4) match glob pattern "388"? no
".+\n"? no
"Y.*"? no
"O.*"? no
Your text (Q=stop):
expect: does "Your text (Q=stop):\n" (spawn_id exp4) match glob pattern
"388"? no
".+\n"? no
"Y.*"? yes
expect: set expect_out(0,string) "Your text (Q=stop):\n"
expect: set expect_out(spawn_id) "exp4"
expect: set expect_out(buffer) "Your text (Q=stop):\n"
warning: indirect variable 388 undefinedsend: sending "Oho 1\r" to {}
expect: does "" (spawn_id exp4) match glob pattern "388"? no
".+\n"? no
"Y.*"? no
"O.*"? no
expect: timed out
expect: does "" (spawn_id exp4) match glob pattern "388"? no
".+\n"? no
"Y.*"? no
"O.*"? no
Strange things:
1. A glob pattern 388 (the number changes from run to run, but there is
always
a glob pattern reported)
2. ".+\n" or ".+" _never_ matches
3. The send command gives a warning, but I see that the text is
received by
the Fortran program (that is logging now too).
4. There is only one text being received (not entirely sure whether the
problem
is Expect here, might be the Fortran side - needing to flush the
output).
If however, I use "exp_send ..." _without_ the -i flag:
expect: does "" (spawn_id exp4) match glob pattern "2572"? no
".+\n"? no
"Y.*"? no
"O.*"? no
????4?????
expect: does "Your text (Q=stop):\n" (spawn_id exp4) match glob pattern
"2572"?
no
".+\n"? no
"Y.*"? yes
expect: set expect_out(0,string) "Your text (Q=stop):\n"
expect: set expect_out(spawn_id) "exp4"
expect: set expect_out(buffer) "Your text (Q=stop):\n"
Y -- Your text (Q=stop):
send: sending "Oho 1\r" to { exp4 }
expect: does "" (spawn_id exp4) match glob pattern "2572"? no
".+\n"? no
"Y.*"? no
"O.*"? no
???+++++++++++++++++++++++++++
and tclsh gets stuck - I need to kill it via the task manager again.
I am afraid that is it for the moment. I have run out of ideas! (And
time)
Regards,
Arjen
... and later he wrote:
> I used "exp_internal 1" to get a log from Expect's actions:
>
> expect: does "" (spawn_id exp4) match glob pattern "388"? no
>
> ".+\n"? no
> ...
I'm no expert on expect, but isn't the usage of the expect command
"expect ?options? pattern body ?options? pattern body ..."?
I think your first pattern is $pid (and thus the diagnostic 'does "" ...
match glob pattern "388"?') and your first body is the three-byte string
-re. Your second pattern is the literal {.+\r} since the option "-re" is
treated as the body of the first pattern.
--
Bryan Oakley
http://www.tclscripting.com
> I'm no expert on expect, but isn't the usage of the expect command
> "expect ?options? pattern body ?options? pattern body ..."?
>
> I think your first pattern is $pid (and thus the diagnostic 'does "" ...
> match glob pattern "388"?') and your first body is the three-byte string
> -re. Your second pattern is the literal {.+\r} since the option "-re" is
> treated as the body of the first pattern.
>
That would account for the mysterious glob pattern - reading the manual
is not enough, you also need to turn off preconceptions :(.
Well, trying that improved version:
- The first pattern now works properly
- The Fortran program does not seem to send anything back (a buffering
problem, perhaps, as Cameron suggested). But via pipes there was
no such problem :(
Oh, it did not receive anything - removing -i $pid from the exp_send
command
results in:
expect: does "" (spawn_id exp4) match regular expression ".+\n"? no
"Y.*"? no
"O.*"? no
????4?????
expect: does "Your text (Q=stop):\n" (spawn_id exp4) match regular
expression ".
+\n"? yes
expect: set expect_out(0,string) "Your text (Q=stop):\n"
expect: set expect_out(spawn_id) "exp4"
expect: set expect_out(buffer) "Your text (Q=stop):\n"
Your text (Q=stop):
send: sending "Oho\r" to { exp4 }
expect: does "" (spawn_id exp4) match regular expression ".+\n"? no
"Y.*"? no
"O.*"? no
??++++++++++++++++++++++++++++
and then tclsh hangs!
I am deeply puzzled now ....
Regards,
Arjen
> and then tclsh hangs!
>
> I am deeply puzzled now ....
>
Thanks to Mark Stucky, the source of the problem has been
locate: he ran the same programs (both Fortran and Tcl),
using the same compiler and it all worked ... Except,
he used a Cygwin terminal and tkcon to run them, whereas
I used a plain DOS box. With a DOS box he got the same
(mis)behaviour!
I repeated my experiments using tkcon:
It all works without a trace of the previous problems!
It even works if I use the advance=no option.
So, I leave it to the experts to find out why a DOS box
causes so much trouble ...
Regards,
Arjen