/*
// ColdMUD was created and is copyright 1993, 1994 by Greg Hudson
//
// ColdX is a derivitive work, and is copyright 1995 by the ColdX Project.
// Full copyright information can be found in the file doc/CREDITS
//
// File: miscop.c
// Version: 0.1-5
// Last Edited: 5 Aug 1995
//
// ---
//
// Miscellaneous operations.
*/
/* #define _POSIX_SOURCE */
#include "config.h"
#include <stdlib.h>
#include <time.h>
#include <sys/time.h> /* for mtime() */
#include "defs.h"
#include "x.tab.h"
#include "operator.h"
#include "execute.h"
#include "data.h"
#include "util.h"
#include "ident.h"
#include "lookup.h"
static void find_extreme(int which);
void op_version(void)
{
List *version;
Data *d;
/* Take no arguments. */
if (!func_init_0())
return;
/* Construct a list of the version numbers and push it. */
version = list_new(3);
d = list_empty_spaces(version, 3);
d[0].type = d[1].type = d[2].type = INTEGER;
d[0].u.val = VERSION_MAJOR;
d[1].u.val = VERSION_MINOR;
d[2].u.val = VERSION_PATCH;
push_list(version);
list_discard(version);
}
void op_random(void)
{
Data *args;
/* Take one integer argument. */
if (!func_init_1(&args, INTEGER))
return;
/* Replace argument on stack with a random number. */
args[0].u.val = random_number(args[0].u.val) + 1;
}
void op_time(void)
{
/* Take no arguments. */
if (!func_init_0())
return;
push_int(time(NULL));
}
void op_localtime(void)
{
struct tm * tms;
Data * d;
List * l;
time_t t;
register int x;
if (!func_init_0())
return;
time(&t);
tms = localtime(&t);
#if defined(Solaris) || defined(IRIX)
#define __LSIZE0__ 10
#define __LSIZE1__ 10
#else
#define __LSIZE0__ 11
#define __LSIZE1__ 12
#endif
l = list_new(__LSIZE0__);
d = list_empty_spaces(l, __LSIZE0__);
for (x=0; x < __LSIZE1__; x++)
d[x].type = INTEGER;
d[0].u.val = (int) t;
d[1].u.val = tms->tm_sec;
d[2].u.val = tms->tm_min;
d[3].u.val = tms->tm_hour;
d[4].u.val = tms->tm_mday;
d[5].u.val = tms->tm_mon;
d[6].u.val = tms->tm_year;
d[7].u.val = tms->tm_wday;
d[8].u.val = tms->tm_yday;
d[9].u.val = tms->tm_isdst;
#if !defined(Solaris) && !defined(IRIX)
d[10].u.val = tms->tm_gmtoff;
d[11].type = STRING;
d[11].u.str = string_from_chars(tms->tm_zone, strlen(tms->tm_zone));
#endif
push_list(l);
list_discard(l);
}
/* May as well give it to them, the code is in the driver */
void op_timestamp(void) {
String * str;
char * s;
/* Take no arguments. */
if (!func_init_0())
return;
s = timestamp(NULL);
str = string_from_chars(s, strlen(s));
push_string(str);
string_discard(str);
}
void op_strftime(void) {
char s[LINE];
char * fmt;
Data * args;
String * str;
int nargs;
time_t tt;
struct tm * t;
if (!func_init_1_or_2(&args, &nargs, STRING, INTEGER))
return;
tt = ((nargs == 2) ? (time_t) args[1].u.val : time(NULL));
t = localtime(&tt);
fmt = string_chars(args[0].u.str);
/* some OS's are weird and do odd things when you end in %
(accidentally or no) */
if (fmt[strlen(fmt)] == '%')
fmt[strlen(fmt)] = NULL;
if (strftime(s, LINE, fmt, t) == (size_t) 0) {
cthrow(range_id,
"Format results in a string longer than 80 characters.");
return;
}
str = string_from_chars(s, strlen(s));
pop(nargs);
push_string(str);
string_discard(str);
}
void op_mtime(void) {
struct timeval tp;
/* Take no arguments. */
if (!func_init_0())
return;
gettimeofday(&tp, NULL);
/* usec is microseconds */
push_int((int) tp.tv_usec);
}
void op_ctime(void)
{
Data *args;
int num_args;
time_t tval;
char *timestr;
String *str;
/* Take an optional integer argument. */
if (!func_init_0_or_1(&args, &num_args, INTEGER))
return;
tval = (num_args) ? args[0].u.val : time(NULL);
timestr = ctime(&tval);
str = string_from_chars(timestr, 24);
pop(num_args);
push_string(str);
string_discard(str);
}
/* which is 1 for max, -1 for min. */
static void find_extreme(int which)
{
int arg_start, num_args, i, type;
Data *args, *extreme, d;
arg_start = arg_starts[--arg_pos];
args = &stack[arg_start];
num_args = stack_pos - arg_start;
if (!num_args) {
cthrow(numargs_id, "Called with no arguments, requires at least one.");
return;
}
type = args[0].type;
if (type != INTEGER && type != STRING) {
cthrow(type_id, "First argument (%D) not an integer or string.",
&args[0]);
return;
}
extreme = &args[0];
for (i = 1; i < num_args; i++) {
if (args[i].type != type) {
cthrow(type_id, "Arguments are not all of same type.");
return;
}
if (data_cmp(&args[i], extreme) * which > 0)
extreme = &args[i];
}
/* Replace args[0] with extreme, and pop other arguments. */
data_dup(&d, extreme);
data_discard(&args[0]);
args[0] = d;
pop(num_args - 1);
}
void op_max(void)
{
find_extreme(1);
}
void op_min(void)
{
find_extreme(-1);
}
void op_abs(void)
{
Data *args;
if (!func_init_1(&args, INTEGER))
return;
if (args[0].u.val < 0)
args[0].u.val = -args[0].u.val;
}
void op_get_dbref(void)
{
Data *args;
long dbref;
if (!func_init_1(&args, SYMBOL))
return;
if (!lookup_retrieve_name(args[0].u.symbol, &dbref)) {
cthrow(namenf_id, "Cannot find object %I.", args[0].u.symbol);
return;
}
pop(1);
push_dbref(dbref);
}
void op_ticks_left(void)
{
if (!func_init_0())
return;
push_int(cur_frame->ticks);
}