1 /*---------------------------------------------------------------------------
2 * Wizard List
3 *
4 *---------------------------------------------------------------------------
5 * The Wizard List ("wizlist") started out as a means to determine a high
6 * score list of the most popular castles. Over the time, this list
7 * was generalized into a simple user-id management with driver-internal
8 * purposes.
9 *
10 * A user-id ("wizard name", "creator") is a unique string, and every object
11 * is associated with a uid through the master-apply get_wiz_name(object-name).
12 * The reverse doesn't hold true: the mudlib can use uids which are not
13 * associated with any object.
14 *
15 * A special uid is the number 0: this is denotes the 'default' wizard,
16 * ie. the system itself. Together with the .extra information feature,
17 * the wizlist entry for uid 0 can be used to store information "on driver
18 * level".
19 *
20 * Every uid represented with a wizlist entry of the following structure.
21 * Object structures even contain a '.user' entry pointing directly
22 * to the associated wizlist entry.
23 *
24 * struct wiz_list_s {
25 * wiz_list_t *next;
26 * string_t *name;
27 * int32 score;
28 * int32 cost;
29 * int32 gigacost;
30 * int32 total_cost;
31 * int32 total_gigacost;
32 * int32 heart_beats;
33 * mp_int size_array;
34 * mp_int mapping_total;
35 #ifdef USE_STRUCTS
36 * mp_int struct_total;
37 #endif
38 * svalue_t extra;
39 * int32 last_call_out;
40 * int32 call_out_cost;
41 * string_t *file_name;
42 * string_t *error_message;
43 * int32 line_number;
44 * };
45 *
46 * .name is the tabled uid string of this wizlist entry.
47 * .next is the pointer to the next entry in the wizlist.
48 *
49 * .score, .(total_)cost+.(total_)gigacost, .heart_beats, .size_array and
50 * .mapping_total collect statistics about the objects for this uid/wizard.
51 * .score is the number of action functions executed (weighted over time),
52 * .cost+.gigacost the eval ticks spent (weighted over time),
53 * .total_cost+.total_gigacost the eval ticks spent (total), .heart_beats the
54 * number of heart_beat() calls (weighted over time). .size_array and
55 * .mapping_total give the number of values held in arrays and mappings for
56 * this wizard.
57 *
58 * .extra offer space for one svalue which can be used by the mudlib
59 * for its own purposes. The driver can be instructed to fill the .extra
60 * member every newly created entry with an empty array of a specific
61 * size. Especially the .extra member for uid 0 can be used to store
62 * data persistent to the whole driver run - it even survives reloads
63 * of the master object.
64 *
65 * .last_call_out and .call_out_cost are used to manage the call_out.
66 * .call_out_cost is the collected execution cost of all call_outs
67 * executed for time .last_call_out for this .user. When executing
68 * call_outs, this value is used to prime the eval_cost counter, and
69 * thus prevents call_outs from hogging all the cpu.
70 *
71 * .file_name, .error_message and .line_number are used to communicate
72 * errors from the driver to the mudlib. Bit 30 (0x40000000) in line_number
73 * is the "forget flag": it is set when the mudlib queries the error
74 * information. This way the mudlib can distinguish old from new
75 * errors.
76 *
77 *
78 * Part of the wizard list information is stored in the toplevel file
79 * "WIZLIST". The file is organized in lines, one for every wizard.
80 * Each line must at least contain:
81 *
82 * <name> <score>
83 *
84 * No leading space, and <name> and <score> must be separated by one or
85 * more spaces. If existing, this information is read by the driver at
86 * startup and added(!) to the already existing wizlist entries.
87 *
88 * The mudlib is free to add more information after the <score> and read
89 * it itself. For the same reason it is the task of the mudlib to write
90 * the WIZLIST file.
91 *---------------------------------------------------------------------------
92 */
93
94 #include "driver.h"
95 #include "typedefs.h"
96
97 #include "my-alloca.h"
98
99 #include <stdio.h>
100
101 #include "wiz_list.h"
102 #include "../mudlib/sys/wizlist.h"
103
104 #include "array.h"
105 #include "backend.h"
106 #include "gcollect.h"
107 #include "interpret.h"
108 #include "main.h"
109 #include "mapping.h"
110 #include "mstrings.h"
111 #include "object.h"
112 #include "simulate.h"
113 #include "stdstrings.h"
114 #include "svalue.h"
115 #include "xalloc.h"
116
117 /*-------------------------------------------------------------------------*/
118 wiz_list_t default_wizlist_entry
119 /* The default wizlist entry which is used for all "system" purposes.
120 */
121 = { NULL /* next */
122 , NULL /* name */
123 , 0 /* score */
124 , 0 /* cost */
125 , 0 /* gigacost */
126 , 0 /* total_cost */
127 , 0 /* total_gigacost */
128 , 0 /* heart_beats */
129 , 0 /* size_array */
130 , 0 /* mapping_total */
131 #ifdef USE_STRUCTS
132 , 0 /* struct_total */
133 #endif
134 , { T_NUMBER } /* extra */
135 , 0 /* last_call_out */
136 , 0 /* call_out_cost */
137 , NULL /* error file_name */
138 , NULL /* error_message */
139 , 0 /* error line_number */
140 };
141
142 wiz_list_t *all_wiz = NULL;
143 /* The list of all wizard entries, sorted by the numeric value
144 * of <name>. If the names are queried equally often, this even yields
145 * an average O(1) complexity.
146 */
147
148 static int wiz_info_extra_size = -1;
149 /* Default size of the .extra field, -1 if unspecified.
150 */
151
152 static int number_of_wiz = 0;
153 /* Number of entries in the list.
154 */
155
156 char wizlist_name[MAXPATHLEN+1] = "";
157 /* Name of the wizlist file, relative to the mudlib directory.
158 */
159
160 /*-------------------------------------------------------------------------*/
161 void
name_wizlist_file(const char * name)162 name_wizlist_file (const char *name)
163
164 /* Set the swap file name to a copy of <name>.
165 */
166
167 {
168 /* Skip leading '/' */
169 while (*name == '/') name++;
170
171 xstrncpy(wizlist_name, name, sizeof wizlist_name);
172 wizlist_name[sizeof wizlist_name - 1] = '\0';
173 } /* name_wizlist_file()*/
174
175 /*-------------------------------------------------------------------------*/
176 size_t
wiz_list_size(void)177 wiz_list_size (void)
178
179 /* Return the allocated size of the wiz_list.
180 */
181
182 {
183 /* The extra wizinfo has been counted with the arrays */
184 return sizeof(wiz_list_t) * number_of_wiz;
185 } /* wiz_list_size() */
186
187 /*-------------------------------------------------------------------------*/
188 static wiz_list_t *
find_wiz(string_t * name)189 find_wiz (string_t *name)
190
191 /* Find the entry for the user 'name' and return it's pointer.
192 * Return NULL if it can't be found.
193 */
194
195 {
196 wiz_list_t *wl;
197
198 if ( !( name = find_tabled(name) ) )
199 return NULL;
200
201 for (wl = all_wiz; wl; wl = wl->next)
202 {
203 int rc = mstrcmp(wl->name, name);
204
205 if (!rc)
206 return wl;
207 if (rc > 0)
208 break;
209 }
210 return NULL;
211 } /* find_wiz() */
212
213 /*-------------------------------------------------------------------------*/
214 wiz_list_t *
add_name(string_t * str)215 add_name (string_t * str)
216
217 /* Check if an entry for wizard <str> exists; add it, if it doesn't.
218 * Return the pointer to the wiz_list entry.
219 * Must not change refcount of <str>.
220 */
221
222 {
223 wiz_list_t *wl;
224 wiz_list_t *prev, *this;
225
226 wl = find_wiz(str);
227 if (wl)
228 return wl;
229
230 number_of_wiz++;
231 wl = xalloc(sizeof (wiz_list_t));
232
233 str = make_tabled_from(str);
234
235 wl->next = NULL;
236 wl->name = str;
237 wl->score = 0;
238 wl->cost = 0;
239 wl->gigacost = 0;
240 wl->total_cost = 0;
241 wl->total_gigacost = 0;
242 wl->heart_beats = 0;
243 wl->size_array = 0;
244 wl->mapping_total = 0;
245 #ifdef USE_STRUCTS
246 wl->struct_total = 0;
247 #endif /* USE_STRUCTS */
248 #if 0
249 wl->quota_allowance = 0;
250 wl->quota_usage = 0;
251 #endif
252 wl->file_name = NULL;
253 wl->error_message = NULL;
254 if (wiz_info_extra_size >= 0)
255 put_array(&(wl->extra), allocate_array(wiz_info_extra_size));
256 else
257 wl->extra = const0;
258 wl->last_call_out = 0;
259
260 /* Find the insertion point and insert the new entry */
261 for ( prev = NULL, this = all_wiz
262 ; this && mstrcmp(this->name, str) < 0
263 ; prev = this, this = this->next
264 )
265 { NOOP; }
266
267 if (!prev)
268 {
269 wl->next = all_wiz;
270 all_wiz = wl;
271 }
272 else
273 {
274 wl->next = this;
275 prev->next = wl;
276 }
277
278 return wl;
279 } /* add_name() */
280
281 /*-------------------------------------------------------------------------*/
282 void
wiz_decay(void)283 wiz_decay (void)
284
285 /* Called after every complete walkaround of the reset, this 'decays'
286 * the score of every wizard once per hour.
287 * Together with the decay, the wizlist is checked for destructed extra
288 * data.
289 */
290
291 {
292 wiz_list_t *wl;
293 static int next_time;
294
295 /* Only once per hour */
296 if (next_time > current_time)
297 return;
298
299 next_time = current_time + 60 * 60;
300 for (wl = all_wiz; wl; wl = wl->next)
301 {
302 wl->score = wl->score * 99 / 100;
303 wl->cost = wl->cost * .9;
304 wl->gigacost = wl->gigacost * .9;
305 wl->heart_beats = wl->heart_beats * 9 / 10;
306 }
307
308 check_wizlist_for_destr();
309 } /* wiz_decay() */
310
311 /*-------------------------------------------------------------------------*/
312 static string_t *
get_wiz_name(const char * file)313 get_wiz_name (const char *file)
314
315 /* For the filename <file> return the name of the wizard responsible
316 * for it. This actual query is done with a master apply.
317 *
318 * Result is NULL or an uncounted string reference.
319 */
320
321 {
322 svalue_t *ret;
323
324 /* Don't call the master if it isn't loaded! */
325 if (!master_ob)
326 return NULL;
327
328 push_c_string(inter_sp, file);
329 ret = apply_master(STR_GET_WNAME, 1);
330 if (ret == 0 || ret->type != T_STRING)
331 return NULL;
332 return ret->u.str;
333 } /* get_wiz_name() */
334
335 /*-------------------------------------------------------------------------*/
336 void
load_wiz_file(void)337 load_wiz_file (void)
338
339 /* Load the old wizlist from the wizlist file and add it's data to
340 * the wizlist already in memory.
341 *
342 * This function is called at driver start up.
343 * TODO: Since the wizlist is saved from the mudlib, this function
344 * TODO:: should be implemented on mudlib level, too.
345 */
346
347 {
348 char buff[1000];
349 FILE *f;
350
351 if (wizlist_name[0] == '\0')
352 return;
353
354 f = fopen(wizlist_name, "r");
355 if (f == NULL)
356 return;
357
358 while (fgets(buff, sizeof buff, f) != NULL)
359 {
360 char *p;
361 uint32 score;
362
363 p = strchr(buff, ' ');
364 if (p == 0)
365 {
366 fprintf(stderr, "%s Bad WIZLIST file '%s'.\n"
367 , time_stamp(), wizlist_name);
368 break;
369 }
370 *p = '\0';
371 p++;
372 if (*p == '\0')
373 {
374 fprintf(stderr, "%s Bad WIZLIST file '%s'.\n"
375 , time_stamp(), wizlist_name);
376 break;
377 }
378 score = atoi(p);
379 if (score > 0)
380 {
381 string_t * tmp;
382
383 tmp = new_mstring(buff);
384 add_name(tmp)->score += score;
385 free_mstring(tmp);
386 }
387 }
388 fclose(f);
389 } /* load_wiz_file() */
390
391 /*-------------------------------------------------------------------------*/
392 void
remove_wiz_list(void)393 remove_wiz_list (void)
394
395 /* Remove all memory allocated by the wizlist.
396 *
397 * Called from simulate::shutdowngame().
398 */
399
400 {
401 wiz_list_t *wl, *w;
402
403 for (w = all_wiz; w; w = wl)
404 {
405 free_mstring(w->name);
406 if (w->file_name)
407 free_mstring(w->file_name);
408 if (w->error_message)
409 free_mstring(w->error_message);
410 wl = w->next;
411 xfree(w);
412 }
413 } /* remove_wiz_list() */
414
415 /*-------------------------------------------------------------------------*/
416 void
save_error(const char * msg,const char * file,int line)417 save_error (const char *msg, const char *file, int line)
418
419 /* A runtime error <msg> occured for object <file> in line number <line>.
420 * Store this information in the wizlist so that the mudlib can handle
421 * it later with the efun get_error_file().
422 * TODO: A proper runtime error handling could put this into the mudlib
423 * TODO:: completely.
424 */
425
426 {
427 wiz_list_t *wl;
428 char *copy, *p;
429 string_t *name;
430 size_t len;
431
432 /* Get the wizard name and the wizlist entry. */
433 name = get_wiz_name(file);
434 if (!name)
435 return;
436 wl = add_name(name);
437
438 /* Set the file_name */
439 if (wl->file_name)
440 free_mstring(wl->file_name);
441
442 len = strlen(file);
443 copy = alloca(len + 4); /* May add .c plus the null byte, and / */
444 *copy = '/';
445 strcpy(copy+1, file);
446
447 /* If it is a cloned object, we have to find out what the file
448 * name is, and add '.c'.
449 */
450 if ( NULL != (p = strrchr(copy, '#'))
451 || ((p = copy+len), *p++ != 'c') || p[-2] != '.' )
452 {
453 p[0] = '.';
454 p[1] = 'c';
455 p[2] = '\0';
456 }
457 wl->file_name = new_mstring(copy);
458
459 /* Set the error_message */
460 if (wl->error_message)
461 free_mstring(wl->error_message);
462 wl->error_message = new_mstring(msg);
463
464 /* Set the line_number */
465 wl->line_number = line;
466 } /* save_error() */
467
468 /*=========================================================================*/
469
470 /* EFUNS */
471
472 /*-------------------------------------------------------------------------*/
473 svalue_t *
f_wizlist_info(svalue_t * sp)474 f_wizlist_info (svalue_t *sp)
475
476 /* EFUN wizlist_info()
477 *
478 * mixed *wizlist_info()
479 *
480 * Returns an array with the interesting entries of the wizlist.
481 * Raises a privilege_violation (wizlist_info, this_object(), 0).
482 *
483 * The result is an array with one entry for every wizard (uid).
484 * Every entry is an array itself:
485 *
486 * string w[WL_NAME] = Name of the wizard.
487 * int w[WL_COMMANDS] = Weighted number of commands execute by objects
488 * of this wizard.
489 * int w[WL_COST] and w[WL_GIGACOST] = Weighted sum of eval_costs.
490 * int w[WL_TOTAL_COST] and w[WL_TOTAL_GIGACOST] = Total sum of
491 * eval_costs.
492 * int w[WL_HEART_BEATS] = Weighted count of heart_beats.
493 * int w[WL_CALL_OUT] = Reserved for call_out() (unused yet).
494 * int w[WL_ARRAY_TOTAL] = Total size of arrays in elements.
495 * int w[WL_MAPPING_TOTAL] = Total size of mappings in elements.
496 #ifdef USE_STRUCTS
497 * int w[WL_STRUCT_TOTAL] = Total size of mappings in elements.
498 #endif
499 * mixed w[WL_EXTRA] = Extra wizlist-info if set.
500 */
501
502 {
503 vector_t *all, *entry;
504 svalue_t *wsvp, *svp;
505 wiz_list_t *w;
506
507 if (!privilege_violation(STR_WIZLIST_INFO, &const0, sp))
508 {
509 all = allocate_array(0);
510 }
511 else
512 {
513 all = allocate_array(number_of_wiz);
514 wsvp = all->item;
515 for (w = all_wiz; w; w = w->next)
516 {
517 entry = allocate_array(WL_SIZE);
518 put_array(wsvp, entry);
519 wsvp++;
520 svp = entry->item;
521 put_ref_string(&(svp[WL_NAME]), w->name);
522 put_number(&(svp[WL_COMMANDS]), w->score);
523 put_number(&(svp[WL_COST]), w->cost);
524 put_number(&(svp[WL_GIGACOST]), w->gigacost);
525 put_number(&(svp[WL_TOTAL_COST]), w->total_cost);
526 put_number(&(svp[WL_TOTAL_GIGACOST]), w->total_gigacost);
527 put_number(&(svp[WL_HEART_BEATS]), w->heart_beats);
528 put_number(&(svp[WL_CALL_OUT]), 0); /* TODO: Implement me */
529 put_number(&(svp[WL_ARRAY_TOTAL]), w->size_array);
530 put_number(&(svp[WL_MAPPING_TOTAL]), w->mapping_total);
531 #ifdef USE_STRUCTS
532 put_number(&(svp[WL_STRUCT_TOTAL]), w->struct_total);
533 #else
534 put_number(&(svp[WL_STRUCT_TOTAL]), 0);
535 #endif /* USE_STRUCTS */
536 if (w->extra.type == T_POINTER)
537 {
538 vector_t *v = w->extra.u.vec;
539 put_array(&(svp[WL_EXTRA]), slice_array(v, 0, VEC_SIZE(v) - 1));
540 }
541 else
542 assign_svalue_no_free(&(svp[WL_EXTRA]), &w->extra);
543 } /* end for */
544 } /* end if */
545
546 push_array(sp, all);
547 return sp;
548 } /* f_wizlist_info() */
549
550 /*-------------------------------------------------------------------------*/
551 svalue_t *
f_set_extra_wizinfo(svalue_t * sp)552 f_set_extra_wizinfo (svalue_t *sp)
553
554 /* EFUN set_extra_wizinfo()
555 *
556 * void set_extra_wizinfo (object wiz, mixed extra)
557 * void set_extra_wizinfo (string wiz, mixed extra)
558 * void set_extra_wizinfo (int wiz, mixed extra)
559 *
560 * Set the value <extra> as the 'extra' information for the wizlist
561 * entry of <wiz>.
562 *
563 * If <wiz> is an object, the entry of its creator (uid) is used.
564 * If <wiz> is a string (a creator aka uid), it names the entry
565 * to use.
566 * If <wiz> is the number 0, the data is set in the default wizlist
567 * entry. It can be used to store data for the lifetime of this
568 * driver run, like the time of the last reboot.
569 *
570 * <extra> can be any value.
571 *
572 * The function causes a privilege violation
573 * ("set_extra_wizinfo", this_object(), <wiz>).
574 */
575
576 {
577 wiz_list_t *user;
578 short type;
579
580 if ((type = sp[-1].type) == T_OBJECT)
581 {
582 user = sp[-1].u.ob->user;
583 }
584 else if (type != T_STRING || !(user = find_wiz(sp[-1].u.str)))
585 {
586 if (type == T_NUMBER && sp[-1].u.number == 0)
587 user = NULL;
588 else
589 efun_gen_arg_error(1, sp->type, sp);
590 }
591
592 if (!privilege_violation(STR_SET_EXTRA_WIZINFO, sp-1, sp))
593 free_svalue(sp);
594 else
595 transfer_svalue(user ? &user->extra : &default_wizlist_entry.extra, sp);
596
597 free_svalue(sp-1);
598
599 return sp - 2;
600 } /* f_set_extra_wizinfo() */
601
602 /*-------------------------------------------------------------------------*/
603 svalue_t *
f_get_extra_wizinfo(svalue_t * sp)604 f_get_extra_wizinfo (svalue_t *sp)
605
606 /* EFUN get_extra_wizinfo()
607 *
608 * mixed get_extra_wizinfo (object wiz)
609 * mixed get_extra_wizinfo (string wiz)
610 * mixed get_extra_wizinfo (int wiz)
611 *
612 * Returns the 'extra' information that was set for the given
613 * wizard <wiz> in the wizlist.
614 *
615 * If <wiz> is an object, the entry of its creator (uid) is used.
616 * If <wiz> is a string (a creator aka uid), it names the entry
617 * to use.
618 * If <wiz> is the number 0, the data is get from the default wizlist
619 * entry.
620 *
621 * The function causes a privilege violation
622 * ("get_extra_wizinfo", this_object(), <wiz>).
623 */
624
625 {
626 wiz_list_t *user;
627 short type;
628
629 if ((type = sp->type) == T_OBJECT)
630 {
631 user = sp->u.ob->user;
632 }
633 else if (type != T_STRING || !(user = find_wiz(sp->u.str)))
634 {
635 if (type == T_NUMBER && sp->u.number == 0)
636 user = NULL;
637 else
638 errorf("Bad arg 1 to get_extra_wizinfo(): no valid uid given.\n");
639 }
640
641 if (!privilege_violation(STR_GET_EXTRA_WIZINFO, sp, sp))
642 errorf("Error in get_extra_wizinfo(): privilege violation.\n");
643
644 assign_svalue(sp, user ? &user->extra : &default_wizlist_entry.extra);
645
646 return sp;
647 } /* get_extra_wizlist_info() */
648
649 /*-------------------------------------------------------------------------*/
650 svalue_t *
f_set_extra_wizinfo_size(svalue_t * sp)651 f_set_extra_wizinfo_size (svalue_t *sp)
652
653 /* EFUN set_extra_wizinfo_size()
654 *
655 * void set_extra_wizinfo_size(int size)
656 *
657 * Indicate that the wizlist should contain an array of this size
658 * with extra info foreach wizard. A negative size is used to
659 * indicate non-array 'extra' information.
660 *
661 * Causes the privilege violation
662 * ("set_extra_wizinfo_size", this_object(), size).
663 *
664 * The value is only used to allocate a proper empty 'extra' value
665 * for newly created wizlist entries.
666 *
667 * TODO: The extra_wizinfo idea could be applied to single objects
668 * TODO:: and - ta da! - we have driver supported properties.
669 * TODO:: Which then could be used to implement uids/euids etc.
670 */
671
672 {
673 if (!privilege_violation(STR_SET_EXTRA_WIZINFO_SIZE, &const0, sp))
674 wiz_info_extra_size = sp->u.number;
675
676 sp--;
677
678 return sp;
679 } /* f_set_extra_wizinfo_size() */
680
681 /*-------------------------------------------------------------------------*/
682 svalue_t *
f_get_error_file(svalue_t * sp)683 f_get_error_file (svalue_t *sp)
684
685 /* EFUN get_error_file()
686 *
687 * mixed * get_error_file(string name, int set_forget_flag)
688 *
689 * Return information about the last error which occured for
690 * <name> (where <name> is a valid name from the wiz list).
691 *
692 * Result is an array of four elements: the filename of the
693 * program where the error occured, the linenumber in the
694 * program, the error message (runtime error messages usually
695 * start with a '*'), and a numerical flag (the 'forget flag') if
696 * the error information has been queried already.
697 *
698 * If there is no error stored for the given <name>, 0 is
699 * returned.
700 *
701 * If <set_forget_flag> is non-zero, the 'forget' flag is set
702 * for the error message after it has been returned.
703 */
704
705 {
706 string_t *name;
707 int forget;
708 wiz_list_t *wl;
709 vector_t *vec;
710 svalue_t *v;
711 # define FORGET_FLAG 0x4000000 /* 0x80...0 would be the sign! */
712
713 /* Get the function arguments */
714 name = sp[-1].u.str;
715 forget = sp->u.number;
716 wl = find_wiz(name);
717 sp--;
718 free_string_svalue(sp);
719
720 /* The error_message is used as a flag if there has been any error.
721 */
722 if (!wl || !wl->error_message)
723 {
724 put_number(sp, 0);
725 return sp;
726 }
727
728 vec = allocate_array(4);
729 v = vec->item;
730 put_ref_string(v, wl->file_name);
731 put_number(v+1, wl->line_number & ~0x40000000);
732 put_ref_string(v+2, wl->error_message);
733 put_number(v+3, (wl->line_number & 0x40000000) != 0);
734
735 if (forget)
736 wl->line_number |= 0x40000000;
737
738 put_array(sp, vec);
739 return sp;
740
741 # undef FORGET_FLAG
742 } /* f_get_error_file() */
743
744 /*=========================================================================*/
745
746 /*-------------------------------------------------------------------------*/
747 void
check_wizlist_for_destr(void)748 check_wizlist_for_destr (void)
749
750 /* Check the 'extra' info in all wizinfo and remove destructed objects
751 * and closures.
752 */
753
754 {
755 wiz_list_t *wl;
756
757 for (wl = &default_wizlist_entry; wl; )
758 {
759 size_t num;
760 svalue_t *item;
761
762 if (wl->extra.type == T_POINTER)
763 {
764 num = VEC_SIZE(wl->extra.u.vec);
765 item = &(wl->extra.u.vec->item[0]);
766 }
767 else
768 {
769 num = 1;
770 item = &(wl->extra);
771 }
772
773 for ( ; num != 0 ; item++, num--)
774 {
775 switch(item->type)
776 {
777 case T_POINTER:
778 check_for_destr(item->u.vec);
779 break;
780 case T_MAPPING:
781 check_map_for_destr(item->u.map);
782 break;
783 case T_OBJECT:
784 case T_CLOSURE:
785 if (destructed_object_ref(item))
786 assign_svalue(item, &const0);
787 break;
788 default:
789 NOOP;
790 break;
791 }
792 }
793
794 if (wl == &default_wizlist_entry)
795 wl = all_wiz;
796 else
797 wl = wl->next;
798 }
799 } /* check_wizlist_for_destr() */
800
801 /*-------------------------------------------------------------------------*/
802 #ifdef GC_SUPPORT
803
804 void
clear_ref_from_wiz_list(void)805 clear_ref_from_wiz_list (void)
806
807 /* GC support: Clear the refs for the wiz_list memory.
808 */
809
810 {
811 wiz_list_t *w;
812
813 for (w = all_wiz; w; w = w->next)
814 {
815 clear_ref_in_vector(&w->extra, 1);
816 if(w->file_name)
817 clear_string_ref(w->file_name);
818 if(w->error_message)
819 clear_string_ref(w->error_message);
820 }
821 clear_ref_in_vector(&default_wizlist_entry.extra, 1);
822 } /* clear_ref_from_wiz_list() */
823
824 /*-------------------------------------------------------------------------*/
825 void
count_ref_from_wiz_list(void)826 count_ref_from_wiz_list (void)
827
828 /* GC support: Count the refs for the wiz_list memory.
829 */
830
831 {
832 wiz_list_t *w;
833
834 for (w = all_wiz; w; w = w->next) {
835 count_ref_from_string(w->name);
836 count_ref_in_vector(&w->extra, 1);
837 if(w->file_name)
838 count_ref_from_string(w->file_name);
839 if (w->error_message)
840 count_ref_from_string(w->error_message);
841 note_malloced_block_ref((char *)w);
842 }
843 count_ref_in_vector(&default_wizlist_entry.extra, 1);
844 } /* count_ref_from_wiz_list() */
845
846 #endif /* GC_SUPPORT */
847
848 /*-------------------------------------------------------------------------*/
849 #ifdef DEBUG
850
851 void
count_extra_ref_from_wiz_list(void)852 count_extra_ref_from_wiz_list (void)
853
854 /* DEBUG support: Count the extra refs for the wiz_list memory.
855 */
856
857 {
858 wiz_list_t *w;
859
860 for (w = all_wiz; w; w = w->next) {
861 count_extra_ref_in_vector(&w->extra, 1);
862 }
863 count_extra_ref_in_vector(&default_wizlist_entry.extra, 1);
864 } /* count_extra_ref_from_wiz_list() */
865
866 #endif
867
868 /***************************************************************************/
869
870