/*
 * $Id: sys.ops 47428 2010-06-06 08:32:34Z cotto $
** sys.ops
*/

=head1 NAME

sys.ops - System Interaction Opcodes

=head1 DESCRIPTION

Operations that allow the user to interact with the system.

When making changes to any ops file, run C<make bootstrap-ops> to regenerate
all generated ops files.

=over 4

=cut

###############################################################################

=item B<spawnw>(out INT, in STR)

Spawn a subprocess whose program name and arguments are contained in the string
$2 and wait for it to finish. The return status, which is very
system-dependent, goes in $1.

=item B<spawnw>(out INT, invar PMC)

Spawn a subprocess whose program name and arguments are contained in the array
$2 and wait for it to finish. The return status, which is very
system-dependent, goes in $1.

TT #847: C<spawnw()> should itself handle splitting up command-line arguments,
rather than depending on the shell to do so in potentially unsafe manner.
See https://trac.parrot.org/parrot/ticket/847.

TT #848: C<spawnw()> should return something less system-dependent, and more
object-like. See https://trac.parrot.org/parrot/ticket/848.

=cut

inline op spawnw(out INT, in STR) {
    $1 = Parrot_Run_OS_Command(interp, $2);
}

inline op spawnw(out INT, invar PMC) {
    $1 = Parrot_Run_OS_Command_Argv(interp, $2);
}

###############################################################################

=item B<err>(out INT)

Store the system error code in $1.

=item B<err>(out STR)

Store the system error message in $1.

=item B<err>(out STR, in INT)

Get the system error message for the system error code $2
and store it in $1.

=cut

inline op err(out INT) {
    $1 = errno;
}

op err(out STR) {
    const char * const tmp = strerror(errno);
    $1 = string_make(interp, tmp, strlen(tmp), "ascii", 0);
}

op err(out STR, in INT) {
    const char * const tmp = strerror($2);
    $1 = string_make(interp, tmp, strlen(tmp), "ascii", 0);
}


########################################

=item B<time>(out INT)

Puts the current system time (represented as a whole number of seconds)
in $1.

=cut

inline op time(out INT) {
    $1 = Parrot_intval_time();
}


########################################

=item B<time>(out NUM)

Puts the current system time (represented as a number of seconds, with
microseconds) in $1.

=cut

inline op time(out NUM) {
    $1 = Parrot_floatval_time();
}

########################################

=item B<sleep>(in INT)

=item B<sleep>(in NUM)

Sleep for $1 seconds.

=cut

inline op sleep(in INT) :flow {
    opcode_t *next = expr NEXT();
    if ($1 < 0) {
        opcode_t * const handler = Parrot_ex_throw_from_op_args(interp, next,
            EXCEPTION_NEG_SLEEP,
            "Cannot go back in time");
        goto ADDRESS(handler);
    }
    next = (opcode_t *)Parrot_cx_schedule_sleep(interp, (FLOATVAL) $1, next);
    goto ADDRESS(next);
}

inline op sleep(in NUM) :flow {
    opcode_t *next = expr NEXT();
    if ($1 < 0.0) {
        opcode_t * const handler = Parrot_ex_throw_from_op_args(interp, next,
            EXCEPTION_NEG_SLEEP,
            "Cannot go back in time");
        goto ADDRESS(handler);
    }
    next = (opcode_t *)Parrot_cx_schedule_sleep(interp, $1, next);
    goto ADDRESS(next);
}

###############################################################################

=back

=head1 COPYRIGHT

Copyright (C) 2001-2009, Parrot Foundation.

=head1 LICENSE

This program is free software. It is subject to the same license
as the Parrot interp itself.

=cut

/*
 * Local variables:
 *   c-file-style: "parrot"
 * End:
 * vim: expandtab shiftwidth=4:
 */
