/*
 * $Id: /mirror/trunk/src/ops/sys.ops 32253 2008-10-28T20:44:01.227920Z julianalbo  $
** sys.ops
*/

VERSION = PARROT_VERSION;

=head1 NAME

sys.ops - System Interaction Ops

=head1 DESCRIPTION

Operations that allow the user to interact with the system.

=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.

RT#36619: spawnw should return something less system-dependent, and more
object-like. see RT ticket [perl #36619] for more info.

=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<gmtime>(out STR, in INT)

Take the integer, which represents GMT epoch-seconds, and turn it into a
formatted string.

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

Take the integer, which represents GMT epoch-seconds, and turn it into a
formatted string. The time is adjusted to localtime before formatting.

=item B<decodetime>(out PMC, in INT)

Take the integer, which represents GMT epoch-seconds, and return an Array
PMC which represents the decoded time. The array elements are
(include "tm.pasm" for the constants):

=over 4

=item 0, .TM_SEC

Seconds (0-60)

=item 1, .TM_MIN

Minutes (0-59)

=item 2, .TM_HOUR

Hours (0-23)

=item 3, .TM_MDAY

Day of month (1-31)

=item 4, .TM_MON

Month of year (1-12) (Note, B<actual> month, not month - 1)

=item 5, .TM_YEAR

Year (note, B<actual> year. The year 2004 comes back as 2004, not 104)

=item 6, .TM_WDAY

Day of week. Sunday is day 0

=item 7, .TM_YDAY

Day of year (0-365)

=item 8, .TM_ISDST

Daylight savings/summer time in effect

=back

Timezone name will be GMT and offset will be 0, since the time is taken and
decoded as GMT.

=item B<decodelocaltime>(out PMC, in INT)

Take the passed in  integer, which represents GMT epoch-seconds, and return
an array as in decodetime. The time is first shifted to localtime before
decoding.

=cut

op gmtime(out STR, in INT) {
  struct tm tm;
  const time_t t = (time_t) $2;
  char resultbuffer[26];
  Parrot_gmtime_r(&t, &tm);
  Parrot_asctime_r(&tm, resultbuffer);
  $1 = string_from_cstring(interp, resultbuffer, 25);
}

op localtime(out STR, in INT) {
  struct tm tm;
  const time_t t = (time_t) $2;
  char resultbuffer[26];
  Parrot_localtime_r(&t, &tm);
  Parrot_asctime_r(&tm, resultbuffer);
  $1 = string_from_cstring(interp, resultbuffer, 25);
}

op decodetime(out PMC, in INT) {
  struct tm tm;
  const time_t t = (time_t) $2;
  Parrot_gmtime_r(&t, &tm);
  $1 = tm_to_array(interp, &tm);
}

op decodelocaltime(out PMC, in INT) {
  struct tm tm;
  const time_t t = (time_t) $2;
  Parrot_localtime_r(&t, &tm);
  $1 = tm_to_array(interp, &tm);
}

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

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

=item B<sysinfo>(out INT, in INT)

Return system information. The values it returns depends on what you
ask. They are:

=over 4

=item 1 The size of a platform integer

=item 2 The size of a platform float

=item 3 The size of a platform pointer. (Largest possible data pointer)

=item 4 The OS name

This is something like "OS X", "MacOS", "Windows", or "VMS".

=item 5 The OS version string

This is the current (hopefully) OS Version. For OSes that have plain
version numbers it will be the version number. For OSes that name
their versions, it will be the version name.

On HP/UX, this may be something like 11.2, while on Windows it may be
"95", "98", "2000", "NT", "ME", or "XP".

=item 6 The OS version number string

On OSes that don't name themselves, this will be the same as what's
returned in the OS version string. On OSes that I<do> name themselves,
this will be a more specific version number. In all cases it is OS
dependent.

=item 7 The CPU architecture

The name of the CPU family, such as "VAX", "Alpha", "PPC", or "x86".

=item 8 The CPU model

The model name of the current system's CPU. This is something like
"EV68", "Athlon", or "Pentium III".

=back

Note that some of these values may be set at Parrot compile time,
rather than at runtime, if the system has no reliable way to fetch the
data dynamically, or if there is no way the value can change. Also,
the value returned may be somewhat misleading--Parrot running under a
VirtualPC window will report "Windows" as its OS and "x86" as its CPU,
even if it's really running on an OS X system.

=cut

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

inline op sysinfo(out INT, in INT) {
   $1 = sysinfo_i(interp, $2);
}

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

=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 *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 *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);
}

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

=item B<sizeof>(out INT, in INT)

Get the size of native datatype $2 in $1.

=cut

inline op sizeof (out INT, in INT) {
    if ($2 < enum_first_type || $2 >= enum_last_type)
        $1 = -1;
    else
        $1 = data_types[$2 - enum_first_type].size;
}

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

=back

=head1 COPYRIGHT

Copyright (C) 2001-2008, The Perl 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:
 */
