Process.run
by Peter Bortas (nu med mindre Opera) @ Pike (-) developers forum
14 Jul '08
14 Jul '08
I just checked in a Process.run() in 7.7:
http://pike.ida.liu.se/development/cvs/diff.xml?module=Pike&file=7.7/lib/mo…
The rational for that is that I was once again reminded by a user this
week that getting Process.create_process() or Process.Process right
without some corner case blocking is hard. It's not obvious that if
you bind pipes to booth stderr and stdout you have to take in to
account that OS buffers are not limetless.
Process.run() is a thin wrapper around Process.Process …
[View More]that collects
stdout, stderr and exitcode and return them in a mapping. This could
potentially result in huge strings, but will do what most users want
and even already do when they call create_process() with both pipes
bound.
Something like this should be in 7.8, but I'm open to suggestions for
other things that might be usefull to return in the mapping or for
changing member names.
[View Less]
5
7
Getopt mark II
by Martin Nilsson (Opera Mini - AFK!) @ Pike (-) developers forum
19 Apr '08
19 Apr '08
(or rather Getopt mark III, since I've already rewritten the current
one, although no functionality was changed then)
I've been working a bit on a new Argument parser, and would like some
input. In reality there will be two different way of using the argument
parser, which really doesn't share any code but is convenient to do at
the same time. The first one is a "I just want to get this over with"
kind of interface:
void main(int num, array argv)
{
mapping args = Arg.parse(argv);
argv = …
[View More]args[Arg.REST];
}
The output will contain ([ "foo":1 ]) if the argument is --foo and ([
"foo":"bar" ]) if the argument is --foo=bar. There is no fancy stuff to
handle default values (just or it with another mapping) or options that
may or may not have values (e.g. -bar=foo will produce ([ "b":1, "a":1,
"r":"foo" ]) and --foo x --bar will just produce ([ "foo":1 ]) and then
stop processing the line).
The other mode is the (supposedly) easy yet powerful mode that you would
use for more mature applications.
class Parser
{
inherit Arg.Options;
Arg verbose = NoArg("-v")|NoArg("--verbose")|Env("VERBOSE");
Arg level = HasArg("-l")|HasArg("--level");
}
void main(int n, array argv)
{
Parser p = Parser(argv);
// Index magic. Some like it, some not so much.
if( p->verbose )
werror("Level %s\n", p->level);
}
Which is extended in
class Parser
{
// The name for now.
inherit Arg.OptionsSupreme;
Arg verbose = NoArg("-v")|NoArg("--verbose")|Env("VERBOSE");
// These are used in the automatically generated --help response.
string help_pre = "This program is like awesum.";
string verbose_help = "Increases the verbosity of the program.";
// Called when/if verbose is set to a value.
void verbose_cb(string arg)
{
werror("Verbosity is on.\n");
}
}
Does this match the long list of requirements that I've heard from
others?
[View Less]
I have a few questions relating to pike in Debian (as you may know,
the previous maintainer has retired from Debian and orphaned his
packages).
I've figured out that one can get a fresh tarball from
http://pike.ida.liu.se/generated/pikefarm/packages/7.6/latest. What's
the difference between that and checking out from CVS and running
"make source" (which is what I suspect Marek has done), if any? Is
there any archive of such tarballs except for the official releases?
How did the packaging/…
[View More]debian subdirectory originally come to be? Do
you synchronize with the Debian package yourself or has Marek been
sending you patches? I see that export.pike adds new records to
packaging/debian/changelog. AFAICT, export.pike --tag first increments
the build number (to an even number, typically), then tags, then
increment the build number again, so that an even build number
represents a known state of the source, whereas an odd build number
can include any number of commits inbetween.
[View Less]
> yeah, but next() is optional and not used by foreach
There's no indication that next() is optional. At the very least, the
documentation is somewhat lacking, if for no other reason than the
api including two parallel sets of functions for interacting with the
iterator, one of which is relatively more "standard" than the other
without stating clearly which functions are actually used. I think
most people who have used other languages with iterators will feel
more comfortable …
[View More]with ->next() and friends, and be confused that
they're not actually used. I know I was, and I'm probably not alone.
> and += returns the iterator itself, so you can't return UNDEFINED
> there.
> since += never fails the only option is to test wether you still
> have an
> item there or not, and then ! is a good choice for that test.
Well, you can very easily return undefined from `+=(), and it doesn't
make any difference. That, at the very least, should have prompted an
error, but instead, it kept right on running. I'm not sure that the
semantics of this are appropriate, as the side effect is important
(or should be, even if you're always supposed to return this_object()
from `+=()).
> it would be different if next() where the standard way of advancing
> the
> iterator.
Well, it is the "standard" way, [by "standard", I mean the pattern
employed by C++, Java, Objective-C, etc] Pike just happens to use
operator overloading instead.
Anyhow, my problem is solved. If I find time, I may update the
documentation to be a little more clear about what's required and
what's optional.
Bill
[View Less]
I'm writing an iterator and under 7.7.34 (at least), I can't seem to
get a loop using it to end, even though next() and `+=() both return
UNDEFINED at the end, but the foreach loop doesn't ever seem to end.
Am I missing something?
Bill
Hi.
Some of you may have noticed that I implemented static variables with
function scope a day or two ago. Example:
int inc()
{
static int counter;
return counter++;
}
The problem in Pike is that the intended lifetime of the variable
isn't always obvious; consider nested classes:
class X {
int inc()
{
static int counter;
return counter++;
}
}
int main()
{
function(:int) X1 = X()->inc;
function(:int) X2 = X()->inc;
…
[View More]write("X1:%O,%O\n"
"X2:%O\n",
X1(), X1(),
X2());
}
Should the above output X1:0,1 X2:0, or X1:0,1 X2:2? ie should the
variable be stored in X or in the top-level class?
Pike also has nested functions; consider:
function(:int) X()
{
int inc()
{
static int counter;
return counter++;
};
return inc;
}
int main()
{
function(:int) X1 = X();
function(:int) X2 = X();
write("X1:%O,%O\n"
"X2:%O\n",
X1(), X1(),
X2());
}
Same question.
I believe that the most useful would be to store the variable in the
closest surrounding scope (ie X1:0,1 X2:0 for both of the above), and
then have some extra syntax for specifying some other scope. The
question is what the syntax should be?
Any suggestions?
[View Less]
(forwarding this for matt, martin)
Greetings,
I am pleased to inform everyone concerned that the most preferred dates
have been confirmed and facilities booked in Copenhagen, Denmark.
14 + 15 + 16 November 2007.
First 2 days will be located at Copenhagen University.
Last official day is at a carrier neutral datacentre also located in
Copenhagen.
Further days, for those who have time to stay longer, are TBA, depending
on interest.
I now hope everyone can look at calendars to ensure they …
[View More]have adequate
time to attend the official program, it will be a very good chance to
carry on discussions from last year in Riga, as well as discuss new
developments undertaken since.
All submissions for presentation or discussion topics are welcome.
Please forward your submissions to the list, and/or you can attach
documents by email to matt(a)webhaven.eu
We will construct a 2007 website and publish a clear program for the
3 days.
Pike Conference 2007
Copenhagen, Denmark
---->8------
if (Human.Programmer("meaning you")->wants_to_go())
{
go();
}
----8<------
[View Less]
I've just made some experiments for a replacement to ADT.struct and
ADT.Struct:
> program struct =
>> ADT.Serialize.SimpleStruct("struct",
>> ADT.Serialize.Int32, "integer",
>> ADT.Serialize.SimpleStruct("substruct",
>> ADT.Serialize.String, "data"
>> ), "sub");
> object o = struct(14);
> indices(o);
(1) Result: ({ /* 5 elements */
"encode",
"decode",
"_integer",
"integer",
…
[View More] "sub"
})
> o->integer;
(2) Result: 14
> o->sub;
(3) Result: substruct()
> o->sub->data = "foobar";
(4) Result: "foobar"
A decent encoding API is easy:
> o->encode();
(5) Result: "\0\0\0\16foobar"
Now to the hard part; a streaming decoder API...
As far as I know, there are two main approaches:
* Pull -- the user sends a data source (eg a file object) to
the object, and it's up to the object to actually
read the data.
* Push -- the user reads the data in segments (typically with
non-blocking I/O), and pushes it into the object.
The Pull API is the easiest to implement, but it has the following
problems:
* Does not support non-blocking I/O.
* Error recovery is complicated (eg if the source is a pipe/socket).
* Extra over-head for the common case where you already have read
the data.
The Push API on the other hand has the following problems:
* How to find where to restart the decoding when more data arrives.
* How to signal that more data is needed/too much data was received.
Suggestions?
[View Less]