This is either an oversight in the current implementation *or* its a bug. Or both. Bug described is on Win32.
To read a line of input:
readline Sx, Ix
Switches to line buffered mode and reads from fd Ix.
This works great:
readline $S0, 0
print $S0
But is the old, deprecated way of doing things. As a matter of fact, it's nigh impossible now to open an FD to a file and do anything useful with it as enough bits of the "old way" of doing things are dismantled now...
So, I'm trying to use the new ParrotIO stuff, and according to it I should get a ParrotIO object for STDIN:
fdopen $P1, 0, "r"
And then use the read Sx, Px, Ix function (which on a line-buffered descriptor line STDIN, should stop at EOL):
read $S0, $P1, 255
This crashes:
.sub _main
fdopen $P1, 0, "r" # STDIN
read $S0, $P1, 255
print $S0
end
.end
Suggestions welcome!
> Suggestions welcome!
First, always check the result of IO operations. If something fails,
these return a PerlUndef, so:
.sub _main
fdopen $P1, 0, "r" # STDIN
defined $I0, $P1
unless $I0, err
read $S0, $P1, 255
print $S0
end
err:
print "fdopen failed\n"
end
.end
2. C<fdopen> was disabled totally due to a wrong #ifdef
3. its currently only defined for PIO_OS_UNIX
4. Thanks again for your really valuable bug reports.
leo
*Doh* Stupid Newbie Error.
> unless $I0, err
> read $S0, $P1, 255
> print $S0
> end
> err:
> print "fdopen failed\n"
> end
> .end
>
> 2. C<fdopen> was disabled totally due to a wrong #ifdef
> 3. its currently only defined for PIO_OS_UNIX
Okaaay, so the plan is for this to work and I should probably code this way anyway, right?
BTW
fdopen $P1, 0, "<" # read STDIN
>> 3. its currently only defined for PIO_OS_UNIX
> Okaaay, so the plan is for this to work and I should probably code this way anyway, right?
You could just delete the #ifdef PIO_OS_UNIX in io.ops:fdopen and see,
if its working.
leo
Given Jürgen's patch to completely remove the integer file descriptors and to add the getstdin, getstdout, and getstderr I think this bug can be dropped. fdopen() isn't completely functional under Win32 (either that, or I blew the part where I expose the Unix interface) but this should take care of most fd problems in Win32. (I don't think I've *ever* seen a Windows program pass a file descriptor...)
Given that, there's a possible bug in Jürgen's patch (or IMCC?). Given:
.sub _main
call _INIT
.arg 0
call _READLINE
.result $S0
print $S0
end
.end
.sub _INIT
$P0=new PerlArray # Array of BASIC FD's
getstdin $P1 # traditional #0
defined $I0, $P1
unless $I0, err
$P0[0]=$P1
getstdout $P1 # traditional #1, etc...
$P0[1]=$P1
defined $I0, $P1
unless $I0, err
store_global "FDS", $P0
ret
err: print "Cannot get handle for STDIN"
end
.end
.sub _READLINE # string readline(int fd)
saveall
.param int fd
find_global $P0, "FDS"
$P1=$P0[fd]
set $S0, ""
read $S0, $P1, 255 # <-- Crunch
.return $S0
restoreall
ret
.end
This produces the PASM:
_main:
bsr _INIT
save 0
bsr _READLINE
restore S0
print S0
end
_INIT:
new P1, 19 # .PerlArray
getstdin P0
defined I0, P0
unless I0, err
set P1[0], P0
getstdout P0 # <-- bug is here? Overwrote my P0.
set P1[1], P0
store_global "FDS", P1
ret
err:
print "Cannot get handle for STDIN"
end
_READLINE:
saveall
restore I0
find_global P0, "FDS"
set P0, P0[I0]
set S0, ""
read S0, P0, 255
save S0
restoreall
ret
Given that I'm just taking STDIN, STDOUT, STDERR and trying to stuff them into an array, should I have to use three different registers for this in the PIR?
new $P4, PerlArray
getstdin $P0
getstdout $P1
getstderr $P2
$P4[0], $P0
$P4[1], $P1
$P4[2], $P2
Or should getstdin/out/err have not overwritten the Px register and given up a new one each time?
Either behavior is fine, so long as we're consistant and/or documented.
> set P1[0], P0
> getstdout P0 # <-- bug is here? Overwrote my P0.
> set P1[1], P0
Yep a bug is here. But this bug is a BASIC compiler bug. Things that go
into aggregates (or are stored in lex pads/global tables) are stored by
reference. You have to clone PMCs to get independed vars:
.sub _main
$P0 = new PerlArray
$P1 = new PerlString
$P1 = "ok\n"
$P0[0] = $P1
$P1 = "no\n"
$P0[1] = $P1
$P2 = $P0[0]
$P3 = $P0[1]
print $P2
print $P3
end
.end
$ parrot pierce.imc
no
no
leo
> new $P4, PerlArray
A current workaround for the missing clone in ParrotIO:
getstdin P0
getstdout P1
getstderr P2
$P4[0], P0
$P4[1], P1
$P4[2], P2
leo
What is that supposed to do?
As I understand it it reads a line from stdin and writes it to
standard out.
A short test of this code simply worked.
If it does not work for you, can you send me a parrot -t of this code?
> This produces the PASM:
>
> _main:
> bsr _INIT
> save 0
> bsr _READLINE
> restore S0
> print S0
> end
> _INIT:
> new P1, 19 # .PerlArray
> getstdin P0
> defined I0, P0
> unless I0, err
> set P1[0], P0
> getstdout P0 # <-- bug is here? Overwrote my P0.
Overwriting P0 is not a problem here. You don't use it any more.
Overwriting P1[0] would be a problem, but this should not be the case
because getstd* create always a new PMC.
> set P1[1], P0
> store_global "FDS", P1
> ret
> err:
> print "Cannot get handle for STDIN"
> end
> _READLINE:
> saveall
> restore I0
> find_global P0, "FDS"
> set P0, P0[I0]
> set S0, ""
> read S0, P0, 255
> save S0
> restoreall
> ret
> Either behavior is fine, so long as we're consistant and/or documented.
getstd* Px don't change the value of the old Px, but changing the
pointer to a new PMC. Its like
set P0, P1
and not like
assign P0, P1
bye
boe
--
Juergen Boemmels boem...@physik.uni-kl.de
Fachbereich Physik Tel: ++49-(0)631-205-2817
Universitaet Kaiserslautern Fax: ++49-(0)631-205-3906
PGP Key fingerprint = 9F 56 54 3D 45 C1 32 6F 23 F6 C7 2F 85 93 DD 47
What I do know is that imcc -t under Win32 is crash-happy and I can't trace beyond the first getstdin. Greatly simplified example:
.sub _main
$P0=new PerlArray
getstdin P2
defined $I0, P2
unless $I0, err
$P0[0]=P2
getstderr P3 # STDOUT
defined $I0, P3 # STDOUT
$P0[1]=P3 # STDOUT
unless $I0, err # STDOUT
$P1=$P0[0]
set $S0, ""
read $S0, $P1, 255
print $S0
end
err:print "Error"
end
.end
The above code crashes, but not where I thought it did -- it occurs immediately *after* the read in either the print or end. Do any one of the following and the code works great:
* Remove the print $S0 -- things are fine
* Remove the code indicated by # STDOUT -- things are fine
* Remove the read $S0, $P1, 255 -- peachy as well.
[Offtopic: a small plea goes out to anyone who can get imcc -t under Win32 to not crash...]
> getstderr P3 # STDOUT
^^^^
Should have been "getstdout"
Although... if left at getstderr the error also goes away. (Add that to my bullet list.) My haven't-grokked-the-code psychic abilities tell me that "getstdout" does something Real Bad to the stdout filehandle and any later uses of it (with print?) cause segfaults.
> What I do know is that imcc -t under Win32 is crash-happy
Snippet runs fine on Linux (with typo adjusted or not) as well as your
previous one, -t or not.
But, as IO is under *construction* some issues might remain. They'll get
resolved.
leo