mirror of
git://git.psyced.org/git/psyclpc
synced 2024-08-15 03:20:16 +00:00
870 lines
24 KiB
C
870 lines
24 KiB
C
|
/*---------------------------------------------------------------------------
|
||
|
* Wizard List
|
||
|
*
|
||
|
*---------------------------------------------------------------------------
|
||
|
* The Wizard List ("wizlist") started out as a means to determine a high
|
||
|
* score list of the most popular castles. Over the time, this list
|
||
|
* was generalized into a simple user-id management with driver-internal
|
||
|
* purposes.
|
||
|
*
|
||
|
* A user-id ("wizard name", "creator") is a unique string, and every object
|
||
|
* is associated with a uid through the master-apply get_wiz_name(object-name).
|
||
|
* The reverse doesn't hold true: the mudlib can use uids which are not
|
||
|
* associated with any object.
|
||
|
*
|
||
|
* A special uid is the number 0: this is denotes the 'default' wizard,
|
||
|
* ie. the system itself. Together with the .extra information feature,
|
||
|
* the wizlist entry for uid 0 can be used to store information "on driver
|
||
|
* level".
|
||
|
*
|
||
|
* Every uid represented with a wizlist entry of the following structure.
|
||
|
* Object structures even contain a '.user' entry pointing directly
|
||
|
* to the associated wizlist entry.
|
||
|
*
|
||
|
* struct wiz_list_s {
|
||
|
* wiz_list_t *next;
|
||
|
* string_t *name;
|
||
|
* int32 score;
|
||
|
* int32 cost;
|
||
|
* int32 gigacost;
|
||
|
* int32 total_cost;
|
||
|
* int32 total_gigacost;
|
||
|
* int32 heart_beats;
|
||
|
* mp_int size_array;
|
||
|
* mp_int mapping_total;
|
||
|
#ifdef USE_STRUCTS
|
||
|
* mp_int struct_total;
|
||
|
#endif
|
||
|
* svalue_t extra;
|
||
|
* int32 last_call_out;
|
||
|
* int32 call_out_cost;
|
||
|
* string_t *file_name;
|
||
|
* string_t *error_message;
|
||
|
* int32 line_number;
|
||
|
* };
|
||
|
*
|
||
|
* .name is the tabled uid string of this wizlist entry.
|
||
|
* .next is the pointer to the next entry in the wizlist.
|
||
|
*
|
||
|
* .score, .(total_)cost+.(total_)gigacost, .heart_beats, .size_array and
|
||
|
* .mapping_total collect statistics about the objects for this uid/wizard.
|
||
|
* .score is the number of action functions executed (weighted over time),
|
||
|
* .cost+.gigacost the eval ticks spent (weighted over time),
|
||
|
* .total_cost+.total_gigacost the eval ticks spent (total), .heart_beats the
|
||
|
* number of heart_beat() calls (weighted over time). .size_array and
|
||
|
* .mapping_total give the number of values held in arrays and mappings for
|
||
|
* this wizard.
|
||
|
*
|
||
|
* .extra offer space for one svalue which can be used by the mudlib
|
||
|
* for its own purposes. The driver can be instructed to fill the .extra
|
||
|
* member every newly created entry with an empty array of a specific
|
||
|
* size. Especially the .extra member for uid 0 can be used to store
|
||
|
* data persistent to the whole driver run - it even survives reloads
|
||
|
* of the master object.
|
||
|
*
|
||
|
* .last_call_out and .call_out_cost are used to manage the call_out.
|
||
|
* .call_out_cost is the collected execution cost of all call_outs
|
||
|
* executed for time .last_call_out for this .user. When executing
|
||
|
* call_outs, this value is used to prime the eval_cost counter, and
|
||
|
* thus prevents call_outs from hogging all the cpu.
|
||
|
*
|
||
|
* .file_name, .error_message and .line_number are used to communicate
|
||
|
* errors from the driver to the mudlib. Bit 30 (0x40000000) in line_number
|
||
|
* is the "forget flag": it is set when the mudlib queries the error
|
||
|
* information. This way the mudlib can distinguish old from new
|
||
|
* errors.
|
||
|
*
|
||
|
*
|
||
|
* Part of the wizard list information is stored in the toplevel file
|
||
|
* "WIZLIST". The file is organized in lines, one for every wizard.
|
||
|
* Each line must at least contain:
|
||
|
*
|
||
|
* <name> <score>
|
||
|
*
|
||
|
* No leading space, and <name> and <score> must be separated by one or
|
||
|
* more spaces. If existing, this information is read by the driver at
|
||
|
* startup and added(!) to the already existing wizlist entries.
|
||
|
*
|
||
|
* The mudlib is free to add more information after the <score> and read
|
||
|
* it itself. For the same reason it is the task of the mudlib to write
|
||
|
* the WIZLIST file.
|
||
|
*---------------------------------------------------------------------------
|
||
|
*/
|
||
|
|
||
|
#include "driver.h"
|
||
|
#include "typedefs.h"
|
||
|
|
||
|
#include "my-alloca.h"
|
||
|
|
||
|
#include <stdio.h>
|
||
|
|
||
|
#include "wiz_list.h"
|
||
|
#include "../mudlib/sys/wizlist.h"
|
||
|
|
||
|
#include "array.h"
|
||
|
#include "backend.h"
|
||
|
#include "gcollect.h"
|
||
|
#include "interpret.h"
|
||
|
#include "main.h"
|
||
|
#include "mapping.h"
|
||
|
#include "mstrings.h"
|
||
|
#include "object.h"
|
||
|
#include "simulate.h"
|
||
|
#include "stdstrings.h"
|
||
|
#include "svalue.h"
|
||
|
#include "xalloc.h"
|
||
|
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
wiz_list_t default_wizlist_entry
|
||
|
/* The default wizlist entry which is used for all "system" purposes.
|
||
|
*/
|
||
|
= { NULL /* next */
|
||
|
, NULL /* name */
|
||
|
, 0 /* score */
|
||
|
, 0 /* cost */
|
||
|
, 0 /* gigacost */
|
||
|
, 0 /* total_cost */
|
||
|
, 0 /* total_gigacost */
|
||
|
, 0 /* heart_beats */
|
||
|
, 0 /* size_array */
|
||
|
, 0 /* mapping_total */
|
||
|
#ifdef USE_STRUCTS
|
||
|
, 0 /* struct_total */
|
||
|
#endif
|
||
|
, { T_NUMBER } /* extra */
|
||
|
, 0 /* last_call_out */
|
||
|
, 0 /* call_out_cost */
|
||
|
, NULL /* error file_name */
|
||
|
, NULL /* error_message */
|
||
|
, 0 /* error line_number */
|
||
|
};
|
||
|
|
||
|
wiz_list_t *all_wiz = NULL;
|
||
|
/* The list of all wizard entries, sorted by the numeric value
|
||
|
* of <name>. If the names are queried equally often, this even yields
|
||
|
* an average O(1) complexity.
|
||
|
*/
|
||
|
|
||
|
static int wiz_info_extra_size = -1;
|
||
|
/* Default size of the .extra field, -1 if unspecified.
|
||
|
*/
|
||
|
|
||
|
static int number_of_wiz = 0;
|
||
|
/* Number of entries in the list.
|
||
|
*/
|
||
|
|
||
|
char wizlist_name[MAXPATHLEN+1] = "";
|
||
|
/* Name of the wizlist file, relative to the mudlib directory.
|
||
|
*/
|
||
|
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
void
|
||
|
name_wizlist_file (const char *name)
|
||
|
|
||
|
/* Set the swap file name to a copy of <name>.
|
||
|
*/
|
||
|
|
||
|
{
|
||
|
/* Skip leading '/' */
|
||
|
while (*name == '/') name++;
|
||
|
|
||
|
xstrncpy(wizlist_name, name, sizeof wizlist_name);
|
||
|
wizlist_name[sizeof wizlist_name - 1] = '\0';
|
||
|
} /* name_wizlist_file()*/
|
||
|
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
size_t
|
||
|
wiz_list_size (void)
|
||
|
|
||
|
/* Return the allocated size of the wiz_list.
|
||
|
*/
|
||
|
|
||
|
{
|
||
|
/* The extra wizinfo has been counted with the arrays */
|
||
|
return sizeof(wiz_list_t) * number_of_wiz;
|
||
|
} /* wiz_list_size() */
|
||
|
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
static wiz_list_t *
|
||
|
find_wiz (string_t *name)
|
||
|
|
||
|
/* Find the entry for the user 'name' and return it's pointer.
|
||
|
* Return NULL if it can't be found.
|
||
|
*/
|
||
|
|
||
|
{
|
||
|
wiz_list_t *wl;
|
||
|
|
||
|
if ( !( name = find_tabled(name) ) )
|
||
|
return NULL;
|
||
|
|
||
|
for (wl = all_wiz; wl; wl = wl->next)
|
||
|
{
|
||
|
int rc = mstrcmp(wl->name, name);
|
||
|
|
||
|
if (!rc)
|
||
|
return wl;
|
||
|
if (rc > 0)
|
||
|
break;
|
||
|
}
|
||
|
return NULL;
|
||
|
} /* find_wiz() */
|
||
|
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
wiz_list_t *
|
||
|
add_name (string_t * str)
|
||
|
|
||
|
/* Check if an entry for wizard <str> exists; add it, if it doesn't.
|
||
|
* Return the pointer to the wiz_list entry.
|
||
|
* Must not change refcount of <str>.
|
||
|
*/
|
||
|
|
||
|
{
|
||
|
wiz_list_t *wl;
|
||
|
wiz_list_t *prev, *this;
|
||
|
|
||
|
wl = find_wiz(str);
|
||
|
if (wl)
|
||
|
return wl;
|
||
|
|
||
|
number_of_wiz++;
|
||
|
wl = xalloc(sizeof (wiz_list_t));
|
||
|
|
||
|
str = make_tabled_from(str);
|
||
|
|
||
|
wl->next = NULL;
|
||
|
wl->name = str;
|
||
|
wl->score = 0;
|
||
|
wl->cost = 0;
|
||
|
wl->gigacost = 0;
|
||
|
wl->total_cost = 0;
|
||
|
wl->total_gigacost = 0;
|
||
|
wl->heart_beats = 0;
|
||
|
wl->size_array = 0;
|
||
|
wl->mapping_total = 0;
|
||
|
#ifdef USE_STRUCTS
|
||
|
wl->struct_total = 0;
|
||
|
#endif /* USE_STRUCTS */
|
||
|
#if 0
|
||
|
wl->quota_allowance = 0;
|
||
|
wl->quota_usage = 0;
|
||
|
#endif
|
||
|
wl->file_name = NULL;
|
||
|
wl->error_message = NULL;
|
||
|
if (wiz_info_extra_size >= 0)
|
||
|
put_array(&(wl->extra), allocate_array(wiz_info_extra_size));
|
||
|
else
|
||
|
wl->extra = const0;
|
||
|
wl->last_call_out = 0;
|
||
|
|
||
|
/* Find the insertion point and insert the new entry */
|
||
|
for ( prev = NULL, this = all_wiz
|
||
|
; this && mstrcmp(this->name, str) < 0
|
||
|
; prev = this, this = this->next
|
||
|
)
|
||
|
{ NOOP; }
|
||
|
|
||
|
if (!prev)
|
||
|
{
|
||
|
wl->next = all_wiz;
|
||
|
all_wiz = wl;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
wl->next = this;
|
||
|
prev->next = wl;
|
||
|
}
|
||
|
|
||
|
return wl;
|
||
|
} /* add_name() */
|
||
|
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
void
|
||
|
wiz_decay (void)
|
||
|
|
||
|
/* Called after every complete walkaround of the reset, this 'decays'
|
||
|
* the score of every wizard once per hour.
|
||
|
* Together with the decay, the wizlist is checked for destructed extra
|
||
|
* data.
|
||
|
*/
|
||
|
|
||
|
{
|
||
|
wiz_list_t *wl;
|
||
|
static int next_time;
|
||
|
|
||
|
/* Only once per hour */
|
||
|
if (next_time > current_time)
|
||
|
return;
|
||
|
|
||
|
next_time = current_time + 60 * 60;
|
||
|
for (wl = all_wiz; wl; wl = wl->next)
|
||
|
{
|
||
|
wl->score = wl->score * 99 / 100;
|
||
|
wl->cost = wl->cost * .9;
|
||
|
wl->gigacost = wl->gigacost * .9;
|
||
|
wl->heart_beats = wl->heart_beats * 9 / 10;
|
||
|
}
|
||
|
|
||
|
check_wizlist_for_destr();
|
||
|
} /* wiz_decay() */
|
||
|
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
static string_t *
|
||
|
get_wiz_name (const char *file)
|
||
|
|
||
|
/* For the filename <file> return the name of the wizard responsible
|
||
|
* for it. This actual query is done with a master apply.
|
||
|
*
|
||
|
* Result is NULL or an uncounted string reference.
|
||
|
*/
|
||
|
|
||
|
{
|
||
|
svalue_t *ret;
|
||
|
|
||
|
/* Don't call the master if it isn't loaded! */
|
||
|
if (!master_ob)
|
||
|
return NULL;
|
||
|
|
||
|
push_c_string(inter_sp, file);
|
||
|
ret = apply_master(STR_GET_WNAME, 1);
|
||
|
if (ret == 0 || ret->type != T_STRING)
|
||
|
return NULL;
|
||
|
return ret->u.str;
|
||
|
} /* get_wiz_name() */
|
||
|
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
void
|
||
|
load_wiz_file (void)
|
||
|
|
||
|
/* Load the old wizlist from the wizlist file and add it's data to
|
||
|
* the wizlist already in memory.
|
||
|
*
|
||
|
* This function is called at driver start up.
|
||
|
* TODO: Since the wizlist is saved from the mudlib, this function
|
||
|
* TODO:: should be implemented on mudlib level, too.
|
||
|
*/
|
||
|
|
||
|
{
|
||
|
char buff[1000];
|
||
|
FILE *f;
|
||
|
|
||
|
if (wizlist_name[0] == '\0')
|
||
|
return;
|
||
|
|
||
|
f = fopen(wizlist_name, "r");
|
||
|
if (f == NULL)
|
||
|
return;
|
||
|
|
||
|
while (fgets(buff, sizeof buff, f) != NULL)
|
||
|
{
|
||
|
char *p;
|
||
|
uint32 score;
|
||
|
|
||
|
p = strchr(buff, ' ');
|
||
|
if (p == 0)
|
||
|
{
|
||
|
fprintf(stderr, "%s Bad WIZLIST file '%s'.\n"
|
||
|
, time_stamp(), wizlist_name);
|
||
|
break;
|
||
|
}
|
||
|
*p = '\0';
|
||
|
p++;
|
||
|
if (*p == '\0')
|
||
|
{
|
||
|
fprintf(stderr, "%s Bad WIZLIST file '%s'.\n"
|
||
|
, time_stamp(), wizlist_name);
|
||
|
break;
|
||
|
}
|
||
|
score = atoi(p);
|
||
|
if (score > 0)
|
||
|
{
|
||
|
string_t * tmp;
|
||
|
|
||
|
tmp = new_mstring(buff);
|
||
|
add_name(tmp)->score += score;
|
||
|
free_mstring(tmp);
|
||
|
}
|
||
|
}
|
||
|
fclose(f);
|
||
|
} /* load_wiz_file() */
|
||
|
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
void
|
||
|
remove_wiz_list (void)
|
||
|
|
||
|
/* Remove all memory allocated by the wizlist.
|
||
|
*
|
||
|
* Called from simulate::shutdowngame().
|
||
|
*/
|
||
|
|
||
|
{
|
||
|
wiz_list_t *wl, *w;
|
||
|
|
||
|
for (w = all_wiz; w; w = wl)
|
||
|
{
|
||
|
free_mstring(w->name);
|
||
|
if (w->file_name)
|
||
|
free_mstring(w->file_name);
|
||
|
if (w->error_message)
|
||
|
free_mstring(w->error_message);
|
||
|
wl = w->next;
|
||
|
xfree(w);
|
||
|
}
|
||
|
} /* remove_wiz_list() */
|
||
|
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
void
|
||
|
save_error (const char *msg, const char *file, int line)
|
||
|
|
||
|
/* A runtime error <msg> occured for object <file> in line number <line>.
|
||
|
* Store this information in the wizlist so that the mudlib can handle
|
||
|
* it later with the efun get_error_file().
|
||
|
* TODO: A proper runtime error handling could put this into the mudlib
|
||
|
* TODO:: completely.
|
||
|
*/
|
||
|
|
||
|
{
|
||
|
wiz_list_t *wl;
|
||
|
char *copy, *p;
|
||
|
string_t *name;
|
||
|
size_t len;
|
||
|
|
||
|
/* Get the wizard name and the wizlist entry. */
|
||
|
name = get_wiz_name(file);
|
||
|
if (!name)
|
||
|
return;
|
||
|
wl = add_name(name);
|
||
|
|
||
|
/* Set the file_name */
|
||
|
if (wl->file_name)
|
||
|
free_mstring(wl->file_name);
|
||
|
|
||
|
len = strlen(file);
|
||
|
copy = alloca(len + 4); /* May add .c plus the null byte, and / */
|
||
|
*copy = '/';
|
||
|
strcpy(copy+1, file);
|
||
|
|
||
|
/* If it is a cloned object, we have to find out what the file
|
||
|
* name is, and add '.c'.
|
||
|
*/
|
||
|
if ( NULL != (p = strrchr(copy, '#'))
|
||
|
|| ((p = copy+len), *p++ != 'c') || p[-2] != '.' )
|
||
|
{
|
||
|
p[0] = '.';
|
||
|
p[1] = 'c';
|
||
|
p[2] = '\0';
|
||
|
}
|
||
|
wl->file_name = new_mstring(copy);
|
||
|
|
||
|
/* Set the error_message */
|
||
|
if (wl->error_message)
|
||
|
free_mstring(wl->error_message);
|
||
|
wl->error_message = new_mstring(msg);
|
||
|
|
||
|
/* Set the line_number */
|
||
|
wl->line_number = line;
|
||
|
} /* save_error() */
|
||
|
|
||
|
/*=========================================================================*/
|
||
|
|
||
|
/* EFUNS */
|
||
|
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
svalue_t *
|
||
|
f_wizlist_info (svalue_t *sp)
|
||
|
|
||
|
/* EFUN wizlist_info()
|
||
|
*
|
||
|
* mixed *wizlist_info()
|
||
|
*
|
||
|
* Returns an array with the interesting entries of the wizlist.
|
||
|
* Raises a privilege_violation (wizlist_info, this_object(), 0).
|
||
|
*
|
||
|
* The result is an array with one entry for every wizard (uid).
|
||
|
* Every entry is an array itself:
|
||
|
*
|
||
|
* string w[WL_NAME] = Name of the wizard.
|
||
|
* int w[WL_COMMANDS] = Weighted number of commands execute by objects
|
||
|
* of this wizard.
|
||
|
* int w[WL_COST] and w[WL_GIGACOST] = Weighted sum of eval_costs.
|
||
|
* int w[WL_TOTAL_COST] and w[WL_TOTAL_GIGACOST] = Total sum of
|
||
|
* eval_costs.
|
||
|
* int w[WL_HEART_BEATS] = Weighted count of heart_beats.
|
||
|
* int w[WL_CALL_OUT] = Reserved for call_out() (unused yet).
|
||
|
* int w[WL_ARRAY_TOTAL] = Total size of arrays in elements.
|
||
|
* int w[WL_MAPPING_TOTAL] = Total size of mappings in elements.
|
||
|
#ifdef USE_STRUCTS
|
||
|
* int w[WL_STRUCT_TOTAL] = Total size of mappings in elements.
|
||
|
#endif
|
||
|
* mixed w[WL_EXTRA] = Extra wizlist-info if set.
|
||
|
*/
|
||
|
|
||
|
{
|
||
|
vector_t *all, *entry;
|
||
|
svalue_t *wsvp, *svp;
|
||
|
wiz_list_t *w;
|
||
|
|
||
|
if (!privilege_violation(STR_WIZLIST_INFO, &const0, sp))
|
||
|
{
|
||
|
all = allocate_array(0);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
all = allocate_array(number_of_wiz);
|
||
|
wsvp = all->item;
|
||
|
for (w = all_wiz; w; w = w->next)
|
||
|
{
|
||
|
entry = allocate_array(WL_SIZE);
|
||
|
put_array(wsvp, entry);
|
||
|
wsvp++;
|
||
|
svp = entry->item;
|
||
|
put_ref_string(&(svp[WL_NAME]), w->name);
|
||
|
put_number(&(svp[WL_COMMANDS]), w->score);
|
||
|
put_number(&(svp[WL_COST]), w->cost);
|
||
|
put_number(&(svp[WL_GIGACOST]), w->gigacost);
|
||
|
put_number(&(svp[WL_TOTAL_COST]), w->total_cost);
|
||
|
put_number(&(svp[WL_TOTAL_GIGACOST]), w->total_gigacost);
|
||
|
put_number(&(svp[WL_HEART_BEATS]), w->heart_beats);
|
||
|
put_number(&(svp[WL_CALL_OUT]), 0); /* TODO: Implement me */
|
||
|
put_number(&(svp[WL_ARRAY_TOTAL]), w->size_array);
|
||
|
put_number(&(svp[WL_MAPPING_TOTAL]), w->mapping_total);
|
||
|
#ifdef USE_STRUCTS
|
||
|
put_number(&(svp[WL_STRUCT_TOTAL]), w->struct_total);
|
||
|
#else
|
||
|
put_number(&(svp[WL_STRUCT_TOTAL]), 0);
|
||
|
#endif /* USE_STRUCTS */
|
||
|
if (w->extra.type == T_POINTER)
|
||
|
{
|
||
|
vector_t *v = w->extra.u.vec;
|
||
|
put_array(&(svp[WL_EXTRA]), slice_array(v, 0, VEC_SIZE(v) - 1));
|
||
|
}
|
||
|
else
|
||
|
assign_svalue_no_free(&(svp[WL_EXTRA]), &w->extra);
|
||
|
} /* end for */
|
||
|
} /* end if */
|
||
|
|
||
|
push_array(sp, all);
|
||
|
return sp;
|
||
|
} /* f_wizlist_info() */
|
||
|
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
svalue_t *
|
||
|
f_set_extra_wizinfo (svalue_t *sp)
|
||
|
|
||
|
/* EFUN set_extra_wizinfo()
|
||
|
*
|
||
|
* void set_extra_wizinfo (object wiz, mixed extra)
|
||
|
* void set_extra_wizinfo (string wiz, mixed extra)
|
||
|
* void set_extra_wizinfo (int wiz, mixed extra)
|
||
|
*
|
||
|
* Set the value <extra> as the 'extra' information for the wizlist
|
||
|
* entry of <wiz>.
|
||
|
*
|
||
|
* If <wiz> is an object, the entry of its creator (uid) is used.
|
||
|
* If <wiz> is a string (a creator aka uid), it names the entry
|
||
|
* to use.
|
||
|
* If <wiz> is the number 0, the data is set in the default wizlist
|
||
|
* entry. It can be used to store data for the lifetime of this
|
||
|
* driver run, like the time of the last reboot.
|
||
|
*
|
||
|
* <extra> can be any value.
|
||
|
*
|
||
|
* The function causes a privilege violation
|
||
|
* ("set_extra_wizinfo", this_object(), <wiz>).
|
||
|
*/
|
||
|
|
||
|
{
|
||
|
wiz_list_t *user;
|
||
|
short type;
|
||
|
|
||
|
if ((type = sp[-1].type) == T_OBJECT)
|
||
|
{
|
||
|
user = sp[-1].u.ob->user;
|
||
|
}
|
||
|
else if (type != T_STRING || !(user = find_wiz(sp[-1].u.str)))
|
||
|
{
|
||
|
if (type == T_NUMBER && sp[-1].u.number == 0)
|
||
|
user = NULL;
|
||
|
else
|
||
|
efun_gen_arg_error(1, sp->type, sp);
|
||
|
}
|
||
|
|
||
|
if (!privilege_violation(STR_SET_EXTRA_WIZINFO, sp-1, sp))
|
||
|
free_svalue(sp);
|
||
|
else
|
||
|
transfer_svalue(user ? &user->extra : &default_wizlist_entry.extra, sp);
|
||
|
|
||
|
free_svalue(sp-1);
|
||
|
|
||
|
return sp - 2;
|
||
|
} /* f_set_extra_wizinfo() */
|
||
|
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
svalue_t *
|
||
|
f_get_extra_wizinfo (svalue_t *sp)
|
||
|
|
||
|
/* EFUN get_extra_wizinfo()
|
||
|
*
|
||
|
* mixed get_extra_wizinfo (object wiz)
|
||
|
* mixed get_extra_wizinfo (string wiz)
|
||
|
* mixed get_extra_wizinfo (int wiz)
|
||
|
*
|
||
|
* Returns the 'extra' information that was set for the given
|
||
|
* wizard <wiz> in the wizlist.
|
||
|
*
|
||
|
* If <wiz> is an object, the entry of its creator (uid) is used.
|
||
|
* If <wiz> is a string (a creator aka uid), it names the entry
|
||
|
* to use.
|
||
|
* If <wiz> is the number 0, the data is get from the default wizlist
|
||
|
* entry.
|
||
|
*
|
||
|
* The function causes a privilege violation
|
||
|
* ("get_extra_wizinfo", this_object(), <wiz>).
|
||
|
*/
|
||
|
|
||
|
{
|
||
|
wiz_list_t *user;
|
||
|
short type;
|
||
|
|
||
|
if ((type = sp->type) == T_OBJECT)
|
||
|
{
|
||
|
user = sp->u.ob->user;
|
||
|
}
|
||
|
else if (type != T_STRING || !(user = find_wiz(sp->u.str)))
|
||
|
{
|
||
|
if (type == T_NUMBER && sp->u.number == 0)
|
||
|
user = NULL;
|
||
|
else
|
||
|
errorf("Bad arg 1 to get_extra_wizinfo(): no valid uid given.\n");
|
||
|
}
|
||
|
|
||
|
if (!privilege_violation(STR_GET_EXTRA_WIZINFO, sp, sp))
|
||
|
errorf("Error in get_extra_wizinfo(): privilege violation.\n");
|
||
|
|
||
|
assign_svalue(sp, user ? &user->extra : &default_wizlist_entry.extra);
|
||
|
|
||
|
return sp;
|
||
|
} /* get_extra_wizlist_info() */
|
||
|
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
svalue_t *
|
||
|
f_set_extra_wizinfo_size (svalue_t *sp)
|
||
|
|
||
|
/* EFUN set_extra_wizinfo_size()
|
||
|
*
|
||
|
* void set_extra_wizinfo_size(int size)
|
||
|
*
|
||
|
* Indicate that the wizlist should contain an array of this size
|
||
|
* with extra info foreach wizard. A negative size is used to
|
||
|
* indicate non-array 'extra' information.
|
||
|
*
|
||
|
* Causes the privilege violation
|
||
|
* ("set_extra_wizinfo_size", this_object(), size).
|
||
|
*
|
||
|
* The value is only used to allocate a proper empty 'extra' value
|
||
|
* for newly created wizlist entries.
|
||
|
*
|
||
|
* TODO: The extra_wizinfo idea could be applied to single objects
|
||
|
* TODO:: and - ta da! - we have driver supported properties.
|
||
|
* TODO:: Which then could be used to implement uids/euids etc.
|
||
|
*/
|
||
|
|
||
|
{
|
||
|
if (!privilege_violation(STR_SET_EXTRA_WIZINFO_SIZE, &const0, sp))
|
||
|
wiz_info_extra_size = sp->u.number;
|
||
|
|
||
|
sp--;
|
||
|
|
||
|
return sp;
|
||
|
} /* f_set_extra_wizinfo_size() */
|
||
|
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
svalue_t *
|
||
|
f_get_error_file (svalue_t *sp)
|
||
|
|
||
|
/* EFUN get_error_file()
|
||
|
*
|
||
|
* mixed * get_error_file(string name, int set_forget_flag)
|
||
|
*
|
||
|
* Return information about the last error which occured for
|
||
|
* <name> (where <name> is a valid name from the wiz list).
|
||
|
*
|
||
|
* Result is an array of four elements: the filename of the
|
||
|
* program where the error occured, the linenumber in the
|
||
|
* program, the error message (runtime error messages usually
|
||
|
* start with a '*'), and a numerical flag (the 'forget flag') if
|
||
|
* the error information has been queried already.
|
||
|
*
|
||
|
* If there is no error stored for the given <name>, 0 is
|
||
|
* returned.
|
||
|
*
|
||
|
* If <set_forget_flag> is non-zero, the 'forget' flag is set
|
||
|
* for the error message after it has been returned.
|
||
|
*/
|
||
|
|
||
|
{
|
||
|
string_t *name;
|
||
|
int forget;
|
||
|
wiz_list_t *wl;
|
||
|
vector_t *vec;
|
||
|
svalue_t *v;
|
||
|
# define FORGET_FLAG 0x4000000 /* 0x80...0 would be the sign! */
|
||
|
|
||
|
/* Get the function arguments */
|
||
|
name = sp[-1].u.str;
|
||
|
forget = sp->u.number;
|
||
|
wl = find_wiz(name);
|
||
|
sp--;
|
||
|
free_string_svalue(sp);
|
||
|
|
||
|
/* The error_message is used as a flag if there has been any error.
|
||
|
*/
|
||
|
if (!wl || !wl->error_message)
|
||
|
{
|
||
|
put_number(sp, 0);
|
||
|
return sp;
|
||
|
}
|
||
|
|
||
|
vec = allocate_array(4);
|
||
|
v = vec->item;
|
||
|
put_ref_string(v, wl->file_name);
|
||
|
put_number(v+1, wl->line_number & ~0x40000000);
|
||
|
put_ref_string(v+2, wl->error_message);
|
||
|
put_number(v+3, (wl->line_number & 0x40000000) != 0);
|
||
|
|
||
|
if (forget)
|
||
|
wl->line_number |= 0x40000000;
|
||
|
|
||
|
put_array(sp, vec);
|
||
|
return sp;
|
||
|
|
||
|
# undef FORGET_FLAG
|
||
|
} /* f_get_error_file() */
|
||
|
|
||
|
/*=========================================================================*/
|
||
|
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
void
|
||
|
check_wizlist_for_destr (void)
|
||
|
|
||
|
/* Check the 'extra' info in all wizinfo and remove destructed objects
|
||
|
* and closures.
|
||
|
*/
|
||
|
|
||
|
{
|
||
|
wiz_list_t *wl;
|
||
|
|
||
|
for (wl = &default_wizlist_entry; wl; )
|
||
|
{
|
||
|
size_t num;
|
||
|
svalue_t *item;
|
||
|
|
||
|
if (wl->extra.type == T_POINTER)
|
||
|
{
|
||
|
num = VEC_SIZE(wl->extra.u.vec);
|
||
|
item = &(wl->extra.u.vec->item[0]);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
num = 1;
|
||
|
item = &(wl->extra);
|
||
|
}
|
||
|
|
||
|
for ( ; num != 0 ; item++, num--)
|
||
|
{
|
||
|
switch(item->type)
|
||
|
{
|
||
|
case T_POINTER:
|
||
|
check_for_destr(item->u.vec);
|
||
|
break;
|
||
|
case T_MAPPING:
|
||
|
check_map_for_destr(item->u.map);
|
||
|
break;
|
||
|
case T_OBJECT:
|
||
|
case T_CLOSURE:
|
||
|
if (destructed_object_ref(item))
|
||
|
assign_svalue(item, &const0);
|
||
|
break;
|
||
|
default:
|
||
|
NOOP;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (wl == &default_wizlist_entry)
|
||
|
wl = all_wiz;
|
||
|
else
|
||
|
wl = wl->next;
|
||
|
}
|
||
|
} /* check_wizlist_for_destr() */
|
||
|
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
#ifdef GC_SUPPORT
|
||
|
|
||
|
void
|
||
|
clear_ref_from_wiz_list (void)
|
||
|
|
||
|
/* GC support: Clear the refs for the wiz_list memory.
|
||
|
*/
|
||
|
|
||
|
{
|
||
|
wiz_list_t *w;
|
||
|
|
||
|
for (w = all_wiz; w; w = w->next)
|
||
|
{
|
||
|
clear_ref_in_vector(&w->extra, 1);
|
||
|
if(w->file_name)
|
||
|
clear_string_ref(w->file_name);
|
||
|
if(w->error_message)
|
||
|
clear_string_ref(w->error_message);
|
||
|
}
|
||
|
clear_ref_in_vector(&default_wizlist_entry.extra, 1);
|
||
|
} /* clear_ref_from_wiz_list() */
|
||
|
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
void
|
||
|
count_ref_from_wiz_list (void)
|
||
|
|
||
|
/* GC support: Count the refs for the wiz_list memory.
|
||
|
*/
|
||
|
|
||
|
{
|
||
|
wiz_list_t *w;
|
||
|
|
||
|
for (w = all_wiz; w; w = w->next) {
|
||
|
count_ref_from_string(w->name);
|
||
|
count_ref_in_vector(&w->extra, 1);
|
||
|
if(w->file_name)
|
||
|
count_ref_from_string(w->file_name);
|
||
|
if (w->error_message)
|
||
|
count_ref_from_string(w->error_message);
|
||
|
note_malloced_block_ref((char *)w);
|
||
|
}
|
||
|
count_ref_in_vector(&default_wizlist_entry.extra, 1);
|
||
|
} /* count_ref_from_wiz_list() */
|
||
|
|
||
|
#endif /* GC_SUPPORT */
|
||
|
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
#ifdef USE_PARANOIA
|
||
|
|
||
|
void
|
||
|
count_extra_ref_from_wiz_list (void)
|
||
|
|
||
|
/* DEBUG support: Count the extra refs for the wiz_list memory.
|
||
|
*/
|
||
|
|
||
|
{
|
||
|
wiz_list_t *w;
|
||
|
|
||
|
for (w = all_wiz; w; w = w->next) {
|
||
|
count_extra_ref_in_vector(&w->extra, 1);
|
||
|
}
|
||
|
count_extra_ref_in_vector(&default_wizlist_entry.extra, 1);
|
||
|
} /* count_extra_ref_from_wiz_list() */
|
||
|
|
||
|
#endif
|
||
|
|
||
|
/***************************************************************************/
|
||
|
|