diff --git a/CHANGELOG b/CHANGELOG
index 823a78e..14f665d 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,9 @@
+2009-05-22 (lynX) (4.0.12)
+ + adopted changes in LDMUD 3.3.718:
+ - many many many fixes
+ + support for iksemel xml parser library
+ + state of the art random generator
+
2008-07-27 (lynX) (4.0.10)
+ added ERR_TLS_NOT_DETECTED code to sys/tls.h
+ added suitable message to tls_error()
diff --git a/mudlib/sys/debug_info.h b/mudlib/sys/debug_info.h
index 14dd944..8623963 100644
--- a/mudlib/sys/debug_info.h
+++ b/mudlib/sys/debug_info.h
@@ -25,6 +25,7 @@
#define DIT_ERROR 1 /* Return the last error call chain as an array */
#define DIT_UNCAUGHT_ERROR 2 /* Return the last uncaught error call chain */
#define DIT_STR_CURRENT 3 /* Return the current call chain as a string */
+#define DIT_CURRENT_DEPTH 4 /* Return the current control stack depth */
/* Indices into the array resulting from debug_info(DINFO_DATA, DID_STATUS)
*/
@@ -226,8 +227,13 @@
#define TRACE_PROGRAM 2
#define TRACE_OBJECT 3
#define TRACE_LOC 4
+#ifdef __EVAL_COST_TRACE__
+#define TRACE_EVALCOST 5
+#define TRACE_MAX 6
+#else
#define TRACE_MAX 5
+#endif
/* Values for entry TRACE_TYPE */
diff --git a/src/Makefile.in b/src/Makefile.in
index 52e70ba..bcc917c 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -73,6 +73,14 @@ OPTIMIZE= $(@val_optimize@_OPTIMIZE)
# recompile.
#DEBUG = -DDEBUG # -DDEBUG_TELNET
DEBUG=
+
+# Flags for compiling the SFMT random number generator.
+SFMT_FLAGS = -fno-strict-aliasing
+# for machines with sse2 support you may use:
+#SFMT_FLAGS = -msse2 -fno-strict-aliasing -DHAVE_SSE2=1
+# for machines with altivec support you may use:
+#SFMT_FLAGS = -faltivec -fno-strict-aliasing -DHAVE_ALTIVEC=1
+
#
MPATH=-DMUD_LIB='"$(MUD_LIB)"' -DBINDIR='"$(BINDIR)"' -DERQ_DIR='"$(ERQ_DIR)"'
#
@@ -93,7 +101,7 @@ SRC = access_check.c actions.c array.c backend.c bitstrings.c call_out.c \
interpret.c \
lex.c main.c mapping.c md5.c mempools.c mregex.c mstrings.c object.c \
otable.c\
- parser.c parse.c pkg-alists.c pkg-idna.c \
+ parser.c parse.c pkg-alists.c pgk-iksemel.c pkg-idna.c pkg-expat.c \
pkg-mccp.c pkg-mysql.c pkg-pcre.c \
pkg-pgsql.c pkg-sqlite.c pkg-tls.c \
ptmalloc.c port.c ptrtable.c \
@@ -105,13 +113,12 @@ OBJ = access_check.o actions.o array.o backend.o bitstrings.o call_out.o \
interpret.o \
lex.o main.o mapping.o md5.o mempools.o mregex.o mstrings.o object.o \
otable.o \
- parser.o parse.o pkg-alists.o pkg-idna.o \
+ parser.o parse.o pkg-alists.o pkg-iksemel.o pkg-idna.o pkg-expat.o \
pkg-mccp.o pkg-mysql.o pkg-pcre.o \
pkg-pgsql.o pkg-sqlite.o pkg-tls.o \
ptmalloc.o port.o ptrtable.o \
random.o regexp.o sha1.o simulate.o simul_efun.o stdstrings.o \
- strfuns.o structs.o sprintf.o swap.o wiz_list.o xalloc.o @ALLOCA@ \
- pkg-expat.o
+ strfuns.o structs.o sprintf.o swap.o wiz_list.o xalloc.o @ALLOCA@
all: make-patchlevel @PROGNAME@@EXEEXT@
@@ -123,7 +130,7 @@ it: @PROGNAME@@EXEEXT@
docs: @PROGNAME@@EXEEXT@
-help2man --name=@PROGNAME@ -N --help-option=--longhelp --include=../HELP --output=../@PROGNAME@.1 ./@PROGNAME@@EXEEXT@
-
+
install-all: install-driver install-headers install-utils
install: install-driver
@@ -213,6 +220,9 @@ lang.c lang.h: lang.y
pcre/chartables.c : dftables@EXEEXT@
./dftables@EXEEXT@ pcre/chartables.c
+random.o : random.c config.h driver.h
+ $(CC) $(CFLAGS) $(SFMT_FLAGS) -c random.c -o random.o
+
#--------------------------------------------------------
# The dependency generation uses the program 'mkdepend' and assumes GNUmake.
@@ -228,11 +238,11 @@ pcre/chartables.c : dftables@EXEEXT@
depend: $(SRC) $(GENSRC)
@$(SHELL) -ec "if type mkdepend > /dev/null 2>&1; then \
echo Updating dependencies.; \
- mkdepend $(SKELETON) -I. $(EXCEPT) -m -p .c:%n.o -fMakefile; \
- mkdepend $(SKELETON) -I. $(EXCEPT) $(SELECT) -m -p .c:%n.o -fMakefile; \
+ mkdepend $(SKELETON) -I. -Ipcre -Iptmalloc $(EXCEPT) -m -p .c:%n.o -fMakefile; \
+ mkdepend $(SKELETON) -I. -Ipcre -Iptmalloc $(EXCEPT) $(SELECT) -m -p .c:%n.o -fMakefile; \
echo Updating dependencies in Makefile.in.; \
- mkdepend $(SKELETON) -I. $(EXCEPT) -m -p .c:%n.o -fMakefile.in; \
- mkdepend $(SKELETON) -I. $(EXCEPT) $(SELECT) -m -p .c:%n.o -fMakefile.in; \
+ mkdepend $(SKELETON) -I. -Ipcre -Iptmalloc $(EXCEPT) -m -p .c:%n.o -fMakefile.in; \
+ mkdepend $(SKELETON) -I. -Ipcre -Iptmalloc $(EXCEPT) $(SELECT) -m -p .c:%n.o -fMakefile.in; \
else\
echo mkdepend utility not available.; \
fi"
@@ -242,8 +252,8 @@ depend: $(SRC) $(GENSRC)
depend-generic: $(SRC) $(GENSRC)
@$(SHELL) -ec "if type mkdepend > /dev/null 2>&1; then \
echo Updating dependencies in hosts/be/Makefile.; \
- mkdepend $(SKELETON) -I. $(EXCEPT) -m -p .c:$$\(OBJ\)/%n.o -fhosts/be/Makefile; \
- mkdepend $(SKELETON) -I. $(EXCEPT) $(SELECT) -m -p .c:$$\(OBJ\)/%n.o -fhosts/be/Makefile; \
+ mkdepend $(SKELETON) -I. -Ipcre -Iptmalloc $(EXCEPT) -m -p .c:$$\(OBJ\)/%n.o -fhosts/be/Makefile; \
+ mkdepend $(SKELETON) -I. -Ipcre -Iptmalloc $(EXCEPT) $(SELECT) -m -p .c:$$\(OBJ\)/%n.o -fhosts/be/Makefile; \
else\
echo mkdepend utility not available.; \
fi"
@@ -271,20 +281,20 @@ array.o : i-svalue_cmp.h xalloc.h wiz_list.h swap.h svalue.h simulate.h \
hosts/be/be.h machine.h
backend.o : ../mudlib/sys/debug_message.h ../mudlib/sys/driver_hook.h \
- xalloc.h wiz_list.h swap.h svalue.h stdstrings.h simulate.h random.h \
- otable.h object.h mstrings.h mregex.h mapping.h main.h lex.h \
- interpret.h heartbeat.h gcollect.h filestat.h exec.h ed.h comm.h \
- closure.h call_out.h array.h actions.h backend.h my-alloca.h typedefs.h \
- driver.h strfuns.h sent.h bytecode.h hash.h pkg-tls.h port.h config.h \
- hosts/unix.h hosts/be/be.h machine.h
+ i-eval_cost.h xalloc.h wiz_list.h swap.h svalue.h stdstrings.h \
+ simulate.h random.h otable.h object.h mstrings.h mregex.h mapping.h \
+ main.h lex.h interpret.h heartbeat.h gcollect.h filestat.h exec.h ed.h \
+ comm.h closure.h call_out.h array.h actions.h backend.h my-alloca.h \
+ typedefs.h driver.h strfuns.h sent.h bytecode.h hash.h pkg-tls.h port.h \
+ config.h hosts/unix.h hosts/be/be.h machine.h
bitstrings.o : xalloc.h svalue.h simulate.h mstrings.h interpret.h \
bitstrings.h typedefs.h driver.h strfuns.h sent.h bytecode.h hash.h \
backend.h port.h config.h main.h hosts/unix.h hosts/be/be.h machine.h
-call_out.o : ../mudlib/sys/debug_info.h xalloc.h wiz_list.h swap.h svalue.h \
- strfuns.h stdstrings.h simulate.h object.h mstrings.h main.h \
- interpret.h gcollect.h exec.h comm.h closure.h backend.h array.h \
+call_out.o : ../mudlib/sys/debug_info.h i-eval_cost.h xalloc.h wiz_list.h \
+ swap.h svalue.h strfuns.h stdstrings.h simulate.h object.h mstrings.h \
+ main.h interpret.h gcollect.h exec.h comm.h closure.h backend.h array.h \
actions.h call_out.h typedefs.h driver.h sent.h bytecode.h hash.h \
pkg-tls.h port.h config.h hosts/unix.h hosts/be/be.h machine.h
@@ -295,13 +305,13 @@ closure.o : i-svalue_cmp.h xalloc.h switch.h swap.h svalue.h structs.h \
bytecode.h port.h config.h hosts/unix.h hosts/be/be.h machine.h
comm.o : util/erq/erq.h ../mudlib/sys/input_to.h \
- ../mudlib/sys/driver_hook.h ../mudlib/sys/comm.h xalloc.h wiz_list.h \
- swap.h svalue.h stdstrings.h simulate.h sent.h pkg-tls.h pkg-pgsql.h \
- pkg-mccp.h object.h mstrings.h main.h interpret.h gcollect.h filestat.h \
- exec.h ed.h closure.h array.h actions.h access_check.h comm.h \
- ../mudlib/sys/telnet.h my-alloca.h typedefs.h driver.h strfuns.h \
- bytecode.h hash.h backend.h config.h port.h hosts/unix.h hosts/be/be.h \
- machine.h
+ ../mudlib/sys/driver_hook.h ../mudlib/sys/comm.h i-eval_cost.h xalloc.h \
+ wiz_list.h swap.h svalue.h stdstrings.h simulate.h sent.h pkg-tls.h \
+ pkg-pgsql.h pkg-mccp.h object.h mstrings.h main.h interpret.h \
+ gcollect.h filestat.h exec.h ed.h closure.h array.h actions.h \
+ access_check.h comm.h ../mudlib/sys/telnet.h my-alloca.h typedefs.h \
+ driver.h strfuns.h bytecode.h hash.h backend.h config.h port.h \
+ hosts/unix.h hosts/be/be.h machine.h
dumpstat.o : xalloc.h svalue.h structs.h stdstrings.h simulate.h ptrtable.h \
object.h mstrings.h mapping.h instrs.h filestat.h exec.h closure.h \
@@ -316,14 +326,14 @@ ed.o : ../mudlib/sys/regexp.h xalloc.h svalue.h stdstrings.h simulate.h \
efuns.o : ../mudlib/sys/time.h ../mudlib/sys/strings.h \
../mudlib/sys/regexp.h ../mudlib/sys/objectinfo.h \
- ../mudlib/sys/driver_hook.h ../mudlib/sys/debug_info.h xalloc.h \
- wiz_list.h svalue.h swap.h structs.h strfuns.h simulate.h stdstrings.h \
- sha1.h random.h ptrtable.h otable.h object.h mstrings.h mregex.h md5.h \
- mempools.h mapping.h main.h lex.h interpret.h heartbeat.h exec.h \
- dumpstat.h comm.h closure.h call_out.h backend.h array.h actions.h \
- efuns.h my-rusage.h my-alloca.h typedefs.h driver.h hash.h sent.h \
- bytecode.h my-stdint.h pkg-tls.h port.h config.h hosts/unix.h \
- hosts/be/be.h machine.h
+ ../mudlib/sys/driver_hook.h ../mudlib/sys/debug_info.h i-eval_cost.h \
+ xalloc.h wiz_list.h svalue.h swap.h structs.h strfuns.h simulate.h \
+ stdstrings.h sha1.h random.h ptrtable.h otable.h object.h mstrings.h \
+ mregex.h md5.h mempools.h mapping.h main.h lex.h interpret.h \
+ heartbeat.h exec.h dumpstat.h comm.h closure.h call_out.h backend.h \
+ array.h actions.h efuns.h my-rusage.h my-alloca.h typedefs.h driver.h \
+ hash.h sent.h bytecode.h my-stdint.h pkg-tls.h port.h config.h \
+ hosts/unix.h hosts/be/be.h machine.h
files.o : ../mudlib/sys/files.h xalloc.h svalue.h stdstrings.h simulate.h \
mstrings.h mempools.h main.h lex.h interpret.h filestat.h comm.h \
@@ -331,8 +341,8 @@ files.o : ../mudlib/sys/files.h xalloc.h svalue.h stdstrings.h simulate.h \
bytecode.h hash.h backend.h pkg-tls.h port.h config.h hosts/unix.h \
hosts/be/be.h machine.h
-gcollect.o : ../mudlib/sys/driver_hook.h xalloc.h wiz_list.h swap.h \
- structs.h stdstrings.h simul_efun.h simulate.h sent.h random.h \
+gcollect.o : ../mudlib/sys/driver_hook.h i-eval_cost.h xalloc.h wiz_list.h \
+ swap.h structs.h stdstrings.h simul_efun.h simulate.h sent.h random.h \
ptrtable.h prolang.h pkg-pgsql.h parse.h otable.h object.h mstrings.h \
mregex.h mempools.h mapping.h main.h lex.h instrs.h interpret.h \
heartbeat.h filestat.h ed.h comm.h closure.h call_out.h backend.h \
@@ -342,35 +352,36 @@ gcollect.o : ../mudlib/sys/driver_hook.h xalloc.h wiz_list.h swap.h \
hash.o : hash.h
-heartbeat.o : ../mudlib/sys/debug_info.h xalloc.h wiz_list.h svalue.h \
- strfuns.h simulate.h sent.h object.h mstrings.h interpret.h gcollect.h \
- exec.h comm.h backend.h array.h actions.h heartbeat.h typedefs.h \
- driver.h bytecode.h hash.h pkg-tls.h main.h port.h config.h \
+heartbeat.o : ../mudlib/sys/debug_info.h i-eval_cost.h xalloc.h wiz_list.h \
+ svalue.h strfuns.h simulate.h sent.h object.h mstrings.h interpret.h \
+ gcollect.h exec.h comm.h backend.h array.h actions.h heartbeat.h \
+ typedefs.h driver.h bytecode.h hash.h pkg-tls.h main.h port.h config.h \
hosts/unix.h hosts/be/be.h machine.h
-interpret.o : ../mudlib/sys/trace.h ../mudlib/sys/debug_info.h \
- ../mudlib/sys/driver_hook.h xalloc.h wiz_list.h switch.h swap.h \
- svalue.h structs.h stdstrings.h simul_efun.h simulate.h prolang.h \
- parse.h otable.h object.h mstrings.h mapping.h lex.h instrs.h \
- heartbeat.h gcollect.h filestat.h exec.h efuns.h ed.h comm.h closure.h \
- call_out.h backend.h array.h actions.h interpret.h my-alloca.h \
- typedefs.h driver.h strfuns.h hash.h ptrtable.h sent.h bytecode.h \
- pkg-tls.h main.h port.h config.h hosts/unix.h hosts/be/be.h machine.h
+interpret.o : ../mudlib/sys/debug_info.h ../mudlib/sys/driver_hook.h \
+ i-eval_cost.h xalloc.h wiz_list.h switch.h swap.h svalue.h structs.h \
+ stdstrings.h simul_efun.h simulate.h prolang.h parse.h otable.h \
+ object.h mstrings.h mapping.h lex.h instrs.h heartbeat.h gcollect.h \
+ filestat.h exec.h efuns.h ed.h comm.h closure.h call_out.h backend.h \
+ array.h actions.h interpret.h my-alloca.h typedefs.h driver.h strfuns.h \
+ hash.h ptrtable.h sent.h bytecode.h pkg-tls.h main.h port.h config.h \
+ hosts/unix.h hosts/be/be.h machine.h
-lex.o : efun_defs.c ../mudlib/sys/driver_hook.h xalloc.h wiz_list.h \
- svalue.h strfuns.h stdstrings.h simul_efun.h simulate.h prolang.h \
- patchlevel.h object.h mstrings.h mempools.h main.h lang.h interpret.h \
- instrs.h hash.h gcollect.h filestat.h exec.h comm.h closure.h backend.h \
- array.h lex.h my-alloca.h typedefs.h driver.h ptrtable.h sent.h \
- bytecode.h pkg-tls.h port.h config.h hosts/unix.h hosts/be/be.h \
- machine.h
+lex.o : efun_defs.c ../mudlib/sys/driver_hook.h i-eval_cost.h xalloc.h \
+ wiz_list.h svalue.h strfuns.h stdstrings.h simul_efun.h simulate.h \
+ prolang.h patchlevel.h object.h mstrings.h mempools.h main.h lang.h \
+ interpret.h instrs.h hash.h gcollect.h filestat.h exec.h comm.h \
+ closure.h backend.h array.h lex.h my-alloca.h typedefs.h driver.h \
+ ptrtable.h sent.h bytecode.h pkg-tls.h port.h config.h hosts/unix.h \
+ hosts/be/be.h machine.h
-main.o : ../mudlib/sys/regexp.h pkg-mysql.h xalloc.h wiz_list.h swap.h \
- svalue.h stdstrings.h simul_efun.h simulate.h random.h pkg-tls.h \
- patchlevel.h otable.h object.h mstrings.h mregex.h mempools.h mapping.h \
- lex.h interpret.h gcollect.h filestat.h comm.h array.h backend.h main.h \
- my-alloca.h typedefs.h driver.h strfuns.h ptrtable.h exec.h sent.h \
- bytecode.h hash.h port.h config.h hosts/unix.h hosts/be/be.h machine.h
+main.o : ../mudlib/sys/regexp.h i-eval_cost.h pkg-mysql.h xalloc.h \
+ wiz_list.h swap.h svalue.h stdstrings.h simul_efun.h simulate.h \
+ random.h pkg-tls.h patchlevel.h otable.h object.h mstrings.h mregex.h \
+ mempools.h mapping.h lex.h interpret.h gcollect.h filestat.h comm.h \
+ array.h backend.h main.h my-alloca.h typedefs.h driver.h strfuns.h \
+ ptrtable.h exec.h sent.h bytecode.h hash.h port.h config.h hosts/unix.h \
+ hosts/be/be.h machine.h
mapping.o : i-svalue_cmp.h xalloc.h wiz_list.h svalue.h structs.h \
simulate.h object.h mstrings.h main.h interpret.h gcollect.h closure.h \
@@ -421,12 +432,12 @@ parse.o : xalloc.h wiz_list.h svalue.h stdstrings.h simulate.h object.h \
parse.h typedefs.h driver.h strfuns.h sent.h bytecode.h hash.h \
backend.h port.h config.h hosts/unix.h hosts/be/be.h machine.h
-parser.o : lang.c ../mudlib/sys/driver_hook.h xalloc.h wiz_list.h switch.h \
- swap.h svalue.h structs.h stdstrings.h simul_efun.h simulate.h object.h \
- mstrings.h mapping.h main.h lex.h instrs.h interpret.h gcollect.h \
- exec.h closure.h backend.h array.h prolang.h my-alloca.h typedefs.h \
- driver.h strfuns.h hash.h ptrtable.h sent.h bytecode.h port.h config.h \
- hosts/unix.h hosts/be/be.h machine.h
+parser.o : lang.c ../mudlib/sys/driver_hook.h i-eval_cost.h xalloc.h \
+ wiz_list.h switch.h swap.h svalue.h structs.h stdstrings.h simul_efun.h \
+ simulate.h object.h mstrings.h mapping.h main.h lex.h instrs.h \
+ interpret.h gcollect.h exec.h closure.h backend.h array.h prolang.h \
+ my-alloca.h typedefs.h driver.h strfuns.h hash.h ptrtable.h sent.h \
+ bytecode.h port.h config.h hosts/unix.h hosts/be/be.h machine.h
dftables.o : pcre/maketables.c pcre/internal.h pcre/pcre.h pcre/config.h
@@ -487,9 +498,10 @@ ptrtable.o : simulate.h mempools.h ptrtable.h driver.h svalue.h strfuns.h \
random.o : random.h driver.h port.h config.h hosts/unix.h hosts/be/be.h \
machine.h
-regexp.o : main.h xalloc.h simulate.h interpret.h regexp.h driver.h \
- typedefs.h svalue.h strfuns.h sent.h bytecode.h backend.h pkg-pcre.h \
- port.h config.h pcre/pcre.h hosts/unix.h hosts/be/be.h machine.h
+regexp.o : i-eval_cost.h main.h xalloc.h simulate.h regexp.h driver.h \
+ interpret.h typedefs.h svalue.h strfuns.h sent.h bytecode.h pkg-pcre.h \
+ port.h config.h backend.h pcre/pcre.h hosts/unix.h hosts/be/be.h \
+ machine.h
sha1.o : sha1.h my-stdint.h driver.h port.h config.h hosts/unix.h \
hosts/be/be.h machine.h
@@ -502,12 +514,12 @@ simul_efun.o : xalloc.h swap.h svalue.h stdstrings.h simulate.h prolang.h \
simulate.o : ../mudlib/sys/rtlimits.h ../mudlib/sys/regexp.h \
../mudlib/sys/files.h ../mudlib/sys/driver_hook.h \
- ../mudlib/sys/debug_info.h xalloc.h wiz_list.h svalue.h swap.h \
- structs.h strfuns.h stdstrings.h simul_efun.h sent.h prolang.h \
+ ../mudlib/sys/debug_info.h i-eval_cost.h xalloc.h wiz_list.h svalue.h \
+ swap.h structs.h strfuns.h stdstrings.h simul_efun.h sent.h prolang.h \
pkg-sqlite.h pkg-tls.h otable.h object.h mstrings.h mregex.h mempools.h \
- mapping.h main.h lex.h interpret.h heartbeat.h gcollect.h filestat.h \
- ed.h comm.h closure.h call_out.h backend.h array.h actions.h simulate.h \
- my-alloca.h typedefs.h driver.h hash.h exec.h ptrtable.h bytecode.h \
+ mapping.h main.h lex.h heartbeat.h gcollect.h filestat.h ed.h comm.h \
+ closure.h call_out.h backend.h array.h actions.h simulate.h my-alloca.h \
+ typedefs.h driver.h interpret.h hash.h exec.h ptrtable.h bytecode.h \
port.h config.h hosts/unix.h hosts/be/be.h machine.h
sprintf.o : xalloc.h swap.h svalue.h structs.h stdstrings.h simul_efun.h \
diff --git a/src/actions.c b/src/actions.c
index 2b1a2ee..5494aef 100644
--- a/src/actions.c
+++ b/src/actions.c
@@ -496,12 +496,20 @@ remove_shadow_actions (object_t *shadow, object_t *target)
*/
{
-#ifdef USE_INVENTORIES
+# ifdef USE_INVENTORIES
object_t *item;
-#endif
+# endif
+ object_t *shadowing;
+
+ /* Get the real underlying object, just as add_action does. */
+ while ((target->flags & O_SHADOW)
+ && NULL != (shadowing = O_GET_SHADOW(target)->shadowing))
+ {
+ target = shadowing;
+ }
remove_shadow_action_sent(shadow, target);
-#ifdef USE_INVENTORIES
+# ifdef USE_INVENTORIES
for (item = target->contains; item; item = item->next_inv)
{
if (shadow != item)
@@ -517,7 +525,7 @@ remove_shadow_actions (object_t *shadow, object_t *target)
remove_shadow_action_sent(shadow, item);
}
}
-#endif
+# endif
} /* remove_shadow_actions() */
#endif
@@ -1248,7 +1256,7 @@ execute_command (char *str, object_t *ob)
/* Save the current context */
save_command_context(&context);
context.rt.last = rt_context;
- rt_context = (rt_context_t *)&context;
+ rt_context = (rt_context_t *)&context.rt;
/* Default settings */
command_giver = ob;
@@ -1423,8 +1431,8 @@ e_add_action (svalue_t *func, svalue_t *cmd, p_int flag)
if ((size_t)(-flag) >= mstrsize(p->verb))
{
free_action_sent(p);
- errorf("Bad arg 3 to add_action(): value %ld larger than verb '%s'.\n"
- , (long)flag, get_txt(p->verb));
+ errorf("Bad arg 3 to add_action(): value %"PRIdPINT" larger than verb '%s'.\n"
+ , flag, get_txt(p->verb));
/* NOTREACHED */
return MY_TRUE;
}
@@ -1437,8 +1445,8 @@ e_add_action (svalue_t *func, svalue_t *cmd, p_int flag)
else
{
free_action_sent(p);
- errorf("Bad arg 3 to add_action(): value %ld too big.\n"
- , (long)flag);
+ errorf("Bad arg 3 to add_action(): value %"PRIdPINT" too big.\n"
+ , flag);
/* NOTREACHED */
return MY_TRUE;
}
@@ -1613,7 +1621,8 @@ f_execute_command (svalue_t *sp)
len = mstrsize(argp->u.str);
if (len >= sizeof(buf) - 1)
- errorf("Command too long: '%.200s...'\n", get_txt(argp->u.str));
+ errorf("Command too long (size: %zu): '%.200s...'\n",
+ len, get_txt(argp->u.str));
strncpy(buf, get_txt(argp->u.str), len);
buf[len+1] = '\0';
@@ -1940,7 +1949,7 @@ f_remove_action (svalue_t *sp)
*/
{
- object_t *ob;
+ object_t *ob, *shadow_ob;
string_t *verb;
sentence_t **sentp;
action_t *s;
@@ -1969,14 +1978,33 @@ f_remove_action (svalue_t *sp)
efun_gen_arg_error(1, sp[-1].type, sp);
/* NOTREACHED */
}
-
- /* Now search and remove the sentence */
+
rc = 0;
sentp = &ob->sent;
+
ob = current_object;
+ shadow_ob = NULL;
+
+ /* Look for the underlying object, just as add_action does. */
+ if (ob->flags & O_SHADOW && O_GET_SHADOW(ob)->shadowing)
+ {
+ object_t *shadowing;
+
+ shadow_ob = ob;
+
+ while ((ob->flags & O_SHADOW)
+ && NULL != (shadowing = O_GET_SHADOW(ob)->shadowing))
+ {
+ ob = shadowing;
+ }
+ }
+
+ /* Now search and remove the sentence */
while ( NULL != (s = (action_t *)*sentp) )
{
- if (!SENT_IS_INTERNAL((*sentp)->type) && s->ob == ob && (!verb || s->verb == verb))
+ if (!SENT_IS_INTERNAL((*sentp)->type) && s->ob == ob
+ && (!verb || s->verb == verb)
+ && (!shadow_ob || s->shadow_ob == shadow_ob))
{
#ifdef CHECK_OBJECT_REF
if (sentp == &ob->sent)
@@ -2281,7 +2309,7 @@ f_disable_commands (svalue_t *sp)
return sp;
if (d_flag > 1) {
- debug_message("%s Disable commands %s (ref %ld)\n"
+ debug_message("%s Disable commands %s (ref %"PRIdPINT")\n"
, time_stamp(), get_txt(current_object->name)
, current_object->ref);
}
@@ -2311,7 +2339,7 @@ f_enable_commands (svalue_t *sp)
return sp;
if (d_flag > 1) {
- debug_message("%s Enable commands %s (ref %ld)\n"
+ debug_message("%s Enable commands %s (ref %"PRIdPINT")\n"
, time_stamp(), get_txt(current_object->name)
, current_object->ref);
}
@@ -2545,8 +2573,8 @@ f_set_modify_command (svalue_t *sp)
else
{
if (sp->u.number != -1)
- errorf("Bad num arg 1 to set_modify_command(): got %ld, "
- "expected 0 or -1\n", sp->u.number);
+ errorf("Bad num arg 1 to set_modify_command(): got %"PRIdPINT
+ ", expected 0 or -1\n", sp->u.number);
if (old) ref_object(old, "set_modify_command");
}
}
diff --git a/src/array.c b/src/array.c
index 420f316..218abad 100644
--- a/src/array.c
+++ b/src/array.c
@@ -63,7 +63,7 @@
#include "array.h"
#include "backend.h"
#include "closure.h" /* closure_cmp(), closure_eq() */
-#include "interpret.h" /* for the efuns */
+#include "interpret.h"
#include "main.h"
#include "mapping.h"
#include "mempools.h"
@@ -133,7 +133,7 @@ _allocate_array(mp_int n MTRACE_DECL)
svalue_t *svp;
if (n < 0 || (max_array_size && (size_t)n > max_array_size))
- errorf("Illegal array size: %ld.\n", n);
+ errorf("Illegal array size: %"PRIdMPINT".\n", n);
if (n == 0) {
p = ref_array(&null_vector);
@@ -145,10 +145,11 @@ _allocate_array(mp_int n MTRACE_DECL)
p = ALLOC_VECTOR(n);
if (!p) {
#ifndef MALLOC_TRACE
- (*allocate_array_error_handler)("Out of memory: array[%ld]\n", n);
+ (*allocate_array_error_handler)
+ ("Out of memory: array[%"PRIdMPINT"]\n", n);
#else
(*allocate_array_error_handler)
- ("(%s:%d) Out of memory: array[%ld]\n"
+ ("(%s:%d) Out of memory: array[%"PRIdMPINT"]\n"
MTRACE_PASS, n);
#endif
return 0;
@@ -191,7 +192,7 @@ _allocate_array_unlimited(mp_int n MTRACE_DECL)
svalue_t *svp;
if (n < 0)
- errorf("Illegal array size: %ld.\n", n);
+ errorf("Illegal array size: %"PRIdMPINT".\n", n);
if (n == 0) {
p = ref_array(&null_vector);
@@ -204,10 +205,10 @@ _allocate_array_unlimited(mp_int n MTRACE_DECL)
if (!p) {
#ifndef MALLOC_TRACE
(*allocate_array_error_handler)
- ("Out of memory: unlimited array[%ld]\n", n);
+ ("Out of memory: unlimited array[%"PRIdMPINT"]\n", n);
#else
(*allocate_array_error_handler)
- ("(%s:%d) Out of memory: unlimited array[%ld]\n"
+ ("(%s:%d) Out of memory: unlimited array[%"PRIdMPINT"]\n"
MTRACE_PASS, n);
#endif
return 0;
@@ -247,7 +248,7 @@ _allocate_uninit_array (mp_int n MTRACE_DECL)
vector_t *p;
if (n < 0 || (max_array_size && (size_t)n > max_array_size))
- errorf("Illegal array size: %ld.\n", n);
+ errorf("Illegal array size: %"PRIdMPINT".\n", n);
if (n == 0) {
p = ref_array(&null_vector);
@@ -260,10 +261,10 @@ _allocate_uninit_array (mp_int n MTRACE_DECL)
if (!p) {
#ifndef MALLOC_TRACE
(*allocate_array_error_handler)
- ("Out of memory: uninited array[%ld]\n", n);
+ ("Out of memory: uninited array[%"PRIdMPINT"]\n", n);
#else
(*allocate_array_error_handler)
- ("(%s:%d) Out of memory: uninited array[%ld]\n"
+ ("(%s:%d) Out of memory: uninited array[%"PRIdMPINT"]\n"
MTRACE_PASS, n);
#endif
return 0;
@@ -293,7 +294,8 @@ _free_vector (vector_t *p)
#ifdef DEBUG
if (p->ref > 0)
- fatal("Vector with %ld refs passed to _free_vector()\n", p->ref);
+ fatal("Vector with %"PRIdPINT" refs passed to _free_vector()\n",
+ p->ref);
if (p == &null_vector)
fatal("Tried to free the zero-size shared vector.\n");
#endif
@@ -1860,7 +1862,7 @@ v_allocate (svalue_t *sp, int num_arg)
size = svp->u.number;
if (size < 0 || (max_array_size && (size_t)size > max_array_size))
- errorf("Illegal array size: %ld\n", (long)size);
+ errorf("Illegal array size: %"PRIdPINT"\n", size);
if (size == 0 && dim < num_dim-1)
errorf("Only the last dimension can have empty arrays.\n");
@@ -2186,7 +2188,8 @@ x_map_array (svalue_t *sp, int num_arg)
res = allocate_array(cnt);
if (!res)
- errorf("(map_array) Out of memory: array[%ld] for result\n", cnt);
+ errorf("(map_array) Out of memory: array[%"PRIdMPINT
+ "] for result\n", cnt);
push_array(inter_sp, res); /* In case of errors */
for (w = arr->item, x = res->item; --cnt >= 0; w++, x++)
@@ -2224,7 +2227,8 @@ x_map_array (svalue_t *sp, int num_arg)
res = allocate_array(cnt);
if (!res)
- errorf("(map_array) Out of memory: array[%ld] for result\n", cnt);
+ errorf("(map_array) Out of memory: array[%"PRIdMPINT
+ "] for result\n", cnt);
push_array(inter_sp, res); /* In case of errors */
/* Loop through arr and res, mapping the values from arr */
diff --git a/src/array.h b/src/array.h
index 0b8aef4..059d07d 100644
--- a/src/array.h
+++ b/src/array.h
@@ -7,49 +7,6 @@
#include "typedefs.h"
#include "svalue.h"
-/* --- Macros --- */
-
-/* vector_t *ref_array(vector_t *a)
- * Add another ref to array and return the vector .
- */
-
-#define ref_array(a) ((a)->ref++, (a))
-
-/* void free_array(vector_t *a)
- * Subtract one ref from array , and free the array fully if
- * the refcount reaches zero.
- */
-
-#define free_array(a) MACRO( if (--((a)->ref) <= 0) _free_vector(a); )
-
-/* p_int deref_array(vector_t *a)
- * Subtract one ref from array , but don't check if it needs to
- * be freed. Result is the number of refs left.
- */
-
-#define deref_array(a) (--(a)->ref)
-
-/* See array.c for a description of what the following macros do. */
-
-/* Helper for LOCAL_VECn() */
-#ifdef DEBUG
-# define VEC_DEBUGREF(ref) ref,
-#else
-# define VEC_DEBUGREF(ref)
-#endif
-#include "svalue.h"
-
-#define VEC_HEAD(size) size, 1, VEC_DEBUGREF(1) NULL
-
-#define VEC_SIZE(v) ((v)->size)
-
-#define LOCAL_VEC1(name, type1) \
- struct { vector_t v; } name \
- = { { VEC_HEAD(1), { { type1, { 0 } } } } }
-
-#define LOCAL_VEC2(name, type1, type2) \
- struct { vector_t v; svalue_t item[1]; } name \
- = { { VEC_HEAD(2), { { type1, { 0 } } } }, { { type2, { 0 } } } }
/* --- Types --- */
@@ -70,6 +27,30 @@ struct vector_s {
};
+/* --- Macros --- */
+/* See array.c for a description of what the following macros do. */
+
+/* Helper for LOCAL_VECn() */
+#ifdef DEBUG
+# define VEC_DEBUGREF(ref) ref,
+#else
+# define VEC_DEBUGREF(ref)
+#endif
+
+
+#define VEC_HEAD(size) size, 1, VEC_DEBUGREF(1) NULL
+
+#define VEC_SIZE(v) ((v)->size)
+
+#define LOCAL_VEC1(name, type1) \
+ struct { vector_t v; } name \
+ = { { VEC_HEAD(1), { { type1, { 0 } } } } }
+
+#define LOCAL_VEC2(name, type1, type2) \
+ struct { vector_t v; svalue_t item[1]; } name \
+ = { { VEC_HEAD(2), { { type1, { 0 } } } }, { { type2, { 0 } } } }
+
+
/* --- Variables --- */
extern vector_t null_vector;
@@ -77,6 +58,7 @@ extern vector_t null_vector;
extern int num_arrays;
extern void (*allocate_array_error_handler) (const char *, ...);
+
/* --- Prototypes --- */
#if defined(MALLOC_TRACE)
@@ -134,4 +116,33 @@ extern void clear_array_size (void);
extern void count_array_size (vector_t *vec);
#endif
+
+/* --- static helper functions --- */
+
+/* vector_t *ref_array(vector_t *a)
+ * Add another ref to array and return the vector .
+ */
+static INLINE vector_t* ref_array(vector_t *a) {
+ ++a->ref;
+ return a;
+}
+
+/* void free_array(vector_t *a)
+ * Subtract one ref from array , and free the array fully if
+ * the refcount reaches zero.
+ */
+static INLINE void free_array(vector_t *a) {
+ if (--(a->ref) <= 0)
+ _free_vector(a);
+}
+
+/* p_int deref_array(vector_t *a)
+ * Subtract one ref from array , but don't check if it needs to
+ * be freed. Result is the number of refs left.
+ */
+static INLINE p_int deref_array(vector_t *a) {
+ return --a->ref;
+}
+
+
#endif /* ARRAY_H__ */
diff --git a/src/backend.c b/src/backend.c
index 092b579..d1bc46d 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -74,6 +74,8 @@
#include "wiz_list.h"
#include "xalloc.h"
+#include "i-eval_cost.h"
+
#include "../mudlib/sys/driver_hook.h"
#include "../mudlib/sys/debug_message.h"
@@ -122,9 +124,9 @@ uint num_last_data_cleaned = 0;
/* Number of object data-cleaned in last process_objects().
*/
-statistic_t stat_last_processed = { 0 };
-statistic_t stat_last_data_cleaned = { 0 };
-statistic_t stat_in_list = { 0 };
+statistic_t stat_last_processed = { 0, 0, 0.0 };
+statistic_t stat_last_data_cleaned = { 0, 0, 0.0 };
+statistic_t stat_in_list = { 0, 0, 0.0 };
/* Decaying average number of objects processed and objects in the list.
*/
@@ -151,12 +153,12 @@ Bool mud_is_up = MY_FALSE;
*/
#endif
-statistic_t stat_load = { 0 };
+statistic_t stat_load = { 0, 0, 0.0 };
/* The load average (player commands/second), weighted over the
* last period of time.
*/
-statistic_t stat_compile = { 0 };
+statistic_t stat_compile = { 0, 0, 0.0 };
/* The average of compiled lines/second, weighted over the last period
* of time.
*/
@@ -337,7 +339,7 @@ handle_usr1 (int sig UNUSED)
#ifndef RETSIGTYPE_VOID
return 0;
#endif
-} /* handle_usr1() */
+} /* handle_usr2() */
/*-------------------------------------------------------------------------*/
static RETSIGTYPE
@@ -614,7 +616,7 @@ backend (void)
/* puts("Handling outgoing connections."); */
check_for_out_connections();
} else
- extra_jobs_to_do = MY_FALSE;
+ extra_jobs_to_do = MY_FALSE;
} /* if (extra_jobs_to_do */
@@ -841,8 +843,9 @@ void check_alarm (void)
}
else if (curtime - last_alarm_time > 15)
{
- debug_message("%s Last alarm was %ld seconds ago - restarting it.\n"
- , time_stamp(), curtime - last_alarm_time);
+ debug_message("%s Last alarm was %"PRIdMPINT" seconds ago "
+ "- restarting it.\n",
+ time_stamp(), curtime - last_alarm_time);
alarm(0); /* stop alarm in case it is still alive, but just slow */
comm_time_to_call_heart_beat = MY_TRUE;
@@ -931,7 +934,7 @@ static Bool did_swap;
error_recovery_info.rt.last = rt_context;
error_recovery_info.rt.type = ERROR_RECOVERY_BACKEND;
- rt_context = (rt_context_t *)&error_recovery_info;
+ rt_context = (rt_context_t *)&error_recovery_info.rt;
if (setjmp(error_recovery_info.con.text))
{
diff --git a/src/bitstrings.c b/src/bitstrings.c
index c8832cc..e077010 100644
--- a/src/bitstrings.c
+++ b/src/bitstrings.c
@@ -64,10 +64,10 @@ last_bit (string_t *str)
*/
{
- mp_int pos;
- long len;
- char * cstr;
- int c;
+ mp_int pos;
+ long len;
+ const char * cstr;
+ int c;
pos = -1;
@@ -624,7 +624,7 @@ f_count_bits (svalue_t *sp)
} /* f_count_bits() */
/*-------------------------------------------------------------------------*/
-static INLINE void
+static void
copy_bits ( string_t * dest, p_int deststart
, string_t * src, p_int srcstart
, p_int len
diff --git a/src/bytecode.h b/src/bytecode.h
index bd4d024..686bc19 100644
--- a/src/bytecode.h
+++ b/src/bytecode.h
@@ -232,7 +232,7 @@ typedef bytecode_t * bytecode_p;
RSTORE_2BYTE(p,_us);)
#else
# error "Unsupported size of short."
-#endif
+#endif /* SIZEOF_SHORT */
#if SIZEOF_LONG == 4
# define GET_LONG(d,p) GET_4BYTE(d,p)
@@ -256,7 +256,7 @@ typedef bytecode_t * bytecode_p;
RSTORE_4BYTE(p,_ui);)
#else
# error "Unsupported size of long."
-#endif
+#endif /* SIZEOF_LONG */
#define LOAD_INT16(d,p) LOAD_2BYTE(d,p)
@@ -280,7 +280,7 @@ typedef bytecode_t * bytecode_p;
# define LOAD_INT32(d,p) LOAD_2BYTE(d,p)
#endif
-#endif
+#endif /* CHAR_BIT */
#ifndef GET_CODE
# error "No bytecode type defined."
diff --git a/src/call_out.c b/src/call_out.c
index e410302..bfd45dc 100644
--- a/src/call_out.c
+++ b/src/call_out.c
@@ -46,6 +46,8 @@
#include "wiz_list.h"
#include "xalloc.h"
+#include "i-eval_cost.h"
+
#include "../mudlib/sys/debug_info.h"
/*-------------------------------------------------------------------------*/
@@ -262,7 +264,7 @@ call_out (void)
error_recovery_info.rt.last = rt_context;
error_recovery_info.rt.type = ERROR_RECOVERY_BACKEND;
- rt_context = (rt_context_t *)&error_recovery_info;
+ rt_context = (rt_context_t *)&error_recovery_info.rt;
if (setjmp(error_recovery_info.con.text))
{
diff --git a/src/closure.c b/src/closure.c
index d69ae36..da48f86 100644
--- a/src/closure.c
+++ b/src/closure.c
@@ -344,6 +344,9 @@ static work_area_t current
/* Forward declarations */
static void lambda_error VARPROT((const char *error_str, ...), printf, 1, 2) NORETURN;
+static void lambda_cerror(const char *s) FORMATDEBUG(printf,1,0) NORETURN;
+static void lambda_cerrorl(const char *s1, const char *s2 UNUSED, int line1 UNUSED,
+ int line2 UNUSED) NORETURN FORMATDEBUG(printf,1,0);
static void free_symbols(void);
static Bool is_lvalue (svalue_t *argp, int index_lvalue);
static void compile_lvalue(svalue_t *, int);
@@ -939,7 +942,7 @@ replace_program_lambda_adjust (replace_ob_t *r_ob)
error_recovery_info.rt.last = rt_context;
error_recovery_info.rt.type = ERROR_RECOVERY_BACKEND;
- rt_context = (rt_context_t *)&error_recovery_info;
+ rt_context = (rt_context_t *)&error_recovery_info.rt;
if (setjmp(error_recovery_info.con.text))
{
bytecode_p p;
@@ -1347,8 +1350,9 @@ realloc_values (void)
new_values = xalloc(new_max * sizeof(*new_values));
if (!new_values)
- lambda_error("Out of memory (%lu bytes) for %ld new values\n"
- , new_max, new_max * sizeof(*new_values));
+ lambda_error("Out of memory (%"PRIdMPINT
+ " bytes) for %"PRIdMPINT" new values\n",
+ new_max, new_max * sizeof(*new_values));
current.values_left += current.value_max;
memcpy( (current.valuep = new_values + current.value_max)
@@ -1380,7 +1384,8 @@ realloc_code (void)
new_max = current.code_max * 2;
new_code = rexalloc(current.code, (size_t)new_max);
if (!new_code)
- lambda_error("Out of memory (%ld bytes) for new code\n", new_max);
+ lambda_error("Out of memory (%"PRIdMPINT" bytes) for new code\n",
+ new_max);
current.code_left += current.code_max;
current.code_max = new_max;
@@ -1595,7 +1600,7 @@ make_symbol (string_t *name)
if (!symp) {
current.symbol_max /= 2;
xfree(sym);
- lambda_error("Out of memory (%ld bytes) for symbol table\n"
+ lambda_error("Out of memory (%"PRIdMPINT" bytes) for symbol table\n"
, current.symbol_max);
}
current.symbol_mask = i = current.symbol_max - (long)sizeof sym;
@@ -5200,8 +5205,8 @@ lambda (vector_t *args, svalue_t *block, object_t *origin)
current.code_left = CODE_BUFFER_START_SIZE-3;
current.levels_left = MAX_LAMBDA_LEVELS;
if ( !(current.code = current.codep = xalloc((size_t)current.code_max)) )
- lambda_error("Out of memory (%ld bytes) for initial codebuffer\n"
- , current.code_max);
+ lambda_error("Out of memory (%"PRIdMPINT
+ " bytes) for initial codebuffer\n", current.code_max);
/* Store the lambda code header */
STORE_UINT8(current.codep, 0); /* dummy for num values */
@@ -5212,8 +5217,9 @@ lambda (vector_t *args, svalue_t *block, object_t *origin)
if ( !(current.values =
xalloc(current.value_max * sizeof current.values[0])) )
{
- lambda_error("Out of memory (%lu bytes) for initial value buffer\n"
- , current.value_max * sizeof current.values[0]);
+ lambda_error("Out of memory (%"PRIdMPINT
+ " bytes) for initial value buffer\n",
+ current.value_max * sizeof current.values[0]);
}
current.valuep = current.values + current.value_max;
diff --git a/src/closure.h b/src/closure.h
index 1914ed1..c81641b 100644
--- a/src/closure.h
+++ b/src/closure.h
@@ -9,6 +9,10 @@
#include "svalue.h"
#endif /* USE_NEW_INLINES */
+/* In case offsetof() is not a compiler builtin include stddef.h which
+ * supplies a define as fallback. Needed for LAMBDA_VALUE_OFFSET */
+#include
+
/* --- Types --- */
/* --- struct lambda_s: ---
diff --git a/src/comm.c b/src/comm.c
index 6cee71a..f67d871 100644
--- a/src/comm.c
+++ b/src/comm.c
@@ -140,6 +140,8 @@
#include "wiz_list.h"
#include "xalloc.h"
+#include "i-eval_cost.h"
+
#include "../mudlib/sys/comm.h"
#include "../mudlib/sys/driver_hook.h"
#include "../mudlib/sys/input_to.h"
@@ -398,22 +400,26 @@ static void (*telopts_wont[NTELOPTS])(int);
/* Tables with the telnet statemachine handlers.
*/
-#define TS_DATA 0
-#define TS_IAC 1
-#define TS_WILL 2
-#define TS_WONT 3
-#define TS_DO 4
-#define TS_DONT 5
-#define TS_SB 6
-#define TS_SB_IAC 7
-#define TS_READY 8
-#define TS_SYNCH 9
-#define TS_INVALID 10
+enum telnet_states {
+ TS_DATA = 0,
+ TS_IAC,
+ TS_WILL,
+ TS_WONT,
+ TS_DO,
+ TS_DONT,
+ TS_SB,
+ TS_SB_IAC,
+ TS_READY,
+ TS_SYNCH,
+ TS_INVALID
+};
/* Telnet states
*/
-#define TN_START_VALID(x) ((x & ~1) == TS_SB)
+static inline int TN_START_VALID(int x) {
+ return (x & ~TS_IAC) == TS_SB;
+}
/* --- Misc --- */
@@ -526,16 +532,13 @@ static void *writer_thread(void *arg);
# define s6_addr32 __u6_addr.__u6_addr32
#endif
-#ifndef CREATE_IPV6_MAPPED
-
-#define CREATE_IPV6_MAPPED(v6,v4) \
- ((v6).s6_addr32[0] = 0, \
- (v6).s6_addr32[1] = 0, \
- (v6).s6_addr32[2] = 0x0000ffff, \
- (v6).s6_addr32[2] = 0xffff0000, \
- (v6).s6_addr32[3] = v4 )
-
-#endif
+static inline void CREATE_IPV6_MAPPED(struct in_addr *v6, uint32 v4) {
+ v6->s6_addr32[0] = 0;
+ v6->s6_addr32[1] = 0;
+ v6->s6_addr32[2] = 0x0000ffff;
+ v6->s6_addr32[2] = 0xffff0000;
+ v6->s6_addr32[3] = v4;
+}
/* These are the typical IPv6 structures - we use them transparently.
*
@@ -663,6 +666,8 @@ dump_bytes (void * data, size_t length, int indent)
} /* dump_bytes() */
/*-------------------------------------------------------------------------*/
+static void comm_fatal (interactive_t *ip, char *fmt, ...)
+ FORMATDEBUG(printf,2,3) ;
static void
comm_fatal (interactive_t *ip, char *fmt, ...)
@@ -729,20 +734,20 @@ comm_fatal (interactive_t *ip, char *fmt, ...)
dump_bytes(&(ip->prompt), sizeof(ip->prompt), 21);
fprintf(stderr, " .addr: ");
dump_bytes(&(ip->addr), sizeof(ip->addr), 21);
- fprintf(stderr, " .msg_discarded: %02x\n", (unsigned char)ip->msg_discarded);
- fprintf(stderr, " .set_input_to: %02x\n", (unsigned char)ip->set_input_to);
- fprintf(stderr, " .closing: %02x\n", (unsigned char)ip->closing);
- fprintf(stderr, " .tn_enabled: %02x\n", (unsigned char)ip->tn_enabled);
- fprintf(stderr, " .do_close: %02x", (unsigned char)ip->do_close);
+ fprintf(stderr, " .msg_discarded: %02hhx\n", (unsigned char)ip->msg_discarded);
+ fprintf(stderr, " .set_input_to: %02hhx\n", (unsigned char)ip->set_input_to);
+ fprintf(stderr, " .closing: %02hhx\n", (unsigned char)ip->closing);
+ fprintf(stderr, " .tn_enabled: %02hhx\n", (unsigned char)ip->tn_enabled);
+ fprintf(stderr, " .do_close: %02hhx", (unsigned char)ip->do_close);
if (ip->do_close & (FLAG_DO_CLOSE|FLAG_PROTO_ERQ)) fprintf(stderr, " (");
if (ip->do_close & FLAG_DO_CLOSE) fprintf(stderr, "DO_CLOSE");
if (ip->do_close & (FLAG_DO_CLOSE|FLAG_PROTO_ERQ)) fprintf(stderr, ", ");
if (ip->do_close & FLAG_PROTO_ERQ) fprintf(stderr, "PROTO_ERQ");
if (ip->do_close & (FLAG_DO_CLOSE|FLAG_PROTO_ERQ)) fprintf(stderr, ")");
putc('\n', stderr);
- fprintf(stderr, " .noecho: %02x", (unsigned char)ip->noecho);
+ fprintf(stderr, " .noecho: %02hhx", (unsigned char)ip->noecho);
fprintf(stderr, " %s\n", decode_noecho(ip->noecho));
- fprintf(stderr, " .tn_state: %d", ip->tn_state);
+ fprintf(stderr, " .tn_state: %hhd", ip->tn_state);
switch(ip->tn_state) {
case TS_DATA: fprintf(stderr, " (TS_DATA)\n"); break;
case TS_IAC: fprintf(stderr, " (TS_IAC)\n"); break;
@@ -757,7 +762,7 @@ comm_fatal (interactive_t *ip, char *fmt, ...)
case TS_INVALID: fprintf(stderr, " (TS_INVALID)\n"); break;
default: putc('\n', stderr);
}
- fprintf(stderr, " .save_tn_state: %d", ip->save_tn_state);
+ fprintf(stderr, " .save_tn_state: %hhd", ip->save_tn_state);
switch(ip->save_tn_state) {
case TS_DATA: fprintf(stderr, " (TS_DATA)\n"); break;
case TS_IAC: fprintf(stderr, " (TS_IAC)\n"); break;
@@ -772,13 +777,13 @@ comm_fatal (interactive_t *ip, char *fmt, ...)
case TS_INVALID: fprintf(stderr, " (TS_INVALID)\n"); break;
default: putc('\n', stderr);
}
- fprintf(stderr, " .supress_go_ahead: %02x\n", (unsigned char)ip->supress_go_ahead);
+ fprintf(stderr, " .supress_go_ahead: %02hhx\n", (unsigned char)ip->supress_go_ahead);
fprintf(stderr, " .text_end: %hd (%p)\n", ip->text_end, ip->text+ip->text_end);
fprintf(stderr, " .command_start: %hd (%p)\n", ip->command_start, ip->text+ip->command_start);
fprintf(stderr, " .command_end: %hd (%p)\n", ip->command_end, ip->text+ip->command_end);
fprintf(stderr, " .tn_start: %hd (%p)\n", ip->tn_start, ip->text+ip->tn_start);
fprintf(stderr, " .tn_end: %hd (%p)\n", ip->tn_end, ip->text+ip->tn_end);
- fprintf(stderr, " .chars_ready: %ld\n", (long)ip->chars_ready);
+ fprintf(stderr, " .chars_ready: %"PRId32"\n",ip->chars_ready);
#ifdef USE_SNOOPING
fprintf(stderr, " .snoop_on: %p", ip->snoop_on);
if (ip->snoop_on && ip->snoop_on->ob) fprintf(stderr, " (%s)", get_txt(ip->snoop_on->ob->name));
@@ -787,7 +792,7 @@ comm_fatal (interactive_t *ip, char *fmt, ...)
if (ip->snoop_by) fprintf(stderr, " (%s)", get_txt(ip->snoop_by->name));
putc('\n', stderr);
#endif
- fprintf(stderr, " .last_time: %ld\n", (long)ip->last_time);
+ fprintf(stderr, " .last_time: %"PRIdMPINT"\n", ip->last_time);
#ifdef USE_SOCKET_LIMITS
fprintf(stderr, " .numCmds: %ld\n", ip->numCmds);
fprintf(stderr, " .maxNumCmds: %ld\n", ip->maxNumCmds);
@@ -808,10 +813,10 @@ comm_fatal (interactive_t *ip, char *fmt, ...)
dump_bytes(&(ip->charset), sizeof(ip->charset), 21);
fprintf(stderr, " .combine_cset: ");
dump_bytes(&(ip->combine_cset), sizeof(ip->combine_cset), 21);
- fprintf(stderr, " .quote_iac: %02x\n", (unsigned char)ip->quote_iac);
- fprintf(stderr, " .catch_tell_activ: %02x\n", (unsigned char)ip->catch_tell_activ);
- fprintf(stderr, " .gobble_char: %02x\n", (unsigned char)ip->gobble_char);
- fprintf(stderr, " .ts_data: %02x\n", (unsigned char)ip->ts_data);
+ fprintf(stderr, " .quote_iac: %02hhx\n", (unsigned char)ip->quote_iac);
+ fprintf(stderr, " .catch_tell_activ: %02hhx\n", (unsigned char)ip->catch_tell_activ);
+ fprintf(stderr, " .gobble_char: %02hhx\n", (unsigned char)ip->gobble_char);
+ fprintf(stderr, " .ts_data: %02hhx\n", (unsigned char)ip->ts_data);
fprintf(stderr, " .text: ");
dump_bytes(&(ip->text), sizeof(ip->text), 21);
fprintf(stderr, " .message_buf: ");
@@ -1417,9 +1422,8 @@ interactive_cleanup (interactive_t *ip)
default:
{
- int e = tmp->errorno;
dprintf2(2, "%s comm: write: unexpected errno %d\n"
- , (p_int)time_stamp(), (p_int)e);
+ , (p_int)time_stamp(), (p_int)tmp->errorno);
break;
}
} /* switch (ip->errorno) */
@@ -1959,15 +1963,20 @@ add_message (const char *fmt, ...)
}
else
{
- buff[(sizeof buff) - 1] = '\0'; /* Overrun sentinel */
- vsprintf(buff+1,fmt,va);
+ size_t len;
+ len = vsnprintf(buff+1, sizeof(buff)-1, fmt,va);
va_end(va);
- if (buff[(sizeof buff) - 1])
+ /* old sprintf() implementations returned -1 if the output was
+ * truncated. Since size_t is an unsigned type, the check for
+ * len == -1 is implicitly included by >= sizeof(...)-1, because
+ * -1 will be wrapped to SIZE_T_MAX which is the maximum sizeof()
+ * can return and can never be valid as return value here. */
+ if (len >= sizeof(buff)-1)
{
- debug_message("%s Message too long: '%.200s...'\n"
- , time_stamp(), buff);
- comm_fatal(ip, "Message too long!\n");
- return;
+ char err[] = "\n*** Message truncated ***\n";
+ debug_message("%s Message too long (Length: %zu): '%.200s...'\n"
+ , time_stamp(), len, buff);
+ (void)strcpy(buff+(sizeof(buff)-sizeof(err)), err);
}
source = buff+1;
srclen = strlen(buff+1);
@@ -2071,9 +2080,9 @@ add_message (const char *fmt, ...)
#ifdef DEBUG
if (d_flag > 1)
- debug_message("%s [%s(%ld)]: %s"
+ debug_message("%s [%s (%zu)]: %s"
, time_stamp(), get_txt(command_giver->name)
- , (long)srclen, source);
+ , srclen, source);
#endif
/* --- Send the final message --- */
@@ -2095,8 +2104,8 @@ if (sending_telnet_command)
{
char *cp;
long left;
- printf("%s TDEBUG: '%s' Sending telnet (%lu bytes): "
- , time_stamp(), get_txt(ip->ob->name), (unsigned long) strlen(source));
+ printf("%s TDEBUG: '%s' Sending telnet (%zu bytes): "
+ , time_stamp(), get_txt(ip->ob->name), strlen(source));
for (cp = source, left = srclen; left > 0; cp++, left--)
printf(" %02x", (unsigned char)*cp);
printf("\n");
@@ -2310,14 +2319,14 @@ if (sending_telnet_command)
ip->out_compress->next_out = ip->out_compress_buf + length - n;
if (n != length)
fprintf(stderr, "%s write socket (compressed): wrote %ld, "
- "should be %ld.\n"
- , time_stamp(), (long)n, (long)chunk);
+ "should be %td.\n"
+ , time_stamp(), (long)n, chunk);
}
else
#endif
if (n != chunk)
- fprintf(stderr, "%s write socket: wrote %ld, should be %ld.\n"
- , time_stamp(), (long)n, (long)chunk);
+ fprintf(stderr, "%s write socket: wrote %ld, should be %td.\n"
+ , time_stamp(), (long)n, chunk);
/* Continue with the processing of source */
dest = &ip->message_buf[0];
@@ -2361,7 +2370,8 @@ reset_input_buffer (interactive_t *ip)
{
if (ip->command_start)
{
- DTN(("reset input buffer: cmd_start %d, tn_start %d, tn_end %d, text_end %d\n", ip->command_start, ip->tn_start, ip->tn_end, ip->text_end));
+ DTN(("reset input buffer: cmd_start %hd, tn_start %hd, tn_end %hd, text_end %hd\n",
+ ip->command_start, ip->tn_start, ip->tn_end, ip->text_end));
ip->tn_start -= ip->command_start;
ip->tn_end -= ip->command_start;
ip->text_end -= ip->command_start;
@@ -2714,7 +2724,7 @@ get_message (char *buff, size_t *len)
if (l <= 0)
{
#ifdef DEBUG_ERQ
- fprintf(stderr, "%s read %ld bytes from erq demon\n"
+ fprintf(stderr, "%s read %"PRIdMPINT" bytes from erq demon\n"
, time_stamp(), l);
if (l)
perror("");
@@ -2745,7 +2755,7 @@ get_message (char *buff, size_t *len)
#ifdef DEBUG_ERQ
fprintf( stderr
, "%s invalid length of message from"
- "erq demon: %ld bytes\n"
+ "erq demon: %"PRIdMPINT" bytes\n"
, time_stamp(), msglen);
#endif /* DEBUG_ERQ */
stop_erq_demon(MY_TRUE);
@@ -2784,14 +2794,14 @@ get_message (char *buff, size_t *len)
}
#endif
} else {
- int32 naddr;
+ uint32 naddr;
struct in_addr net_addr;
- memcpy((char*)&naddr, rp+8, 4);
+ memcpy((char*)&naddr, rp+8, sizeof(naddr));
#ifndef USE_IPV6
net_addr.s_addr = naddr;
#else
- CREATE_IPV6_MAPPED(net_addr, naddr);
+ CREATE_IPV6_MAPPED(&net_addr, naddr);
#endif
add_ip_entry(net_addr, rp+12);
}
@@ -3003,8 +3013,8 @@ get_message (char *buff, size_t *len)
udp_data = new_n_mstring(udp_buf, cnt);
if (!udp_data)
{
- debug_message("%s Out of memory (%ld bytes) for UDP message.\n"
- , time_stamp(), (long)cnt);
+ debug_message("%s Out of memory (%d bytes) for UDP message.\n"
+ , time_stamp(), cnt);
}
else
{
@@ -3073,13 +3083,33 @@ get_message (char *buff, size_t *len)
l = MAX_TEXT - ip->text_end;
+ /* In CHARMODE with combine-charset, the driver gets
+ * confused when receiving MAX_TEXT or more combinable
+ * characters.
+ * I couldn't quite figure out what and why, but
+ * reading less than MAX_TEXT characters works around
+ * the issue.
+ */
+#ifndef SIMULATE_CHARMODE
+ if ((ip->noecho & (CHARMODE_REQ|CHARMODE)) == (CHARMODE_REQ|CHARMODE))
+#else
+ if (ip->noecho & (CHARMODE_REQ|CHARMODE))
+#endif
+ {
+ l -= 2;
+ }
+
+ DTN(("text_end %hd, can read %d chars\n", ip->text_end, l));
+
#ifdef USE_TLS
if (ip->tls_status != TLS_INACTIVE)
- l = tls_read(ip, ip->text + ip->text_end, l);
+ l = tls_read(ip, ip->text + ip->text_end, (size_t)l);
else
#endif
l = socket_read(ip->socket, ip->text + ip->text_end, (size_t)l);
-
+ DTN(("# chars read: %d\n", l));
+ /* TODO: Check if the block below can be simplified by using
+ * TODO::strerror().*/
if (l == -1) {
if (errno == ENETUNREACH) {
debug_message("%s Net unreachable detected.\n"
@@ -3251,8 +3281,8 @@ get_message (char *buff, size_t *len)
? ip->tn_start
: ip->command_end
) - ip->command_start;
- DTN((" incomplete negotiation: length %d\n"
- , length));
+ DTN((" incomplete negotiation: length %ld\n"
+ , (long)length));
if (!length)
continue;
if (length < 0)
@@ -3260,7 +3290,7 @@ get_message (char *buff, size_t *len)
comm_fatal(ip, "comm: data length < 0: %ld\n", (long)length);
continue;
}
- DTN((" save machine state %d, set to %d (READY)\n"
+ DTN((" save machine state %hhd, set to %d (READY)\n"
, ip->tn_state, TS_READY));
ip->save_tn_state = ip->tn_state;
ip->chars_ready = length;
@@ -3274,7 +3304,7 @@ get_message (char *buff, size_t *len)
* At the moment it is TS_INVALID, so the next
* character received would be thrown away.
*/
- DTN((" save machine state %d (DATA)\n"
+ DTN((" Empty input: save machine state %d (DATA)\n"
, TS_DATA));
length = strlen(ip->text + ip->command_start) + 1;
ip->chars_ready = length;
@@ -3286,7 +3316,7 @@ get_message (char *buff, size_t *len)
/* Copy as many characters from the text[] into
* the buff[] as possible.
*/
- DTN((" %ld chars ready\n", ip->chars_ready));
+ DTN((" %"PRId32" chars ready\n", ip->chars_ready));
if (end_of_line)
{
DTN((" faking NL\n"));
@@ -3337,7 +3367,7 @@ get_message (char *buff, size_t *len)
if (!end_of_line)
ip->chars_ready -= destix;
- DTN((" %ld chars left ready\n", ip->chars_ready));
+ DTN((" %"PRId32" chars left ready\n", ip->chars_ready));
if (!ip->chars_ready)
{
/* All the pure data was read, now restore the
@@ -3345,7 +3375,7 @@ get_message (char *buff, size_t *len)
* Leave the first char in to make input escape
* possible
*/
- DTN((" restore old telnet machine state %d\n"
+ DTN((" restore old telnet machine state %hhd\n"
, ip->save_tn_state));
ip->tn_state = ip->save_tn_state;
ip->save_tn_state = TS_INVALID;
@@ -3366,6 +3396,7 @@ get_message (char *buff, size_t *len)
* negative. We have to correct them then to point
* to ip->command_start.
*/
+ DTN((" tn_start %hd, command_end %hd\n", ip->tn_start, ip->command_end));
if (ip->tn_start < 1)
ip->tn_start = 1;
if (ip->command_end < 1)
@@ -3389,7 +3420,7 @@ get_message (char *buff, size_t *len)
ip->numCmds++;
#endif
- DTN(("--- return with char command %02x '%c' ---\n", buff[0], buff[0]));
+ DTN(("--- return with char command %02x '%c' length %d ---\n", buff[0], buff[0], destix));
return MY_TRUE;
}
@@ -3400,7 +3431,7 @@ get_message (char *buff, size_t *len)
? ip->tn_start
: ip->command_end
) - ip->command_start;
- DTN((" data length %d\n", length));
+ DTN((" data length %ld\n", (long)length));
if (length < 0)
{
comm_fatal(ip, "comm: data length < 0: %ld\n", (long)length);
@@ -3430,7 +3461,7 @@ get_message (char *buff, size_t *len)
* the beginning of .text[] and terminated with a '\0'. Whenever
* a command is complete, the tn_state is TS_READY.
*/
- DTN(("tn complete, telnet machine state: %d\n", ip->tn_state));
+ DTN(("tn complete, telnet machine state: %hhd\n", ip->tn_state));
if (ip->tn_state == TS_READY)
{
/* We have a command: copy it into buff, handle a
@@ -3438,6 +3469,10 @@ get_message (char *buff, size_t *len)
*/
DTN(("telnet machine ready\n"));
+ /* buffer overflows here are impossible even with strcpy(),
+ * because buff is allocated in backend() as MAX_TEXT+4 and
+ * ip->text is allocated as MAX_TEXT+2. Ok, as long as nobody
+ * changes buff in backend() withour changing ip->text ... */
strcpy(buff, ip->text);
command_giver = ip->ob;
trace_level = ip->trace_level;
@@ -3484,6 +3519,10 @@ get_message (char *buff, size_t *len)
}
else
{
+ /* buff is limited to MAX_TEXT+4. Additionally,
+ * get_message() is usually not called recursively or
+ * from a very high stack depth, so alloca() is
+ * probably ok. */
char *snoop_message = alloca(strlen(buff) + 4);
sprintf(snoop_message, "%% %s\n", buff);
tell_npc_str(snooper, snoop_message);
@@ -3794,9 +3833,9 @@ static void
new_player ( object_t *ob, SOCKET_T new_socket
, struct sockaddr_in *addr, size_t addrlen
#if !defined(ACCESS_CONTROL) && !defined(USE_AUTHLOCAL)
- , int login_port UNUSED
+ , int login_port UNUSED
#else
- , int login_port
+ , int login_port
#endif
)
@@ -3924,8 +3963,8 @@ new_player ( object_t *ob, SOCKET_T new_socket
message = "Cannot accept connection (out of memory). Come back later.\r\n";
socket_write(new_socket, message, strlen(message));
socket_close(new_socket);
- debug_message("%s Out of memory (%lu bytes) for new connection.\n"
- , time_stamp(), (unsigned long) sizeof(interactive_t));
+ debug_message("%s Out of memory (%zu bytes) for new connection.\n"
+ , time_stamp(), sizeof(interactive_t));
return;
}
@@ -4137,7 +4176,7 @@ new_player ( object_t *ob, SOCKET_T new_socket
/*-------------------------------------------------------------------------*/
void
-set_noecho (interactive_t *ip, char noecho, Bool local_change)
+set_noecho (interactive_t *ip, char noecho, Bool local_change, Bool external)
/* Change the input mode ->noecho to the given , performing all
* necessary telnet negotiations. If the driverhook H_NOECHO is set,
@@ -4152,7 +4191,7 @@ set_noecho (interactive_t *ip, char noecho, Bool local_change)
if (!ip->tn_enabled)
{
- DTN(("set_noecho(%02x) old %02x: TN disabled\n"
+ DTN(("set_noecho(%02hhx) old %02hhx: TN disabled\n"
, noecho, ip->noecho));
}
@@ -4160,11 +4199,11 @@ set_noecho (interactive_t *ip, char noecho, Bool local_change)
confirm = (char)(
noecho | CHARMODE_REQ_TO_CHARMODE(noecho & (NOECHO_REQ|CHARMODE_REQ)));
- DTN(("set_noecho(%02x%s) old %02x %s\n"
+ DTN(("set_noecho(%02hhx%s) old %02hhx %s\n"
, noecho, local_change ? " local" : "", old, decode_noecho(old)));
- DTN((" -> confirm: %02x %s\n"
+ DTN((" -> confirm: %02hhx %s\n"
, confirm, decode_noecho(confirm)));
- DTN((" -> %02x %s\n"
+ DTN((" -> %02hhx %s\n"
, confirm | NOECHO_ACKSHIFT(confirm)
, decode_noecho(confirm | NOECHO_ACKSHIFT(confirm))
));
@@ -4187,7 +4226,7 @@ set_noecho (interactive_t *ip, char noecho, Bool local_change)
push_ref_valid_object(inter_sp, ob, "set_no_echo");
push_number(inter_sp, local_change ? 1 : 0);
if (driver_hook[H_NOECHO].type == T_STRING)
- secure_apply(driver_hook[H_NOECHO].u.str, ob, 3);
+ secure_apply_ob(driver_hook[H_NOECHO].u.str, ob, 3, external);
else
{
if (driver_hook[H_NOECHO].x.closure_type == CLOSURE_LAMBDA)
@@ -4197,14 +4236,14 @@ set_noecho (interactive_t *ip, char noecho, Bool local_change)
driver_hook[H_NOECHO].u.lambda->ob
= ref_object(ob, "set_noecho");
}
- secure_callback_lambda(&driver_hook[H_NOECHO], 3);
+ secure_call_lambda(&driver_hook[H_NOECHO], 3, external);
}
if (~confirm & old & CHARMODE_MASK)
{
if (ip->save_tn_state != TS_INVALID)
{
DT(("'%s' set_noecho(): 0 chars ready, "
- "saved state %d\n", get_txt(ip->ob->name)
+ "saved state %hhd\n", get_txt(ip->ob->name)
, ip->save_tn_state));
ip->chars_ready = 0;
ip->tn_state = ip->save_tn_state;
@@ -4275,7 +4314,7 @@ set_noecho (interactive_t *ip, char noecho, Bool local_change)
}
if (ip->save_tn_state != TS_INVALID)
{
- DTN(("set_noecho(): 0 chars ready, saved state %d\n", ip->save_tn_state));
+ DTN(("set_noecho(): 0 chars ready, saved state %hhd\n", ip->save_tn_state));
ip->chars_ready = 0;
ip->tn_state = ip->save_tn_state;
}
@@ -4428,7 +4467,8 @@ call_function_interactive (interactive_t *i, char *str, size_t len)
{
/* Sorry, the object has selfdestructed ! */
set_noecho(i, it->next ? it->next->noecho : 0
- , it->next ? it->next->local : MY_FALSE);
+ , it->next ? it->next->local : MY_FALSE
+ , MY_TRUE);
i->input_to = it->next;
free_input_to(it);
return MY_FALSE;
@@ -4439,7 +4479,8 @@ call_function_interactive (interactive_t *i, char *str, size_t len)
&& load_ob_from_swap(ob) < 0)
{
set_noecho(i, it->next ? it->next->noecho : 0
- , it->next ? it->next->local : MY_FALSE);
+ , it->next ? it->next->local : MY_FALSE
+ , MY_TRUE);
i->input_to = it->next;
free_input_to(it);
errorf("Out of memory: unswap object '%s'.\n", get_txt(ob->name));
@@ -4470,7 +4511,7 @@ call_function_interactive (interactive_t *i, char *str, size_t len)
error_recovery_info.rt.last = rt_context;
error_recovery_info.rt.type = ERROR_RECOVERY_BACKEND;
- rt_context = (rt_context_t *)&error_recovery_info;
+ rt_context = (rt_context_t *)&error_recovery_info.rt;
if (setjmp(error_recovery_info.con.text))
{
@@ -4505,7 +4546,8 @@ call_function_interactive (interactive_t *i, char *str, size_t len)
if (i->noecho & NOECHO_STALE)
{
set_noecho(i, i->input_to ? i->input_to->noecho : 0
- , i->input_to ? i->input_to->local : MY_FALSE);
+ , i->input_to ? i->input_to->local : MY_FALSE
+ , MY_TRUE);
}
/* Done */
@@ -4561,7 +4603,7 @@ set_call ( object_t *ob, input_to_t *it, char noecho
ip->set_input_to = MY_TRUE;
if (noecho || ip->noecho)
- set_noecho(ip, noecho, local_change);
+ set_noecho(ip, noecho, local_change, MY_FALSE);
return MY_TRUE;
} /* set_call() */
@@ -4641,7 +4683,9 @@ print_prompt_string (string_t *prompt)
put_number(hook, 0);
current_object = NULL; /* So that catch_tell() can see it */
add_message(FMT_STRING, prompt);
- errorf("H_PRINT_PROMPT for %s was a closure bound to a now-destructed object - hook removed.\n", get_txt(command_giver->name));
+ errorf("H_PRINT_PROMPT for %s was a closure bound to a "
+ "now-destructed object - hook removed.\n",
+ get_txt(command_giver->name));
/* NOTREACHED */
}
@@ -4725,7 +4769,9 @@ print_prompt (void)
free_svalue(prompt);
put_ref_string(prompt, STR_DEFAULT_PROMPT);
print_prompt_string(prompt->u.str);
- errorf("Prompt of %s was a closure bound to a now-destructed object - default prompt restored.\n", get_txt(command_giver->name));
+ errorf("Prompt of %s was a closure bound to a now-destructed "
+ "object - default prompt restored.\n",
+ get_txt(command_giver->name));
/* NOTREACHED */
}
@@ -5096,7 +5142,7 @@ reply_to_will_sga (int option)
send_do(option);
}
else DTN((" we don't need to say DO\n"));
- DTN((" noecho: %02x -> %02x\n", ip->noecho, (char)(ip->noecho | CHARMODE_MASK)));
+ DTN((" noecho: %02hhx -> %02hhx\n", ip->noecho, (char)(ip->noecho | CHARMODE_MASK)));
ip->noecho |= CHARMODE_MASK;
} else {
send_dont(option);
@@ -5134,7 +5180,8 @@ reply_to_wont_sga (int option)
send_dont(option);
}
else DTN((" we don't need to say DONT\n"));
- DTN((" noecho: %02x -> %02x\n", ip->noecho, (unsigned char)((ip->noecho & ~CHARMODE) | CHARMODE_ACK)));
+ DTN((" noecho: %02hhx -> %02hhx\n", ip->noecho,
+ (unsigned char)((ip->noecho & ~CHARMODE) | CHARMODE_ACK)));
ip->noecho = (char)((ip->noecho & ~CHARMODE) | CHARMODE_ACK);
/* Don't reset CHARMODE_REQ here: this WONT can be the answer
* to the DO SGA we sent before, and the client can still answer
@@ -5176,7 +5223,7 @@ mccp_telnet_neg (int option)
#endif
break;
default:
- DTF(("MCCP NEG (%d) STATE (%d)\n", option, ip->tn_state));
+ DTF(("MCCP NEG (%d) STATE (%hhd)\n", option, ip->tn_state));
}
} /* mccp_telnet_neg() */
@@ -5248,7 +5295,7 @@ reply_h_telnet_neg (int option)
i = WONT;
break;
default:
- debug_message("%s Invalid tn_state %d for interactive '%s'\n"
+ debug_message("%s Invalid tn_state %hhd for interactive '%s'\n"
, time_stamp(), ip->tn_state, get_txt(ip->ob->name));
break;
}
@@ -5498,7 +5545,7 @@ telnet_neg (interactive_t *ip)
from = &first[ip->tn_end];
end = &first[ip->text_end];
- DTN(("telnet_neg: state %d\n", ip->tn_state));
+ DTN(("telnet_neg: state %hhd\n", ip->tn_state));
/* Gobble the character *from if gobble_char is set.
* Also test for the end of current buffer content.
@@ -5516,7 +5563,7 @@ telnet_neg (interactive_t *ip)
return;
}
if (ip->gobble_char) {
- DTN(("t_n: gobble char %02x (in buf: %02x)\n"
+ DTN(("t_n: gobble char %02hhx (in buf: %02x)\n"
, ip->gobble_char, *from));
/* we had a crash around here:
*
@@ -5585,7 +5632,7 @@ $12 = 0x2acc67ca
do {
ch = (*from++ & 0xff);
- DTN(("t_n: processing %02x '%c'\n"
+ DTN(("t_n: processing %02hhx '%c'\n"
, (unsigned char)ch, ch));
switch(ip->tn_state)
{
@@ -5601,6 +5648,8 @@ $12 = 0x2acc67ca
if (from >= end)
{
ip->text_end = ip->tn_end = ip->command_end = (short)(to - first);
+ DTN(("t_n: (ts_data) from >= end by %td, text_end := %hd\n (max %d)"
+ , (ptrdiff_t)(from-end), ip->text_end, MAX_TEXT));
*to = '\0';
if (ip->text_end >= MAX_TEXT)
{
@@ -5610,16 +5659,19 @@ $12 = 0x2acc67ca
* In charmode, we must not reset command_end, otherwise
* it might fall under command_start.
*/
- ip->text_end = ip->tn_end = 0;
- if (!(ip->noecho & CHARMODE_REQ))
- ip->command_end = 0;
ip->tn_state = TS_READY;
+ ip->tn_end = 0;
+ ip->text_end = 0;
+ if (!(ip->noecho & (CHARMODE_REQ|CHARMODE)))
+ {
+ ip->command_end = 0;
+ }
return;
}
return;
}
ch = (*from++ & 0xff);
- DTN(("t_n: (ts_data) processing %02x '%c'\n"
+ DTN(("t_n: (ts_data) processing %02hhx '%c'\n"
, (unsigned char)ch, ch));
/* FALLTHROUGH */
@@ -5831,7 +5883,7 @@ $12 = 0x2acc67ca
case GA:
DTN(("t_n: got GA\n")); break;
default:
- DTN(("t_n: got %02x\n", ch)); break;
+ DTN(("t_n: got %02hhx\n", ch)); break;
break;
} /* switch(ch) */
state = ip->ts_data;
@@ -5840,7 +5892,7 @@ $12 = 0x2acc67ca
case TS_WILL:
command_giver = ip->ob;
if (ch < NTELOPTS) {
- DTN(("t_n: state WILL got %s (%02x)\n"
+ DTN(("t_n: state WILL got %s (%02hhx)\n"
, telopts[ch], ch));
#ifdef DEBUG_TELNET
if (d_flag)
@@ -5848,7 +5900,7 @@ $12 = 0x2acc67ca
#endif
(*telopts_will[ch])(ch);
} else {
- debug_message("%s Unknown telnet option Will %d\n"
+ debug_message("%s Unknown telnet option Will %hhd\n"
, time_stamp(), ch);
send_dont(ch);
}
@@ -5858,7 +5910,7 @@ $12 = 0x2acc67ca
case TS_WONT:
command_giver = ip->ob;
if (ch < NTELOPTS) {
- DTN(("t_n: state WONT got %s (%02x)\n"
+ DTN(("t_n: state WONT got %s (%02hhx)\n"
, telopts[ch], ch));
#ifdef DEBUG_TELNET
if (d_flag)
@@ -5866,7 +5918,7 @@ $12 = 0x2acc67ca
#endif
(*telopts_wont[ch])(ch);
} else {
- debug_message("%s Unknown telnet option Wont %d\n"
+ debug_message("%s Unknown telnet option Wont %hhd\n"
, time_stamp(), ch);
}
state = ip->ts_data;
@@ -5875,7 +5927,7 @@ $12 = 0x2acc67ca
case TS_DO:
command_giver = ip->ob;
if (ch < NTELOPTS) {
- DTN(("t_n: state DO got %s (%02x)\n"
+ DTN(("t_n: state DO got %s (%02hhx)\n"
, telopts[ch], ch));
#ifdef DEBUG_TELNET
if (d_flag)
@@ -5883,7 +5935,7 @@ $12 = 0x2acc67ca
#endif
(*telopts_do[ch])(ch);
} else {
- debug_message("%s Unknown telnet option Do %d\n"
+ debug_message("%s Unknown telnet option Do %hhd\n"
, time_stamp(), ch);
send_wont(ch);
}
@@ -5893,7 +5945,7 @@ $12 = 0x2acc67ca
case TS_DONT:
command_giver = ip->ob;
if (ch < NTELOPTS) {
- DTN(("t_n: state DONT got %s (%02x)\n"
+ DTN(("t_n: state DONT got %s (%02hhx)\n"
, telopts[ch], ch));
#ifdef DEBUG_TELNET
if (d_flag)
@@ -5901,14 +5953,14 @@ $12 = 0x2acc67ca
#endif
(*telopts_dont[ch])(ch);
} else {
- debug_message("%s Unknown telnet option Dont %d\n"
+ debug_message("%s Unknown telnet option Dont %hhd\n"
, time_stamp(), ch);
}
state = ip->ts_data;
goto change_state;
case TS_SB:
- DTN(("t_n: state TS_SB got %02x\n", ch));
+ DTN(("t_n: state TS_SB got %02hhx\n", ch));
if (ch == IAC) {
state = TS_SB_IAC;
goto change_state;
@@ -5921,7 +5973,7 @@ $12 = 0x2acc67ca
mp_int size;
vector_t *v;
- DTN(("t_n: state TS_SB_IAC got %02x\n", ch));
+ DTN(("t_n: state TS_SB_IAC got %02hhx\n", ch));
if (ch == IAC) {
DTN(("t_n: that is: state TS_SB_IAC got IAC\n"));
*to++ = (char)ch;
@@ -5937,7 +5989,7 @@ $12 = 0x2acc67ca
svalue_t *svp;
str = (unsigned char *)&ip->text[ip->tn_start];
- DTN(("t_n: that is: state TS_SB_IAC got useful SE or SB: neg SB %02x (%ld bytes)\n", *str, size));
+ DTN(("t_n: that is: state TS_SB_IAC got useful SE or SB: neg SB %02hhx (%"PRIdMPINT" bytes)\n", *str, size));
push_number(inter_sp, SB);
push_number(inter_sp, *str++);
svp = v->item;
@@ -5957,7 +6009,7 @@ $12 = 0x2acc67ca
}
case TS_SYNCH:
- DTN(("t_n: state TS_SYNCH got %02x\n", ch));
+ DTN(("t_n: state TS_SYNCH got %02hhx\n", ch));
if (ch == IAC) goto new_iac;
if (ch == DM) goto data_mark;
continue;
@@ -5965,7 +6017,7 @@ $12 = 0x2acc67ca
default:
#ifdef DEBUG_TELNET
if (d_flag)
- debug_message("%s Bad state: 0x%x\n", time_stamp(), ip->tn_state);
+ debug_message("%s Bad state: 0x%hhx\n", time_stamp(), ip->tn_state);
#endif
state = TS_DATA;
goto change_state;
@@ -6349,13 +6401,17 @@ f_send_erq (svalue_t *sp)
vector_t *v;
svalue_t *svp;
char *cp;
- mp_int j;
+ p_int j;
v = sp[-1].u.vec;
arglen = VEC_SIZE(v);
- cp = arg = alloca(arglen);
+ cp = arg = xalloc(arglen);
+ if (!arg) {
+ errorf("Out of memory (%zu bytes) in send_erq() for allocating "
+ "temporary buffer.\n", arglen);
+ }
svp = &v->item[0];
- for (j = (mp_int)arglen; --j >= 0; )
+ for (j = (p_int)arglen; --j >= 0; )
*cp++ = (char)(*svp++).u.number;
}
@@ -6403,7 +6459,11 @@ failure:
i = 0;
free_svalue(sp);
}
-
+ /* cleanup */
+ if (sp[-1].type != T_STRING) {
+ /* free arg only if sp-1 is not a string */
+ xfree(arg);
+ }
free_svalue(--sp);
(*--sp).u.number = i;
@@ -6564,7 +6624,7 @@ open_ipv6_conn( const char *hostname, const unsigned short int port
h = gethostbyname2(hostname, AF_INET);
if(h)
{
- CREATE_IPV6_MAPPED(addr.sin6_addr, *((u_int32_t *)h->h_addr_list[0]));
+ CREATE_IPV6_MAPPED(&addr.sin6_addr, *((u_int32_t *)h->h_addr_list[0]));
con = connect(sock, (struct sockaddr *) &addr, sizeof(addr));
}
}
@@ -6688,7 +6748,8 @@ remove_stale_player_data (void)
{
set_noecho(all_players[i]
, it->next ? it->next->noecho : 0
- , it->next ? it->next->local : MY_FALSE);
+ , it->next ? it->next->local : MY_FALSE
+ , MY_TRUE);
all_players[i]->input_to = it->next;
}
else
@@ -6781,7 +6842,7 @@ show_comm_status (strbuf_t * sbuf, Bool verbose UNUSED)
}
if (sbuf)
- strbuf_addf(sbuf, "Comm structures\t\t\t\t %9lu\n", sum);
+ strbuf_addf(sbuf, "Comm structures\t\t\t\t %9zu\n", sum);
return sum;
} /* show_comm_status() */
@@ -7212,7 +7273,7 @@ f_send_udp (svalue_t *sp)
*/
{
- char *to_host;
+ char *to_host = NULL;
int to_port;
char *msg;
size_t msglen;
@@ -7222,7 +7283,10 @@ f_send_udp (svalue_t *sp)
struct sockaddr_in name;
struct hostent *hp;
int ret = 0;
-
+ svalue_t *firstarg; /* store the first argument */
+
+ firstarg = sp-2; /* hostname */
+
switch(0) { default: /* try {...} */
/* Set msg/msglen to the data of the message to send */
@@ -7237,21 +7301,26 @@ f_send_udp (svalue_t *sp)
vector_t *v;
svalue_t *svp;
char *cp;
- mp_int j;
+ p_int j;
v = sp->u.vec;
msglen = VEC_SIZE(v);
- cp = msg = alloca(msglen);
- if (!msg)
- break;
+ /* allocate memory and push error handler onto stack */
+ cp = msg = xalloc_with_error_handler(msglen);
+ if (!msg) {
+ errorf("Out of memory (%zu bytes) in send_udp() for "
+ "temporary buffer.\n", msglen);
+ }
+ sp = inter_sp;
+
svp = &v->item[0];
- for (j = (mp_int)msglen; --j >= 0; )
+ for (j = (p_int)msglen; --j >= 0; )
*cp++ = (char)(*svp++).u.number;
}
/* Is this call valid? */
- if (!privilege_violation(STR_SEND_UDP, sp-2, sp))
+ if (!privilege_violation(STR_SEND_UDP, firstarg, firstarg + 2))
break;
if (udp_s < 0)
@@ -7262,16 +7331,17 @@ f_send_udp (svalue_t *sp)
{
size_t adrlen;
- adrlen = mstrsize((sp-2)->u.str);
- to_host = alloca(adrlen+1);
+ adrlen = mstrsize(firstarg->u.str);
+ /* as there are no runtime error raised below, we just xallocate
+ * and don't bother with an error handler. */
+ to_host = xalloc(adrlen+1);
if (!to_host)
{
- inter_sp = sp;
- errorf("Out of stack (%lu bytes) for host address\n"
- , (unsigned long)(adrlen+1));
+ errorf("Out of memory (%zu bytes) in send_udp() for host address\n"
+ , (adrlen+1));
/* NOTREACHED */
}
- memcpy(to_host, get_txt((sp-2)->u.str), adrlen);
+ memcpy(to_host, get_txt(firstarg->u.str), adrlen);
to_host[adrlen] = '\0';
}
to_port = (sp-1)->u.number;
@@ -7302,7 +7372,7 @@ f_send_udp (svalue_t *sp)
if (hp->h_addrtype == AF_INET)
{
- CREATE_IPV6_MAPPED(name.sin_addr, (u_int32_t)hp->h_addr_list[0]);
+ CREATE_IPV6_MAPPED(&name.sin_addr, (u_int32_t)hp->h_addr_list[0]);
}
name.sin_family = AF_INET6;
#endif /* USE_IPV6 */
@@ -7317,14 +7387,18 @@ f_send_udp (svalue_t *sp)
break;
ret = 1;
}
-
- /* Return the result */
-
- free_svalue(sp);
- free_svalue(--sp);
- free_svalue(--sp);
+ /* Cleanup - an allocated buffer for the message will be on the stack
+ * above the arguments, therefore clean everything from the first argument
+ * (including) to sp.
+ */
+ sp = pop_n_elems((sp-firstarg)+1, sp);
+ xfree(to_host);
+
+ /*Return the result */
+ sp++;
put_number(sp, ret);
return sp;
+
} /* f_send_udp() */
/*-------------------------------------------------------------------------*/
@@ -7350,7 +7424,7 @@ f_set_buffer_size (svalue_t *sp)
if (sp->u.number > SET_BUFFER_SIZE_MAX)
{
- errorf("Bad arg 1 to set_buffer_size(): value %ld exceeds maximum %ld\n"
+ errorf("Bad arg 1 to set_buffer_size(): value %"PRIdPINT" exceeds maximum %ld\n"
, sp->u.number, (long) SET_BUFFER_SIZE_MAX);
/* NOTREACHED */
return sp;
@@ -7437,7 +7511,7 @@ f_binary_message (svalue_t *sp)
size = VEC_SIZE(sp[-1].u.vec);
msg = alloc_mstring(size);
if (!msg)
- fatal("Stack overflow in binary_message()");
+ errorf("Out of memory (%zu bytes) in binary_message()",size);
for (i = (mp_int)size, svp = sp[-1].u.vec->item, p = get_txt(msg)
; --i >= 0; svp++)
{
@@ -7515,6 +7589,7 @@ f_binary_message (svalue_t *sp)
}
if (wrote == -1)
{
+ /* TODO: Use strerror()? */
switch(errno)
{
case EINTR:
@@ -7827,7 +7902,7 @@ v_input_to (svalue_t *sp, int num_arg)
if (arg[2].type != T_STRING && arg[2].type != T_CLOSURE)
{
- vefun_bad_arg(3, arg-1);
+ vefun_bad_arg(3, sp);
/* NOTREACHED */
}
}
@@ -7896,7 +7971,7 @@ v_input_to (svalue_t *sp, int num_arg)
if (error_index >= 0)
{
free_input_to(it);
- vefun_bad_arg(error_index, arg-1);
+ vefun_bad_arg(error_index + num_arg - extra + 1, arg-1);
/* NOTREACHED */
return arg-1;
}
@@ -8081,6 +8156,7 @@ v_find_input_to (svalue_t *sp, int num_arg)
break;
default:
+ /* TODO: Wouldn't errorf() suffice? */
fatal("Unsupported argument type %d\n", arg[1].type);
break;
}
@@ -8235,6 +8311,7 @@ v_remove_input_to (svalue_t *sp, int num_arg)
break;
default:
+ /* TODO: Wouldn't errorf() suffice? */
fatal("Unsupported argument type %d\n", arg[1].type);
break;
}
@@ -8270,6 +8347,7 @@ v_remove_input_to (svalue_t *sp, int num_arg)
ip->noecho |= NOECHO_STALE;
set_noecho(ip, ip->input_to ? ip->input_to->noecho : ip->noecho
, ip->input_to ? ip->input_to->local : MY_FALSE
+ , MY_FALSE
);
}
@@ -8469,7 +8547,7 @@ f_query_mud_port (svalue_t *sp)
{
if (sp->u.number < -1 || sp->u.number >= numports)
{
- errorf("Bad arg 1 to query_mud_port(): value %ld out of range.\n"
+ errorf("Bad arg 1 to query_mud_port(): value %"PRIdPINT" out of range.\n"
, sp->u.number);
/* NOTREACHED */
}
@@ -8491,6 +8569,15 @@ f_query_mud_port (svalue_t *sp)
} /* f_query_mud_port() */
/*-------------------------------------------------------------------------*/
+
+
+static inline void translate_bit(char c, int i, int length, string_t *rc, unsigned int bitno)
+/* static helper function to translatin bits to characters in get_charset */
+{
+ if (c & (1 << bitno))
+ get_txt(rc)[length++] = (char)(i * 8 + bitno);
+} /* translate_bit */
+
static void
get_charset (svalue_t * sp, p_int mode, char charset[32])
@@ -8504,7 +8591,7 @@ get_charset (svalue_t * sp, p_int mode, char charset[32])
switch (mode)
{
default:
- fatal("(get_charset): Illegal mode value %ld\n", mode);
+ fatal("(get_charset): Illegal mode value %"PRIdPINT"\n", mode);
/* NOTREACHED */
break;
@@ -8560,19 +8647,14 @@ get_charset (svalue_t * sp, p_int mode, char charset[32])
{
char c = charset[i];
-#define TRANSLATE(bitno) \
- if (c & (1 << bitno)) \
- get_txt(rc)[length++] = (char)(i * 8 + bitno);
-
- TRANSLATE(0);
- TRANSLATE(1);
- TRANSLATE(2);
- TRANSLATE(3);
- TRANSLATE(4);
- TRANSLATE(5);
- TRANSLATE(6);
- TRANSLATE(7);
-#undef TRANSLATE
+ translate_bit(c, i, length, rc, 0);
+ translate_bit(c, i, length, rc, 1);
+ translate_bit(c, i, length, rc, 2);
+ translate_bit(c, i, length, rc, 3);
+ translate_bit(c, i, length, rc, 4);
+ translate_bit(c, i, length, rc, 5);
+ translate_bit(c, i, length, rc, 6);
+ translate_bit(c, i, length, rc, 7);
}
put_string(sp, rc);
@@ -8608,9 +8690,9 @@ f_get_combine_charset (svalue_t *sp)
mode = sp->u.number;
if (mode != CHARSET_VECTOR && mode != CHARSET_STRING)
{
- errorf("Bad arg 1 to get_combine_charset(): %ld, "
+ errorf("Bad arg 1 to get_combine_charset(): %"PRIdPINT", "
"expected CHARSET_VECTOR (%d) or CHARSET_STRING (%d)\n"
- , (long) mode, CHARSET_VECTOR, CHARSET_STRING);
+ , mode, CHARSET_VECTOR, CHARSET_STRING);
/* NOTREACHED */
return sp;
}
@@ -8659,8 +8741,8 @@ f_set_combine_charset (svalue_t *sp)
i = 0;
if (sp->type == T_POINTER && (i = (mp_int)VEC_SIZE(sp->u.vec)) > 32)
{
- errorf("Bad arg 1 to set_combine_charset(): int[] too long (%ld)\n"
- , (long)i);
+ errorf("Bad arg 1 to set_combine_charset(): int[] too long (%"PRIdMPINT")\n"
+ , i);
/* NOTREACHED */
return sp;
}
@@ -8732,10 +8814,10 @@ f_get_connection_charset (svalue_t *sp)
if (mode != CHARSET_VECTOR && mode != CHARSET_STRING
&& mode != CHARSET_QUOTE_IAC)
{
- errorf("Bad arg 1 to get_connection_charset(): %ld, "
+ errorf("Bad arg 1 to get_connection_charset(): %"PRIdPINT", "
"expected CHARSET_VECTOR (%d), _STRING (%d), "
"or _QUOTE_IAC (%d)\n"
- , (long) mode, CHARSET_VECTOR, CHARSET_STRING, CHARSET_QUOTE_IAC);
+ , mode, CHARSET_VECTOR, CHARSET_STRING, CHARSET_QUOTE_IAC);
/* NOTREACHED */
return sp;
}
@@ -8791,8 +8873,8 @@ f_set_connection_charset (svalue_t *sp)
i = 0;
if (sp[-1].type == T_POINTER && (i = (mp_int)VEC_SIZE(sp[-1].u.vec)) > 32)
{
- errorf("Bad arg 1 to set_connection_charset(): array too big (%ld)\n"
- , i);
+ errorf("Bad arg 1 to set_connection_charset(): array too big (%"
+ PRIdMPINT")\n", i);
/* NOTREACHED */
return sp;
}
@@ -8892,8 +8974,8 @@ f_set_prompt (svalue_t *sp)
if (!str)
{
inter_sp = sp;
- errorf("(set_prompt) Out of memory (%lu bytes) for prompt\n"
- , (unsigned long) mstrsize(sp->u.str));
+ errorf("(set_prompt) Out of memory (%zu bytes) for prompt\n"
+ , mstrsize(sp->u.str));
}
else
{
@@ -8915,7 +8997,7 @@ f_set_prompt (svalue_t *sp)
assign_svalue(sp, prompt);
else
{
- errorf("Bad int arg 1 to set_prompt(): got %ld, expected 0 or -1.\n"
+ errorf("Bad int arg 1 to set_prompt(): got %"PRIdPINT", expected 0 or -1.\n"
, sp->u.number);
/* NOTREACHED */
return sp;
@@ -9151,7 +9233,7 @@ f_enable_telnet (svalue_t *sp)
put_number(sp, rc);
return sp;
} /* f_enable_telnet() */
-
+
/*-------------------------------------------------------------------------*/
#ifdef USE_EXPERIMENTAL
svalue_t *
diff --git a/src/comm.h b/src/comm.h
index c441001..b407049 100644
--- a/src/comm.h
+++ b/src/comm.h
@@ -156,6 +156,10 @@ struct input_to_s {
*
* When changing struct members, take care that you don't introduce
* unnecessary padding.
+ *
+ * If the CBool members should ever be changed to C99's _Bool, take care of
+ * checking who is relying on a specific size (e.g. some printf())
+ *
*/
struct interactive_s {
@@ -416,7 +420,7 @@ extern void add_message VARPROT((const char *, ...), printf, 1, 2);
extern void flush_all_player_mess(void);
extern Bool get_message(char *buff, size_t *len);
extern void remove_interactive(object_t *ob, Bool force);
-extern void set_noecho(interactive_t *i, char noecho, Bool local_change);
+extern void set_noecho(interactive_t *i, char noecho, Bool local_change, Bool external);
extern int find_no_bang (interactive_t *ip);
extern Bool call_function_interactive(interactive_t *i, char *str, size_t len);
extern void remove_all_players(void);
diff --git a/src/driver.h b/src/driver.h
index 553ffef..e144700 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -14,6 +14,9 @@
#include "config.h"
+/* Include the portability headers */
+#include "port.h"
+
/* TODO: Some TODO defines */
/* NO_NEGATIVE_RANGES: If defined, assignments to negative ranges
@@ -46,17 +49,26 @@
# define GC_SUPPORT 1
#endif
+
/* Do some of the selected packages require special treatment? */
-/* SQLite in the threadsafe mode needs a normal malloc() */
-#if defined(SBRK_OK) && defined(USE_SQLITE)
-# undef SBRK_OK
-#endif
+/* ptmalloc only works correctly with SBRK_OK right now. */
+#ifdef MALLOC_ptmalloc
+# ifndef SBRK_OK
+# define SBRK_OK
+# endif
+#else // no ptmalloc
+/* SQLite in the threadsafe mode needs a normal malloc() if the allocator is
+ * not ptmalloc*/
+# if defined(SBRK_OK) && defined(USE_SQLITE) && defined(SQLITE3_USES_PTHREADS)
+# undef SBRK_OK
+# endif
+/* PTHREADS need a normal malloc() if the allocator is not ptmalloc */
+# if defined(SBRK_OK) && defined(USE_PTHREADS)
+# undef SBRK_OK
+# endif
+#endif // MALLOC_ptmalloc
-/* PTHREADS need a normal malloc() */
-#if defined(SBRK_OK) && (defined(USE_PTHREADS) || defined(SQLITE3_USES_PTHREADS))
-# undef SBRK_OK
-#endif
/* When we have allocation tracing, the allocator annotates every
* allocation with the source filename and line where the allocation
@@ -131,9 +143,6 @@
# define __IPV6__
#endif
-/* Include the portability headers */
-#include "port.h"
-
/* TODO: this ctype-stuff might go into lex.h (impl in efun_defs.c) */
#define _MCTe 0x01 /* escaped character in save/restore object. */
#define _MCTd 0x02 /* numeric digit */
@@ -166,4 +175,10 @@ extern unsigned char _my_ctype[];
#define MIN(a,b) (((a)<(b))?(a):(b))
#endif /* MIN */
+/* For the use of mudlib/sys/debug_info.h.
+ */
+#ifdef EVAL_COST_TRACE
+#define __EVAL_COST_TRACE__
+#endif
+
#endif /* DRIVER_H__ */
diff --git a/src/dumpstat.c b/src/dumpstat.c
index 1e93bd9..17c8ec7 100644
--- a/src/dumpstat.c
+++ b/src/dumpstat.c
@@ -346,7 +346,7 @@ dumpstat (string_t *fname)
overhead += sizeof (object_t);
- fprintf(f, "%-20s %5ld (%5ld) ref %2ld %s "
+ fprintf(f, "%-20s %5"PRIdMPINT" (%5"PRIdMPINT") ref %2"PRIdPINT" %s "
, get_txt(ob->name)
, compsize + overhead, totalsize + overhead
, ob->ref
@@ -360,14 +360,15 @@ dumpstat (string_t *fname)
fprintf(f, "-- ");
if (ob->gigaticks)
- fprintf(f, " (%lu%09lu)", ob->gigaticks, ob->ticks);
+ fprintf(f, " (%"PRIuMPINT"%09"PRIuMPINT")",
+ (mp_uint)ob->gigaticks, (mp_uint)ob->ticks);
else
- fprintf(f, " (%lu)", ob->ticks);
+ fprintf(f, " (%"PRIuMPINT")", (mp_uint)ob->ticks);
fprintf(f, " %s",
swapstrings[(O_PROG_SWAPPED(ob)?1:0) | (O_VAR_SWAPPED(ob)?2:0)]
);
tm = localtime((time_t *)&ob->load_time);
- strftime(timest, sizeof(timest)-1, "%Y.%m.%d-%H:%M:%S", tm);
+ strftime(timest, sizeof(timest), "%Y.%m.%d-%H:%M:%S", tm);
fprintf(f, " %s\n", timest);
}
fclose(f);
@@ -406,7 +407,7 @@ dumpstat_dest(string_t *fname)
if (!(ob->flags & O_DESTRUCTED)) /* TODO: Can't happen */
continue;
#endif
- fprintf(f, "%-20s ref %2ld NEW\n"
+ fprintf(f, "%-20s ref %2"PRIdPINT" NEW\n"
, get_txt(ob->name)
, ob->ref
);
@@ -418,7 +419,7 @@ dumpstat_dest(string_t *fname)
if (!(ob->flags & O_DESTRUCTED)) /* TODO: Can't happen */
continue;
#endif
- fprintf(f, "%-20s ref %2ld\n"
+ fprintf(f, "%-20s ref %2"PRIdPINT"\n"
, get_txt(ob->name)
, ob->ref
);
diff --git a/src/ed.c b/src/ed.c
index 3c19a85..90181d9 100644
--- a/src/ed.c
+++ b/src/ed.c
@@ -362,7 +362,7 @@ static void count_blanks(int line);
static void _count_blanks(char *str, int blanks);
static LINE *getptr(int num);
static void putcntl(char c);
-static void prntln(char *str, int vflg, int lin);
+static void prntln(char *str, Bool vflg, int lin);
static regexp_t *optpat(void);
/*-------------------------------------------------------------------------*/
@@ -2917,6 +2917,7 @@ docmd (Bool glob)
free_mstring(fptr);
return err;
}
+ free_mstring(fptr);
P_FCHANGED = TRUE;
break;
@@ -3257,8 +3258,12 @@ clear_ed_buffer_refs (ed_buffer_t *b)
{
object_t *ob;
+ if (b->fname)
+ clear_string_ref(b->fname);
+
if (b->exit_fn)
{
+ clear_string_ref(b->exit_fn);
if ( NULL != (ob = b->exit_ob) )
{
if (ob->flags & O_DESTRUCTED)
diff --git a/src/efuns.c b/src/efuns.c
index bfe633f..d3f371e 100644
--- a/src/efuns.c
+++ b/src/efuns.c
@@ -110,6 +110,7 @@
#include "comm.h"
#include "dumpstat.h"
#include "exec.h"
+#include "gcollect.h"
#include "heartbeat.h"
#include "interpret.h"
#include "lex.h"
@@ -137,6 +138,8 @@
#include "wiz_list.h"
#include "xalloc.h"
+#include "i-eval_cost.h"
+
#include "../mudlib/sys/debug_info.h"
#include "../mudlib/sys/driver_hook.h"
#include "../mudlib/sys/objectinfo.h"
@@ -144,6 +147,11 @@
#include "../mudlib/sys/strings.h"
#include "../mudlib/sys/time.h"
+/* Variables */
+string_t *last_ctime_result = NULL;
+ /* points to the result of the last f_ctime() call. If the caller asks for
+ * the same timestamp, it will be returned. */
+
/* Forward declarations */
static void copy_svalue (svalue_t *dest, svalue_t *, struct pointer_table *, int);
@@ -424,12 +432,20 @@ v_md5 (svalue_t *sp, int num_arg)
if (iterations < 1)
{
- errorf("Bad argument 2 to md5(): expected a number > 0, but got %ld\n"
- , (long) iterations);
+ errorf("Bad argument 2 to md5(): expected a number > 0, but got %"
+ PRIdPINT"\n", iterations);
/* NOTREACHED */
return sp;
}
+ if (add_eval_cost_n(10, iterations))
+ {
+ free_svalue(sp);
+ put_number(sp, 0);
+
+ // The interpreter loop will catch the exceeded evaluation cost.
+ return sp;
+ }
if (sp->type == T_POINTER)
{
@@ -569,13 +585,20 @@ v_sha1 (svalue_t *sp, int num_arg)
if (iterations < 1)
{
- errorf("Bad argument 2 to md5(): expected a number > 0, but got %ld\n"
- , (long) iterations);
+ errorf("Bad argument 2 to sha1(): expected a number > 0, but got %"
+ PRIdPINT"\n", iterations);
/* NOTREACHED */
return sp;
}
+ if (add_eval_cost_n(10, iterations))
+ {
+ free_svalue(sp);
+ put_number(sp, 0);
+ /* The interpreter loop will catch the exceeded evaluation cost. */
+ return sp;
+ }
if (sp->type == T_POINTER)
{
@@ -676,7 +699,7 @@ f_regexp (svalue_t *sp)
string_t * pattern; /* The pattern passed in */
int opt; /* The RE options passed in */
int rc; /* Resultcode from the rx_exec() call */
- mp_int i;
+ mp_int i, j;
v = (sp-2)->u.vec;
pattern = (sp-1)->u.str;
@@ -700,16 +723,18 @@ f_regexp (svalue_t *sp)
/* Check every string in if it matches and set res[]
* accordingly.
+ * Allocate memory and push error handler on the stack.
*/
- res = alloca(v_size * sizeof(*res));
+ res = xalloc_with_error_handler(v_size * sizeof(*res));
if (!res)
{
free_regexp(reg);
- inter_sp = sp;
- errorf("Stack overflow in regexp()");
+ errorf("Out of memory (%"PRIdMPINT" bytes) in regexp()",
+ v_size * sizeof(*res));
/* NOTREACHED */
return sp;
}
+ sp = inter_sp;
for (num_match = i = 0; i < v_size; i++) {
string_t *line;
@@ -719,8 +744,14 @@ f_regexp (svalue_t *sp)
if (v->item[i].type != T_STRING)
continue;
- eval_cost++;
- total_evalcost++;
+ if (add_eval_cost(1))
+ {
+ /* Evalution cost exceeded: we abort matching at this point
+ * and let the interpreter detect the exception.
+ */
+ break;
+ }
+
line = v->item[i].u.str;
rc = rx_exec(reg, line, 0);
if (rc == 0)
@@ -729,7 +760,6 @@ f_regexp (svalue_t *sp)
{
const char * emsg = rx_error_message(rc, reg);
free_regexp(reg);
- inter_sp = sp;
errorf("regexp: %s\n", emsg);
/* NOTREACHED */
return NULL;
@@ -741,15 +771,16 @@ f_regexp (svalue_t *sp)
/* Create the result vector and copy the matching lines */
ret = allocate_array(num_match);
- for (num_match=i=0; i < v_size; i++) {
+ for (j=i=0; i < v_size && j < num_match; i++) {
if (!res[i])
continue;
- assign_svalue_no_free(&ret->item[num_match], &v->item[i]);
- num_match++;
+ assign_svalue_no_free(&ret->item[j++], &v->item[i]);
}
-
+ /* Free regexp and the intermediate buffer res by freeing the error
+ * handler. */
free_regexp(reg);
- }while(0);
+ free_svalue(sp--);
+ } while(0);
free_svalue(sp--);
free_svalue(sp--);
@@ -763,6 +794,43 @@ f_regexp (svalue_t *sp)
} /* f_regexp() */
/*-------------------------------------------------------------------------*/
+/* The found delimiter matches in f_regexplode() are kept in a list of these
+ * structures.
+ */
+struct regexplode_match {
+ size_t start, end; /* Start and end of the match in text */
+ struct regexplode_match *next; /* Next list element */
+};
+
+/* We need a special error handling for f_reg_explode(). It allocates a
+ * chained list of regexplode_match structures in a mempool and the compiled
+ * regexp which we have to free.
+ */
+struct regexplode_cleanup_s {
+ svalue_t sval;
+ regexp_t *reg;
+ Mempool matchmempool;
+};
+
+static void
+regexplode_error_handler( svalue_t * arg)
+/* The error handler: delete the mempool and free the compiled regexp.
+ * Note: it is static, but the compiler will have to emit a function and
+ * symbol for this because the address of the function is taken and it is
+ * therefore not suitable to be inlined.
+ */
+{
+ struct regexplode_cleanup_s *handler = (struct regexplode_cleanup_s *)arg;
+
+ if (handler->reg)
+ free_regexp(handler->reg);
+
+ if (handler->matchmempool) {
+ mempool_delete(handler->matchmempool);
+ }
+ xfree(handler);
+} /* regexplode_error_handler() */
+
svalue_t *
f_regexplode (svalue_t *sp)
@@ -779,13 +847,6 @@ f_regexplode (svalue_t *sp)
*/
{
- /* The found delimiter matches are kept in a list of these
- * structures which are allocated on the stack.
- */
- struct regexplode_match {
- size_t start, end; /* Start and end of the match in text */
- struct regexplode_match *next; /* Next list element */
- };
string_t *text; /* Input string */
string_t *pattern; /* Delimiter pattern from the vm stack */
@@ -796,25 +857,47 @@ f_regexplode (svalue_t *sp)
vector_t *ret; /* Result vector */
svalue_t *svp; /* Next element in ret to fill in */
int num_match; /* Number of matches */
- int arraysize; /* Size of result array */
+ p_int arraysize; /* Size of result array */
int opt; /* RE options */
int rc; /* Result from rx_exec() */
size_t start; /* Start position for match */
+ Mempool pool; /* Mempool for the list of matches */
+ /* cleanup structure holding the head of chain of matches */
+ struct regexplode_cleanup_s *cleanup;
+
/* Get the efun arguments */
-
text = sp[-2].u.str;
pattern = sp[-1].u.str;
opt = (int)sp->u.number;
+
+ /* allocate space for cleanup structure. */
+ cleanup = xalloc(sizeof(*cleanup));
+ if (!cleanup)
+ errorf("Out of memory (%zu bytes) for cleanup structure in "
+ "regexplode().\n",sizeof(*cleanup));
+ /* create mempool */
+ pool = new_mempool(size_mempool(sizeof(*matches)));
+ if (!pool)
+ {
+ xfree(cleanup);
+ errorf("Out of memory (%zu) for mempool in regexplode().\n",
+ sizeof(*matches));
+ }
+ cleanup->matchmempool = pool;
+ cleanup->reg = NULL;
+ /* push error handler above the args on the stack */
+ sp = push_error_handler(regexplode_error_handler, &(cleanup->sval));
+
reg = rx_compile(pattern, opt, MY_FALSE);
if (reg == 0) {
- inter_sp = sp;
errorf("Unrecognized search pattern");
/* NOTREACHED */
return sp;
}
-
+ cleanup->reg = reg;
+
/* Loop over , repeatedly matching it against the pattern,
* until all matches have been found and recorded.
*/
@@ -824,22 +907,30 @@ f_regexplode (svalue_t *sp)
matchp = &matches;
while ((rc = rx_exec(reg, text, start)) > 0)
{
- eval_cost++;
- total_evalcost++;
- match = (struct regexplode_match *)alloca(sizeof *match);
+ if (add_eval_cost(1))
+ {
+ /* Evaluation cost exceeded: terminate matching early, but
+ * let the interpreter loop handle the exception.
+ */
+ rc = 0;
+ break;
+ }
+
+ match = mempool_alloc(pool, sizeof *match);
if (!match)
{
- free_regexp(reg);
- inter_sp = sp;
- errorf("Stack overflow in regexplode()");
+ errorf("Out of memory (%zu bytes) in regexplode().\n",
+ sizeof(*match));
/* NOTREACHED */
return sp;
}
rx_get_match(reg, text, &(match->start), &(match->end));
start = match->end;
+ /* add match to the match list */
*matchp = match;
matchp = &match->next;
num_match++;
+
if (start == mstrsize(text)
|| (match->start == start && ++start == mstrsize(text)) )
break;
@@ -848,8 +939,6 @@ f_regexplode (svalue_t *sp)
if (rc < 0) /* Premature abort on error */
{
const char * emsg = rx_error_message(rc, reg);
- free_regexp(reg);
- inter_sp = sp;
errorf("regexp: %s\n", emsg);
/* NOTREACHED */
return NULL;
@@ -864,17 +953,14 @@ f_regexplode (svalue_t *sp)
arraysize = 2 * num_match + 1;
if (max_array_size && arraysize > (long)max_array_size-1 ) {
- free_regexp(reg);
- inter_sp = sp;
- errorf("Illegal array size");
+ errorf("Illegal array size: %"PRIdPINT".\n", arraysize);
/* NOTREACHED */
return sp;
}
ret = allocate_array(arraysize);
- /* Walk down the list of matches, extracting the
- * text parts and matched delimiters, copying them
- * into ret.
+ /* Walk down the list of matches, extracting the text parts and matched
+ * delimiters, copying them into ret.
*/
svp = ret->item;
start = 0;
@@ -886,11 +972,13 @@ f_regexplode (svalue_t *sp)
len = match->start - start;
if (len)
{
- memsafe(txt = mstr_extract(text, start, match->start-1), (size_t)len, "text before delimiter");
+ memsafe(txt = mstr_extract(text, start, match->start-1),
+ (size_t)len, "text before delimiter");
put_string(svp, txt);
}
else
put_ref_string(svp, STR_EMPTY);
+
svp++;
/* Copy the matched delimiter */
@@ -904,6 +992,7 @@ f_regexplode (svalue_t *sp)
}
else
put_ref_string(svp, STR_EMPTY);
+
svp++;
}
@@ -925,15 +1014,12 @@ f_regexplode (svalue_t *sp)
put_ref_string(svp, STR_EMPTY);
}
- /* Cleanup */
- free_regexp(reg);
- free_svalue(sp);
- sp--;
- free_svalue(sp);
- sp--;
- free_svalue(sp);
+ /* Cleanup: free error handler and 3 arguments. Freeing the error handler
+ * will free the regexp and the chain of matches. */
+ sp = pop_n_elems(4, sp);
/* Return the result */
+ sp++;
put_array(sp, ret);
return sp;
} /* f_regexplode() */
@@ -1062,8 +1148,7 @@ f_regreplace (svalue_t *sp)
rcp->reg = reg;
rcp->matches = NULL;
- push_error_handler(regreplace_cleanup, &(rcp->head));
- sp = inter_sp;
+ sp = push_error_handler(regreplace_cleanup, &(rcp->head));
/* Loop over , repeatedly matching it against the pattern,
* until all matches have been found and recorded.
@@ -1074,8 +1159,15 @@ f_regreplace (svalue_t *sp)
reslen = 0;
while ((rc = rx_exec(reg, text, start)) > 0)
{
- eval_cost++;
- total_evalcost++;
+ if (add_eval_cost(1))
+ {
+ /* Evaluation cost exceeded: terminate the matching early,
+ * but let the interpreter handle the exception.
+ */
+ rc = 0;
+ break;
+ }
+
xallocate(match, sizeof(*match), "regreplace match structure");
rx_get_match(reg, text, &(match->start), &(match->end));
match->sub = NULL;
@@ -1289,9 +1381,9 @@ v_regmatch (svalue_t *sp, int num_arg)
startpos = (size_t)argp[3].u.number;
if (startpos > mstrsize(text))
{
- errorf("regmatch(): Start index out of range: %ld, "
- "should be in [0..%ld]\n"
- , (long)argp[3].u.number, (long)mstrsize(text)
+ errorf("regmatch(): Start index out of range: %zu, "
+ "should be in [0..%zu]\n",
+ startpos, mstrsize(text)
);
/* NOTREACHED */
startpos = 0;
@@ -1556,7 +1648,7 @@ v_trim (svalue_t *sp, int num_arg)
= { '\t', ' ', '\0' };
char *strip; /* String of characters to strip */
size_t strip_l; /* Length of *strip */
- int where;
+ p_int where;
/* Get and test the arguments */
argp = sp - num_arg + 1;
@@ -1569,20 +1661,21 @@ v_trim (svalue_t *sp, int num_arg)
{
where = argp[1].u.number;
if (!where)
- where = TRIM_LEFT|TRIM_RIGHT;
- if (where & ~(TRIM_LEFT|TRIM_RIGHT))
- errorf("Bad argument 2 to trim(): illegal value %ld\n", (long)where);
+ where = TRIM_BOTH;
+ if (where > TRIM_BOTH)
+ errorf("Bad argument 2 to trim(): illegal value %"PRIdPINT"\n",
+ where);
}
else
- where = TRIM_LEFT|TRIM_RIGHT;
+ where = TRIM_BOTH;
if (num_arg > 2)
{
if (argp[2].type == T_NUMBER)
{
if (argp[2].u.number <= 0 || argp[2].u.number >= 1 << CHAR_BIT)
- errorf("Bad argument 3 to trim(): %ld is not a character\n"
- , argp[2].u.number);
+ errorf("Bad argument 3 to trim(): %"PRIdPINT
+ " is not a character\n", argp[2].u.number);
def_ch[0] = (char)argp[2].u.number;
def_ch[1] = '\0';
strip = def_ch;
@@ -2359,10 +2452,10 @@ e_terminal_colour ( string_t * text, mapping_t * map, svalue_t * cl
if (pt - tmpmem + ((l < 0) ? -l : l) >= (ptrdiff_t)tmpmem_size)
{
- errorf("Partial string '%s' too long (%ld+%ld >= %ld).\n"
+ errorf("Partial string '%s' too long (%td+%"PRIdPINT" >= %zu).\n"
, p
- , (long)(pt - tmpmem), (long)((l < 0) ? -l : l)
- , (long)tmpmem_size);
+ , (ptrdiff_t)(pt - tmpmem), ((l < 0) ? -l : l)
+ , tmpmem_size);
/* NOTREACHED */
return NULL;
}
@@ -2573,12 +2666,12 @@ e_terminal_colour ( string_t * text, mapping_t * map, svalue_t * cl
&& (!indent_overflows || (long)(cp - get_txt(deststr)) != wrap)
) {
fatal("Length miscalculated in terminal_colour()\n"
- " Expected: %i (or %i) Was: %ld\n"
+ " Expected: %i (or %i) Was: %td\n"
" In string: %.*s\n"
" Out string: %.*s\n"
" Indent: %i Wrap: %i, indent overflow: %s\n"
, j, wrap
- , (long)(cp - get_txt(deststr))
+ , (ptrdiff_t)(cp - get_txt(deststr))
, (int)mstrsize(text), get_txt(text)
, (int)mstrsize(deststr), get_txt(deststr)
, indent, wrap
@@ -2729,10 +2822,11 @@ process_value (const char *str, Bool original)
*/
if (original)
{
- func = alloca(strlen(str)+1);
+ /* allocate memory and push error handler */
+ func = xalloc_with_error_handler(strlen(str)+1);
if (!func)
- errorf("Out of stack memory (%lu bytes)\n"
- , (unsigned long)(strlen(str)+1));
+ errorf("Out of memory (%zu bytes) in process_value().\n"
+ , strlen(str)+1);
strcpy(func, str);
}
else
@@ -2749,6 +2843,9 @@ process_value (const char *str, Bool original)
*/
if ( NULL == (func2 = find_tabled_str(func)) )
{
+ /* free the error handler if necessary. */
+ if (original)
+ free_svalue(inter_sp--);
return NULL;
}
@@ -2767,6 +2864,9 @@ process_value (const char *str, Bool original)
if (!ob)
{
+ /* free the error handler if necessary. */
+ if (original)
+ free_svalue(inter_sp--);
return NULL;
}
@@ -2785,11 +2885,17 @@ process_value (const char *str, Bool original)
narg++;
}
}
-
- /* Apply the function and see if adequate answer is returned.
- */
+
+ /* Apply the function */
ret = apply(func2, ob, numargs);
+ /* Free func by freeing the error handler (if we allocated func).
+ * Has to be done now, after the arguments have been popped by apply().
+ */
+ if (original)
+ free_svalue(inter_sp--);
+
+ /* see if adequate answer is returned by the apply(). */
if (ret && ret->type == T_STRING)
return ret->u.str;
/* The svalue is stored statically in apply_return_value */
@@ -4097,15 +4203,14 @@ v_clones (svalue_t *sp, int num_arg)
}
#if defined(DYNAMIC_COSTS)
- eval_cost += checked / 100 + found / 256;
- total_evalcost += checked / 100 + found / 256;
+ (void)add_eval_cost(checked / 100 + found / 256);
#endif /* DYNAMIC_COSTS */
/* Create the result and put it onto the stack */
if (max_array_size && found > max_array_size)
{
xfree(ores);
- errorf("Illegal array size: %ld\n", (long)found);
+ errorf("Illegal array size: %zu\n", found);
/* NOTREACHED */
return sp;
}
@@ -4113,8 +4218,8 @@ v_clones (svalue_t *sp, int num_arg)
if (!res)
{
xfree(ores);
- errorf("(clones) Out of memory: array[%lu] for result.\n"
- ,(unsigned long) found);
+ errorf("(clones) Out of memory: array[%zu] for result.\n",
+ found);
/* NOTREACHED */
return sp;
}
@@ -4229,7 +4334,7 @@ v_object_info (svalue_t *sp, int num_args)
} else {}
default:
- errorf("Illegal value %ld for object_info().\n", sp->u.number);
+ errorf("Illegal value %"PRIdPINT" for object_info().\n", sp->u.number);
/* NOTREACHED */
return sp;
@@ -4431,15 +4536,15 @@ v_object_info (svalue_t *sp, int num_args)
#ifdef USE_INVENTORIES
svalue_t *
-f_present_clone (svalue_t *sp)
+v_present_clone (svalue_t *sp, int num_arg)
/* EFUN present_clone()
*
- * object present_clone(string str, object env)
- * object present_clone(object obj, object env)
+ * object present_clone(string str [, object env] [, [int n])
+ * object present_clone(object obj [, object env] [, [int n])
*
- * Search in the inventory of for the first object with the
- * same blueprint as object , resp. for the first object with
+ * Search in the inventory of for the th object with the
+ * same blueprint as object , resp. for the th object with
* the loadname , and return that object.
*
* If not found, 0 is returned.
@@ -4448,27 +4553,79 @@ f_present_clone (svalue_t *sp)
{
string_t * name; /* the shared loadname to look for */
object_t *obj; /* the object under scrutiny */
+ object_t *env; /* the environment to search in */
+ p_int count; /* the object is searched */
- /* Test and get the arguments from the stack */
- if (sp[-1].type == T_STRING)
+ /* Get the arguments */
+ svalue_t *arg = sp - num_arg + 1; // first argument
+ env = current_object; // default
+ count = -1;
+ if (num_arg == 3)
{
- size_t len;
- long i;
+ // if we got 3 args, the third must be a number.
+ count = arg[2].u.number;
+ // but 0 and negative ones make no sense.
+ if (count <= 0)
+ {
+ errorf("Bad argument 3 to present_clone(): got %"PRIdPINT
+ ", expected a positive number.\n",count);
+ return sp; /* NOT REACHED */
+ }
+ free_svalue(sp--);
+ num_arg--;
+ }
+ if (num_arg == 2)
+ {
+ // the second arg may be an object or a number
+ if (arg[1].type == T_NUMBER)
+ {
+ // But it must not be 0 (which is probably a destructed object)
+ // and we don't accept two numbers (as second and third arg)
+ if (arg[1].u.number == 0 || count != -1)
+ {
+ vefun_arg_error(2, T_OBJECT, T_NUMBER, sp);
+ return sp; /* NOTREACHED */
+ }
+ count = arg[1].u.number;
+ if (count < 0)
+ {
+ errorf("Bad argument 2 to present_clone(): got %"PRIdPINT
+ ", expected a positive number or an object.\n",count);
+ return sp; /* NOT REACHED */
+ }
+ }
+ else if (arg[1].type == T_OBJECT)
+ {
+ env = arg[1].u.ob;
+ }
+ free_svalue(sp--);
+ num_arg--;
+ }
+ /* if no number given and count is still ==-1, the for loop below searches
+ * implicitly for the first object */
+
+
+ /* Get the name/object to search for */
+ if (arg->type == T_STRING)
+ {
+ size_t len, i;
char * end;
char * sane_name;
char * name0; /* Intermediate name */
-
- name0 = get_txt(sp[-1].u.str);
-
+ char * tmpbuf; /* intermediate buffer for stripping any #xxxx */
+
+ name0 = get_txt(arg->u.str);
+ tmpbuf = NULL;
+
/* Normalize the given string and check if it is
* in the shared string table. If not, we know that
* there is no blueprint with that name
*/
- /* First, slash of a trailing '#' */
+ /* First, slash off a trailing '#' */
- len = mstrsize((sp-1)->u.str);
- i = (long)len;
+ len = mstrsize(arg->u.str);
+ i = len;
end = name0 + len;
while (--i > 0)
@@ -4481,17 +4638,24 @@ f_present_clone (svalue_t *sp)
/* Not a digit: maybe a '#' */
if ('#' == c && len - i > 1)
{
- name0 = alloca((size_t)i + 1);
- if (!name0)
- errorf("Out of stack memory.\n");
- strncpy(name0, get_txt(sp[-1].u.str), (size_t)i);
+ tmpbuf = xalloc(i + 1);
+ if (!tmpbuf)
+ {
+ errorf("Out of memory (%zu bytes) for temporary "
+ "buffer in present_clone().\n", i+1);
+ }
+ strncpy(tmpbuf, get_txt(arg->u.str), i);
name0[i] = '\0';
}
break; /* in any case */
}
}
-
+ /* if we got a clone name, tmpbuf is filled with the BP name. In any
+ * case, name0 contains now the name to be used. */
+ if (tmpbuf)
+ name0 = tmpbuf;
+
/* Now make the name sane */
sane_name = (char *)make_name_sane(name0, !compat_mode);
@@ -4499,28 +4663,39 @@ f_present_clone (svalue_t *sp)
name = find_tabled_str(sane_name);
else
name = find_tabled_str(name0);
-
+
+ /* tmpbuf (and name0 which might point to the same memory) is unneeded
+ * from now on. Setting both to NULL, just in case somebody uses
+ * them later below. */
+ if (tmpbuf) {
+ xfree(tmpbuf);
+ tmpbuf = name0 = NULL;
+ }
}
- else if (sp[-1].type == T_OBJECT)
+ else if (arg->type == T_OBJECT)
{
- name = sp[-1].u.ob->load_name;
+ name = arg->u.ob->load_name;
}
else
- efun_gen_arg_error(1, sp[-1].type, sp);
+ vefun_exp_arg_error(1, TF_STRING|TF_OBJECT, arg->type, sp);
obj = NULL;
if (name)
{
/* We have a name, now look for the object */
- for (obj = sp->u.ob->contains; obj != NULL; obj = obj->next_inv)
+ for (obj = env->contains; obj != NULL; obj = obj->next_inv)
{
- if (!(obj->flags & O_DESTRUCTED) && name == obj->load_name)
+ /* check for <= is deliberate, count is -1 if no number is
+ * given and then the loop is terminated upon the first object
+ * matching the name. */
+ if (!(obj->flags & O_DESTRUCTED) && name == obj->load_name
+ && --count <= 0)
break;
}
}
- /* Assign the result */
- sp = pop_n_elems(2, sp) + 1;
+ /* Free first argument and assign the result */
+ free_svalue(sp);
if (obj != NULL)
put_ref_object(sp, obj, "present_clone");
else
@@ -4557,8 +4732,8 @@ f_set_is_wizard (svalue_t *sp)
switch (sp->u.number)
{
default:
- errorf("Bad arg to set_is_wizard(): got %ld, expected -1..1\n"
- , sp->u.number);
+ errorf("Bad arg to set_is_wizard(): got %"PRIdPINT
+ ", expected -1..1\n", sp->u.number);
/* NOTREACHED */
case 0: *flagp &= ~O_IS_WIZARD; is_wizard_used = MY_TRUE; break;
case 1: *flagp |= O_IS_WIZARD; is_wizard_used = MY_TRUE; break;
@@ -4762,7 +4937,7 @@ f_abs (svalue_t *sp)
{
if (sp->u.number == PINT_MIN)
{
- errorf("Numeric overflow: abs(%ld)\n", (long)sp->u.number);
+ errorf("Numeric overflow: abs(%"PRIdPINT")\n", sp->u.number);
/* NOTREACHED */
return NULL;
}
@@ -4924,7 +5099,7 @@ f_atan (svalue_t *sp)
{
d = atan((double)(sp->u.number));
if (d < (-DBL_MAX) || d > DBL_MAX)
- errorf("Numeric overflow: atan(%ld)\n", (long)sp->u.number);
+ errorf("Numeric overflow: atan(%"PRIdPINT")\n", sp->u.number);
}
else
{
@@ -5021,7 +5196,7 @@ f_exp (svalue_t *sp)
{
d = exp((double)sp->u.number);
if (d < (-DBL_MAX) || d > DBL_MAX)
- errorf("Numeric overflow: exp(%ld)\n", (long)sp->u.number);
+ errorf("Numeric overflow: exp(%"PRIdPINT")\n", sp->u.number);
}
else
{
@@ -5341,7 +5516,7 @@ f_to_string (svalue_t *sp)
break;
case T_NUMBER:
- sprintf(buf,"%ld", sp->u.number);
+ sprintf(buf,"%"PRIdPINT, sp->u.number);
if (buf[sizeof(buf)-1] != '\0')
fatal("Buffer overflow in to_string(): "
"int number too big.\n");
@@ -5624,7 +5799,8 @@ v_to_struct (svalue_t *sp, int num_arg)
, typename(argp[1].type));
if (VEC_SIZE(argp->u.vec) > struct_size(argp[1].u.strct))
{
- errorf("Too many elements for struct %s: %ld, expected %ld\n"
+ errorf("Too many elements for struct %s: %"PRIdPINT
+ ", expected %ld\n"
, get_txt(struct_name(argp[1].u.strct))
, VEC_SIZE(argp->u.vec)
, (long)struct_size(argp[1].u.strct)
@@ -5661,7 +5837,8 @@ v_to_struct (svalue_t *sp, int num_arg)
, typename(argp[1].type));
if (VEC_SIZE(argp->u.vec) > struct_size(argp[1].u.strct))
{
- errorf("Too many elements for struct %s: %ld, expected %ld\n"
+ errorf("Too many elements for struct %s: %"PRIdPINT
+ ", expected %ld\n"
, get_txt(struct_name(argp[1].u.strct))
, VEC_SIZE(argp->u.vec)
, (long)struct_size(argp[1].u.strct)
@@ -5954,7 +6131,7 @@ f_copy (svalue_t *sp)
check_map_for_destr(old);
new = copy_mapping(old);
if (!new)
- errorf("(copy) Out of memory: mapping[%lu] for copy.\n"
+ errorf("(copy) Out of memory: mapping[%"PRIdPINT"] for copy.\n"
, MAP_SIZE(old));
free_mapping(old);
sp->u.map = new;
@@ -5969,6 +6146,7 @@ f_copy (svalue_t *sp)
/*-------------------------------------------------------------------------*/
/* Data packet passed to deep_copy_mapping() during a mapping walk.
+ * TODO: change width to p_int, because mappings can have p_int values
*/
struct csv_info {
int depth; /* Depth of the copy procedure */
@@ -6058,8 +6236,7 @@ copy_svalue (svalue_t *dest, svalue_t *src
size = (mp_int)VEC_SIZE(old);
DYN_ARRAY_COST(size);
#if defined(DYNAMIC_COSTS)
- eval_cost += (depth+1) / 10;
- total_evalcost += (depth+1) / 10;
+ (void)add_eval_cost((depth+1) / 10);
#endif
/* Create a new array, assign it to dest, and store
@@ -6121,8 +6298,7 @@ copy_svalue (svalue_t *dest, svalue_t *src
size = (mp_int)struct_size(old);
DYN_ARRAY_COST(size);
#if defined(DYNAMIC_COSTS)
- eval_cost += (depth+1) / 10;
- total_evalcost += (depth+1) / 10;
+ (void)add_eval_cost((depth+1) / 10);
#endif
/* Create a new array, assign it to dest, and store
@@ -6181,14 +6357,13 @@ copy_svalue (svalue_t *dest, svalue_t *src
*/
DYN_MAPPING_COST(size);
#if defined(DYNAMIC_COSTS)
- eval_cost += (depth+1) / 10;
- total_evalcost += (depth+1) / 10;
+ (void)add_eval_cost((depth+1) / 10);
#endif
info.depth = depth+1;
info.width = old->num_values;
new = allocate_mapping(size, info.width);
if (!new)
- errorf("(copy) Out of memory: new mapping[%lu, %u].\n"
+ errorf("(copy) Out of memory: new mapping[%"PRIdMPINT", %u].\n"
, size, info.width);
put_mapping(dest, new);
rec->data = new;
@@ -6641,7 +6816,7 @@ v_member (svalue_t *sp, int num_arg)
if (hasStart && startpos < 0)
{
- errorf("Illegal arg 3 to member(): %ld, expected positive number.\n"
+ errorf("Illegal arg 3 to member(): %"PRIdPINT", expected positive number.\n"
, startpos);
/* NOTREACHED */
return sp;
@@ -6868,7 +7043,7 @@ v_rmember (svalue_t *sp, int num_arg)
if (hasStart && startpos < 0)
{
- errorf("Illegal arg 3 to rmember(): %ld, expected positive number.\n"
+ errorf("Illegal arg 3 to rmember(): %"PRIdPINT", expected positive number.\n"
, startpos);
/* NOTREACHED */
return sp;
@@ -7985,20 +8160,21 @@ v_debug_info (svalue_t *sp, int num_arg)
add_message("O_REPLACED : %s\n",
flags&O_REPLACED ?"TRUE":"FALSE");
#ifdef USE_SET_LIGHT
- add_message("total light : %d\n", ob->total_light);
+ add_message("total light : %d\n", (int)ob->total_light);
#endif
- add_message("time_reset : %ld\n", (long)ob->time_reset);
- add_message("time_of_ref : %ld\n", (long)ob->time_of_ref);
- add_message("ref : %ld\n", ob->ref);
+ add_message("time_reset : %"PRIdMPINT"\n", ob->time_reset);
+ add_message("time_of_ref : %"PRIdMPINT"\n", ob->time_of_ref);
+ add_message("ref : %"PRIdPINT"\n", ob->ref);
#ifdef USE_PARANOIA
- add_message("extra_ref : %ld\n", ob->extra_ref);
+ add_message("extra_ref : %"PRIdPINT"\n", ob->extra_ref);
#endif
if (ob->gigaticks)
- add_message("evalcost : %lu%09lu\n", ob->gigaticks, ob->ticks);
+ add_message("evalcost : %"PRIuMPINT"%09"PRIuMPINT"\n",
+ (mp_uint)ob->gigaticks, (mp_uint)ob->ticks);
else
- add_message("evalcost : %lu\n", ob->ticks);
+ add_message("evalcost : %"PRIdMPINT"\n", (mp_uint)ob->ticks);
#ifdef USE_SWAP
- add_message("swap_num : %ld\n", O_SWAP_NUM(ob));
+ add_message("swap_num : %"PRIdPINT"\n", O_SWAP_NUM(ob));
#endif
add_message("name : '%s'\n", get_txt(ob->name));
add_message("load_name : '%s'\n", get_txt(ob->load_name));
@@ -8034,23 +8210,26 @@ v_debug_info (svalue_t *sp, int num_arg)
errorf("Out of memory: unswap object '%s'\n", get_txt(sp->u.ob->name));
#endif
pg = sp->u.ob->prog;
- add_message("program ref's %3ld\n", pg->ref);
+ add_message("program ref's %3"PRIdPINT"\n", pg->ref);
add_message("Name: '%s'\n", get_txt(pg->name));
- add_message("program size %6ld\n"
- ,(long)(PROGRAM_END(*pg) - pg->program));
- add_message("num func's: %3d (%4ld)\n", pg->num_functions
- , (long)(pg->num_functions * sizeof(uint32) +
- pg->num_function_names * sizeof(short)));
- add_message("num vars: %3d (%4ld)\n", pg->num_variables
- , (long)(pg->num_variables * sizeof(variable_t)));
+ add_message("program size %6"PRIuPINT"\n"
+ ,(p_uint)(PROGRAM_END(*pg) - pg->program));
+ add_message("num func's: %3u (%4"PRIuPINT")\n",
+ (unsigned int)pg->num_functions,
+ (p_uint)(pg->num_functions * sizeof(uint32) +
+ pg->num_function_names * sizeof(short)));
+ add_message("num vars: %3u (%4"PRIuPINT")\n",
+ (unsigned int)pg->num_variables,
+ (p_uint)(pg->num_variables * sizeof(variable_t)));
v1 = program_string_size(pg, &v0, &v2);
- add_message("num strings: %3d (%4ld) : overhead %ld + data %ld (%ld)\n"
- , pg->num_strings
- , (long)(v0 + v1)
- , (long)v0
- , (long)v1
- , (long)v2
+ add_message("num strings: %3u (%4"PRIdMPINT") : overhead %"PRIdMPINT
+ "+ data %"PRIdMPINT" (%"PRIdMPINT")\n"
+ , (unsigned int)pg->num_strings
+ , v0 + v1
+ , v0
+ , v1
+ , v2
);
{
@@ -8065,14 +8244,15 @@ v_debug_info (svalue_t *sp, int num_arg)
)
cnt++;
}
- add_message("num inherits %3d (%4ld)\n", cnt
- , (long)(pg->num_inherited * sizeof(inherit_t)));
+ add_message("num inherits %3d (%4"PRIuPINT")\n", cnt
+ , (p_uint)(pg->num_inherited * sizeof(inherit_t)));
}
- add_message("total size %6ld\n"
+ add_message("total size %6"PRIdPINT"\n"
,pg->total_size);
v1 = data_size(sp->u.ob, &v2);
- add_message("data size %6ld (%6ld)\n", v1, v2);
+ add_message("data size %6"PRIdMPINT" (%6"PRIdMPINT")\n",
+ v1, v2);
break;
}
@@ -8401,14 +8581,19 @@ v_debug_info (svalue_t *sp, int num_arg)
put_string(&res, new_mstring(sbuf.buf));
strbuf_free(&sbuf);
}
+ else if (sp->u.number == DIT_CURRENT_DEPTH)
+ {
+ put_number(&res, control_stack_depth());
+ }
else
- errorf("bad arg 2 to debug_info(): %ld, expected 0..2\n"
+ errorf("bad arg 2 to debug_info(): %"PRIdPINT", expected 0..2\n"
, sp->u.number);
break;
}
default:
- errorf("Bad debug_info() request value: %ld\n", arg[0].u.number);
+ errorf("Bad debug_info() request value: %"PRIdPINT"\n",
+ arg[0].u.number);
/* NOTREACHED */
break;
}
@@ -8438,9 +8623,10 @@ x_gm_localtime (svalue_t *sp, Bool localTime)
if (sp->type != T_NUMBER)
{
if (VEC_SIZE(sp->u.vec) != 2)
- errorf("Bad arg 1 to %s(): Invalid array size %ld, expected 2.\n"
+ errorf("Bad arg 1 to %s(): Invalid array size %"PRIdPINT
+ ", expected 2.\n"
, localTime ? "localtime" : "gmtime"
- , (long)VEC_SIZE(sp->u.vec));
+ , VEC_SIZE(sp->u.vec));
if (sp->u.vec->item[0].type != T_NUMBER)
errorf("Bad arg 1 to %s(): Element 0 is '%s', expected 'int'.\n"
, localTime ? "localtime" : "gmtime"
@@ -8547,6 +8733,7 @@ f_localtime (svalue_t *sp)
/*-------------------------------------------------------------------------*/
svalue_t *
f_mktime (svalue_t *sp)
+#if 1 /* PSYCLPC VERSION */
/* EFUN mktime
* wrapper around libc mktime
* argument format is the same as the output of localtime (E)
@@ -8629,8 +8816,71 @@ f_mktime (svalue_t *sp)
}
return sp;
-} /* f_mktime */
+#else /* NEW LDMUD VERSION */
+/* EFUN mktime()
+ *
+ * int time(int* datum)
+ *
+ * Return the unix timestamp (number of seconds ellapsed since 1. Jan 1970,
+ * 0.0:0 GMT) of the date given in the array datum. datum being an array
+ * like the one localtime() or gmtime() return:
+ * int TM_SEC (0) : Seconds (0..59)
+ * int TM_MIN (1) : Minutes (0..59)
+ * int TM_HOUR (2) : Hours (0..23)
+ * int TM_MDAY (3) : Day of the month (1..31)
+ * int TM_MON (4) : Month of the year (0..11)
+ * int TM_YEAR (5) : Year (e.g. 2001)
+ * int TM_WDAY (6) : Day of the week (Sunday = 0)
+ * int TM_YDAY (7) : Day of the year (0..365)
+ * int TM_ISDST (8) : TRUE: Daylight saving time
+ * TM_YDAY and TM_WDAY are ignored (but must also be ints).
+ *
+ */
+{
+ struct tm * pTm; // broken-down time structure for mktime()
+ time_t clk; // unix timestamp corresponding to datum
+ vector_t * v; // just for convenience, stores argument array
+ int i;
+ v = sp->u.vec;
+ if (VEC_SIZE(v) != 9)
+ errorf("Bad arg 1 to mktime(): Invalid array size %ld, expected 9.\n"
+ , (long)VEC_SIZE(v));
+ // all elements must be ints.
+ for(i=0; iitem[i].type != T_NUMBER)
+ errorf("Bad arg 1 to ctime(): Element %d is '%s', expected 'int'.\n"
+ ,i, efun_arg_typename(v->item[0].type));
+ }
+
+ // create the time structure
+ xallocate(pTm, sizeof(*pTm), "broken-down time structure for mktime()");
+ pTm->tm_sec = v->item[TM_SEC].u.number;
+ pTm->tm_min = v->item[TM_MIN].u.number;
+ pTm->tm_hour = v->item[TM_HOUR].u.number;
+ pTm->tm_mday = v->item[TM_MDAY].u.number;
+ pTm->tm_mon = v->item[TM_MON].u.number;
+ pTm->tm_year = v->item[TM_YEAR].u.number - 1900;
+ pTm->tm_isdst = v->item[TM_ISDST].u.number;
+
+ clk = mktime(pTm);
+
+ // free time structure first
+ xfree(pTm);
+
+ if (clk == -1)
+ errorf("Specified date/time cannot be represented as unix timestamp.\n");
+
+ // free argument and put result.
+ free_svalue(sp);
+ put_number(sp, (p_int)clk);
+
+ return sp;
+#endif
+} /* f_mktime() */
+
+#if 1 /* PSYCLPC VERSION */
/*-------------------------------------------------------------------------*/
svalue_t *
f_strftime (svalue_t *sp)
@@ -8657,6 +8907,7 @@ f_strftime (svalue_t *sp)
return sp;
} /* f_strftime */
+#endif
/*-------------------------------------------------------------------------*/
svalue_t *
@@ -8684,7 +8935,7 @@ f_strptime (svalue_t *sp)
put_number(sp, time_res);
return sp;
-} /* f_strftime */
+} /* f_strptime */
/*-------------------------------------------------------------------------*/
svalue_t *
@@ -8766,7 +9017,7 @@ f_random (svalue_t *sp)
if (sp->u.number <= 0)
sp->u.number = 0;
else
- sp->u.number = (p_int)random_number((uint32)sp->u.number);
+ sp->u.number = (p_int)random_number(sp->u.number);
return sp;
} /* f_random() */
@@ -8807,49 +9058,92 @@ f_ctime(svalue_t *sp)
*
* Interpret the argument clock as number of seconds since Jan,
* 1st, 1970, 0.00 and convert it to a nice date and time string.
+ * In this case, the result string will be cached and tabled.
*
* Alternatively, accept an array of two ints: the first is
* value as in the first form, the second int is the number of
* microseconds elapsed in the current second.
+ * In this case the result will not be cached as the value is very
+ * unlikely to be the same in 2 consecutive calls.
*/
{
char *ts, *cp;
string_t *rc;
+
+ static mp_int last_time = -1; // letzte Uhrzeit
if (sp->type != T_NUMBER)
{
+ /* utime case */
if (VEC_SIZE(sp->u.vec) != 2)
- errorf("Bad arg 1 to ctime(): Invalid array size %ld, expected 2.\n"
- , (long)VEC_SIZE(sp->u.vec));
+ errorf("Bad arg 1 to ctime(): Invalid array size %"PRIdPINT
+ ", expected 2.\n", VEC_SIZE(sp->u.vec));
if (sp->u.vec->item[0].type != T_NUMBER)
errorf("Bad arg 1 to ctime(): Element 0 is '%s', expected 'int'.\n"
, efun_arg_typename(sp->u.vec->item[0].type));
if (sp->u.vec->item[1].type != T_NUMBER)
errorf("Bad arg 1 to ctime(): Element 1 is '%s', expected 'int'.\n"
, efun_arg_typename(sp->u.vec->item[1].type));
+
ts = utime_string( sp->u.vec->item[0].u.number
, sp->u.vec->item[1].u.number);
+
+ /* If the string contains nl characters, extract the substring
+ * before the first one. Else just copy the (volatile) result
+ * we got.
+ */
+ cp = strchr(ts, '\n');
+ if (cp)
+ {
+ int len = cp - ts;
+ memsafe(rc = new_n_mstring(ts, len), len, "ctime() result");
+ }
+ else
+ {
+ memsafe(rc = new_mstring(ts), strlen(ts), "ctime() result");
+ }
}
else
{
- ts = time_string(sp->u.number);
- }
-
- /* If the string contains nl characters, extract the substring
- * before the first one. Else just copy the (volatile) result
- * we got.
- */
- cp = strchr(ts, '\n');
- if (cp)
- {
- int len = cp - ts;
- memsafe(rc = new_n_mstring(ts, len), len, "ctime() result");
- }
- else
- {
- memsafe(rc = new_mstring(ts), strlen(ts), "ctime() result");
- }
+ /* second-precision case */
+ // test if string for this time is cached
+ if (last_time != sp->u.number)
+ {
+ /* cache is outdated */
+ ts = time_fstring(sp->u.number, "%a %b %d %H:%M:%S %Y", 0);
+
+ /* If the string contains nl characters, extract the substring
+ * before the first one. Else just copy the (volatile) result
+ * we got.
+ * Table strings, because they are probably used more then once.
+ */
+ cp = strchr(ts, '\n');
+ if (cp)
+ {
+ int len = cp - ts;
+ memsafe(rc = new_n_tabled(ts, len), len,
+ "ctime() result");
+ }
+ else
+ {
+ memsafe(rc = new_tabled(ts), strlen(ts),
+ "ctime() result");
+ }
+ /* fill cache, free last (invalid) string first and don't forget
+ * to increase the ref count for the cache. */
+ free_mstring(last_ctime_result);
+ last_ctime_result = rc;
+ ref_mstring(rc);
+ last_time = sp->u.number;
+ }
+ else {
+ // return last result (and increase ref count)
+ rc = last_ctime_result;
+ ref_mstring(rc);
+ }
+ } // if (sp->type != T_NUMBER)
+
free_svalue(sp);
put_string(sp, rc);
return sp;
@@ -8915,5 +9209,111 @@ f_utime (svalue_t *sp)
return sp;
} /* f_utime() */
+
+/*-------------------------------------------------------------------------*/
+#if 0 /* NEW LDMUD VERSION */
+svalue_t *
+v_strftime(svalue_t *sp, int num_arg)
+/* EFUN strftime()
+ *
+ * string strftime()
+ * string strftime(string fmt)
+ * string strftime(int clock)
+ * string strftime(string fmt, int clock)
+ * string strftime(string fmt, int clock, int localized)
+ *
+ * Interpret the argument clock as number of seconds since Jan,
+ * 1st, 1970, 0.00 and convert it to a nice date and time string.
+ * The formatstring must be given in fmt and may contain the placeholders
+ * defined in 'man 3 strftime'.
+ * If localized == MY_TRUE then the time string will be created with the
+ * locale set in the environment variable LC_TIME
+ * Defaults: fmt="%c", clock=current_time, localized=MY_TRUE
+ * NOTE: the returned string will have at most 511 Characters.
+ * TODO: Implement proper caching of the result.
+ */
+
+{
+ char *ts;
+ string_t *rc = NULL; // ergebnisstring
+
+ /* Begin of arguments on the stack */
+ svalue_t *arg = sp - num_arg + 1;
+
+ // defaults:
+ Bool localized = MY_TRUE;
+ mp_int clk = current_time;
+ char *cfmt = "%c";
+
+ // evaluate arguments
+ switch(num_arg) {
+ case 3:
+ localized = (Bool)arg[2].u.number;
+ // fall-through
+ case 2:
+ if (arg[1].u.number < 0)
+ errorf("Bad arg 2 to strftime(): got %"PRIdPINT
+ ", expected 0 .. %"PRIdPINT"\n",
+ arg[1].u.number, PINT_MAX);
+ clk = arg[1].u.number;
+ // fall-through
+ case 1:
+ // empty strings default to "%c" => only set fmt if non-empty
+ if (arg[0].type == T_STRING && mstrsize(arg[0].u.str)) {
+ cfmt = get_txt(arg[0].u.str);
+ }
+ else if (arg[0].type == T_NUMBER) {
+ if (num_arg>1) // bei > 1 argument nur strings erlaubt
+ vefun_exp_arg_error(1, TF_STRING, sp->type, sp);
+ else if (arg[0].u.number >= 0)
+ clk = arg[0].u.number;
+ else
+ errorf("Bad argument 1 to strftime(): got %"PRIdPINT
+ ", expected 0 .. %"PRIdPINT"\n",
+ arg[0].u.number, PINT_MAX);
+ }
+ break;
+ }
+
+ ts = time_fstring(clk,cfmt,localized);
+ memsafe(rc = new_tabled(ts), strlen(ts)+sizeof(string_t), "strftime() result");
+
+ sp = pop_n_elems(num_arg, sp);
+ push_string(sp, rc);
+
+ return sp;
+} /* v_strftime() */
+#endif
+
/***************************************************************************/
+/*-------------------------------------------------------------------------*/
+#ifdef GC_SUPPORT
+
+void
+clear_ref_from_efuns (void)
+
+/* GC support: Clear the refs for the memory containing the (ctime) cache.
+ */
+
+{
+ if (last_ctime_result)
+ clear_string_ref(last_ctime_result);
+} /* clear_ref_from_efuns() */
+
+/*-------------------------------------------------------------------------*/
+void
+count_ref_from_efuns (void)
+
+/* GC support: Count the refs for the memory containing the (ctime) cache.
+ */
+
+{
+ if (last_ctime_result)
+ count_ref_from_string(last_ctime_result);
+} /* count_ref_from_wiz_list() */
+
+#endif /* GC_SUPPORT */
+
+/*-------------------------------------------------------------------------*/
+
diff --git a/src/efuns.h b/src/efuns.h
index 5e7fe1d..4588379 100644
--- a/src/efuns.h
+++ b/src/efuns.h
@@ -76,21 +76,26 @@ extern svalue_t *f_localtime (svalue_t *sp);
extern svalue_t *f_blueprint (svalue_t *sp);
extern svalue_t *v_clones (svalue_t *sp, int num_args);
extern svalue_t *v_object_info (svalue_t *sp, int num_args);
-extern svalue_t *f_present_clone (svalue_t *sp);
+extern svalue_t *v_present_clone (svalue_t *sp, int num_arg);
extern svalue_t *f_to_object(svalue_t *sp);
extern svalue_t *f_set_is_wizard(svalue_t *sp); /* optional */
extern svalue_t *tell_room(svalue_t *sp);
extern svalue_t *f_ctime(svalue_t *);
+extern svalue_t *v_strftime(svalue_t *, int num_arg);
extern svalue_t *v_debug_info(svalue_t *sp, int num_arg);
extern svalue_t *f_rusage(svalue_t *sp);
extern svalue_t *f_random(svalue_t *);
extern svalue_t *f_shutdown(svalue_t *sp);
extern svalue_t *f_time(svalue_t *);
-extern svalue_t *f_utime(svalue_t *);
-extern svalue_t *f_mktime(svalue_t *);
extern svalue_t *f_strftime(svalue_t *);
extern svalue_t *f_strptime(svalue_t *);
+extern svalue_t *f_mktime(svalue_t *);
+extern svalue_t *f_utime(svalue_t *);
+#ifdef GC_SUPPORT
+extern void clear_ref_from_efuns(void);
+extern void count_ref_from_efuns(void);
+#endif /* GC_SUPPORT */
#endif /* EFUNS_H__ */
diff --git a/src/files.c b/src/files.c
index d5f388d..6ef59c8 100644
--- a/src/files.c
+++ b/src/files.c
@@ -46,7 +46,7 @@ extern int lstat(const char *, struct stat *);
#ifdef SunOS4
# if !defined (__GNUC__) || __GNUC__ < 2 || __GNUC__ == 2 && __GNUC_MINOR__ < 7
-extern int lstat(CONST char *, struct stat *);
+extern int lstat (CONST char *, struct stat *);
# endif
extern int fchmod(int, int);
#endif
@@ -74,10 +74,6 @@ extern int fchmod(int, int);
#include "../mudlib/sys/files.h"
-/* TODO: The move/copy code is a derivate of the GNU fileutils. Rewrite
- * TODO:: it, replace it by the BSD code, or put the driver under the GPL.
- */
-
/*-------------------------------------------------------------------------*/
static Bool
isdir (const char *path)
@@ -115,95 +111,81 @@ copy_file (const char *from, const char *to, int mode)
*/
{
- int ifd;
- int ofd;
- char buf[1024 * 8];
- int len; /* Number of bytes read into `buf'. */
-
- if (unlink(to) && errno != ENOENT)
+ int fromfd, tofd;
+ ssize_t count;
+ char buf[4096];
+
+ fromfd = ixopen(from, O_RDONLY);
+ if (fromfd < 0)
{
- debug_message("copy_file(): cannot remove `%s'\n", to);
+ debug_message("copy_file(): can't open '%s': %s\n", from, strerror(errno));
+ return 1;
+ }
+
+ /* We have to unlink 'to', because it may be a symlink.
+ O_CREAT won't remove that. */
+ if (unlink(to) < 0 && errno != ENOENT)
+ {
+ debug_message("copy_file(): can't unlink '%s': %s\n", to, strerror(errno));
+ close(fromfd);
+ return 1;
+ }
+
+ tofd = ixopen3(to, O_WRONLY|O_CREAT|O_TRUNC, mode);
+ if (tofd < 0)
+ {
+ debug_message("copy_file(): can't open '%s': %s\n", to, strerror(errno));
+ close(fromfd);
return 1;
}
- ifd = ixopen3(from, O_RDONLY | O_BINARY, 0);
- if (ifd < 0)
+#ifdef HAVE_FCHMOD
+ /* We have given the file mode to ixopen3, this is just to counter umask.
+ So don't worry if this fchmod fails. */
+ fchmod(tofd, mode);
+#endif
+
+ do
{
- debug_message("copy_file(): %s: open failed\n", from);
- return errno;
- }
-
- ofd = ixopen3(to, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0600);
- if (ofd < 0)
- {
- debug_message("copy_file(): %s: open failed\n", to);
- close(ifd);
- return 1;
- }
-
-#ifdef HAVE_FCHMOD
- if (fchmod(ofd, mode))
- {
- debug_message("copy_file(): %s: fchmod failed\n", to);
- close(ifd);
- close(ofd);
- unlink(to);
- return 1;
- }
-#endif
+ ssize_t written;
+
+ count = read(fromfd, buf, sizeof(buf));
+ if (count < 0)
+ {
+ debug_message("copy_file(): can't read from '%s': %s\n", from, strerror(errno));
+ close(fromfd);
+ close(tofd);
+ unlink(to);
+ return 1;
+ }
+
+ written = 0;
+ while (written < count)
+ {
+ ssize_t len;
+
+ len = write(tofd, buf + written, count - written);
+ if (len <= 0)
+ {
+ debug_message("copy_file(): can't write to '%s': %s\n", to, strerror(errno));
+ close(fromfd);
+ close(tofd);
+ unlink(to);
+ return 1;
+ }
+
+ written += len;
+ }
+ } while (count > 0);
FCOUNT_READ(from);
FCOUNT_WRITE(to);
- while ((len = read(ifd, buf, sizeof (buf))) > 0)
- {
- int wrote = 0;
- char *bp = buf;
-
- do
- {
- wrote = write(ofd, bp, len);
- if (wrote < 0)
- {
- debug_message("copy_file(): %s: write failed\n", to);
- close(ifd);
- close(ofd);
- unlink(to);
- return 1;
- }
- bp += wrote;
- len -= wrote;
- } while (len > 0);
- }
-
- if (len < 0)
- {
- debug_message("copy_file(): %s: read failed\n", from);
- close(ifd);
- close(ofd);
- unlink(to);
- return 1;
- }
-
- if (close (ifd) < 0)
- {
- debug_message("copy_file(): %s: close failed\n", from);
- close(ofd);
- return 1;
- }
-
- if (close (ofd) < 0)
- {
- debug_message("copy_file(): %s: close failed\n", to);
- return 1;
- }
+ close(fromfd);
+ close(tofd);
#ifndef HAVE_FCHMOD
- if (chmod (to, mode))
- {
- debug_message("copy_file(): %s: chmod failed\n", to);
- return 1;
- }
+ chmod(to, mode);
#endif
return 0;
@@ -218,80 +200,55 @@ move_file (const char *from, const char *to)
*/
{
- struct stat to_stats, from_stats;
-
- if (lstat(from, &from_stats) != 0)
+ struct stat fromstat, tostat;
+
+ if (lstat(from, &fromstat) < 0)
{
- debug_message("move_file(): %s: lstat failed\n", from);
+ debug_message("move_file(): can't lstat '%s': %s\n", from, strerror(errno));
return 1;
}
-
- if (lstat (to, &to_stats) == 0)
+
+ if (!lstat(to, &tostat))
{
- if (from_stats.st_dev == to_stats.st_dev
- && from_stats.st_ino == to_stats.st_ino)
+ if (fromstat.st_dev == tostat.st_dev
+ && fromstat.st_ino == tostat.st_ino)
{
- debug_message("move_file(): '%s' and '%s' are the same file\n", from, to);
+ /* Same file. */
+ debug_message("move_file(): '%s' and '%s' are the same.\n", from, to);
return 1;
}
-
- if (S_ISDIR (to_stats.st_mode))
+
+ if (S_ISDIR(tostat.st_mode))
{
- debug_message("move_file(): %s: cannot overwrite directory\n", to);
+ debug_message("move_file(): destination '%s' is a directory.\n", to);
+ return 1;
+ }
+ }
+
+ if (rename(from, to))
+ {
+ if (errno == EXDEV)
+ {
+ if (!S_ISREG(fromstat.st_mode))
+ {
+ debug_message("move_file(): can't move '%s' across filesystems: Not a regular file.\n", to);
+ return 1;
+ }
+
+ if (copy_file(from, to, fromstat.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)))
+ return 1;
+
+ unlink(from);
+ }
+ else
+ {
+ debug_message("move_file(): can't rename '%s' to '%s': %s\n", to, from, strerror(errno));
return 1;
}
-
- }
- else if (errno != ENOENT)
- {
- perror("do_move");
- debug_message("move_file(): %s: unknown error\n", to);
- return 1;
- }
-#ifndef RENAME_HANDLES_DIRECTORIES
- /* old SYSV */
- if (isdir(from))
- {
- char cmd_buf[3*MAXPATHLEN+1];
-
- if (strchr(from, '\'') || strchr(to, '\''))
- return 0;
- sprintf(cmd_buf, "/usr/lib/mv_dir '%s' '%s'", from, to);
- return system(cmd_buf);
- }
- else
-#endif /* RENAME_HANDLES_DIRECTORIES */
- if (rename (from, to) == 0)
- {
- FCOUNT_DEL(from);
- return 0;
}
- if (errno != EXDEV)
- {
- debug_message("move_file(): cannot move '%s' to '%s'\n", from, to);
- return 1;
- }
-
- /* rename failed on cross-filesystem link. Copy the file instead. */
-
- if (!S_ISREG(from_stats.st_mode))
- {
- debug_message("move_file(): cannot move '%s' across filesystems: "
- "Not a regular file\n", from);
- return 1;
- }
-
- if (copy_file(from, to, from_stats.st_mode & 0777))
- return 1;
-
- if (unlink(from))
- {
- debug_message("move_file(): cannot remove '%s'\n", from);
- return 1;
- }
FCOUNT_DEL(from);
-
+
return 0;
} /* move_file() */
@@ -1750,7 +1707,7 @@ f_write_file (svalue_t *sp)
break;
if (sp->u.number & 1)
- if (remove(get_txt(file)))
+ if (remove(get_txt(file)) && errno != ENOENT)
{
perror("write_file (remove)");
errorf("Could not remove %s: errno %d.\n", get_txt(file), errno);
diff --git a/src/func_spec b/src/func_spec
index 1d17a9a..3760125 100644
--- a/src/func_spec
+++ b/src/func_spec
@@ -657,7 +657,7 @@ object first_inventory(object|string default: F_THIS_OBJECT);
object next_inventory(object default: F_THIS_OBJECT);
void move_object(object|string, object|string);
object present(object|string, void|int|object, void|object);
-object present_clone(object|string, object default: F_THIS_OBJECT); /* PRELIMINARY */
+object present_clone(object|string, object|int|void, int|void);
#ifdef USE_STRUCTS
void say(string|mixed *|object|mapping|struct, void|object|object *);
#else
diff --git a/src/gcollect.c b/src/gcollect.c
index deabb16..4587afc 100644
--- a/src/gcollect.c
+++ b/src/gcollect.c
@@ -94,6 +94,7 @@
#include "closure.h"
#include "comm.h"
#include "ed.h"
+#include "efuns.h"
#include "filestat.h"
#include "heartbeat.h"
#include "interpret.h"
@@ -124,6 +125,8 @@
#include "wiz_list.h"
#include "xalloc.h"
+#include "i-eval_cost.h"
+
#include "../mudlib/sys/driver_hook.h"
/*-------------------------------------------------------------------------*/
@@ -2094,6 +2097,7 @@ garbage_collection(void)
mstring_clear_refs();
clear_ref_from_wiz_list();
clear_ref_from_call_outs();
+ clear_ref_from_efuns();
#if defined(USE_PARSE_COMMAND)
clear_parse_refs();
#endif
@@ -2313,6 +2317,7 @@ garbage_collection(void)
count_ref_from_wiz_list();
count_ref_from_call_outs();
+ count_ref_from_efuns();
if (master_ob)
master_ob->ref++;
diff --git a/src/heartbeat.c b/src/heartbeat.c
index 20e6ba3..ffce533 100644
--- a/src/heartbeat.c
+++ b/src/heartbeat.c
@@ -57,6 +57,8 @@
#include "wiz_list.h"
#include "xalloc.h"
+#include "i-eval_cost.h"
+
#include "../mudlib/sys/debug_info.h"
/*-------------------------------------------------------------------------*/
@@ -165,7 +167,7 @@ call_heart_beat (void)
error_recovery_info.rt.last = rt_context;
error_recovery_info.rt.type = ERROR_RECOVERY_BACKEND;
- rt_context = (rt_context_t *)&error_recovery_info;
+ rt_context = (rt_context_t *)&error_recovery_info.rt;
if (setjmp(error_recovery_info.con.text))
{
diff --git a/src/i-eval_cost.h b/src/i-eval_cost.h
new file mode 100644
index 0000000..752823f
--- /dev/null
+++ b/src/i-eval_cost.h
@@ -0,0 +1,82 @@
+/*---------------------------------------------------------------------------
+ * Eval Cost functions.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+#ifndef I_EVAL_COST__
+#define I_EVAL_COST__
+
+#include "driver.h"
+
+#include "interpret.h"
+
+/*-------------------------------------------------------------------------*/
+static INLINE Bool
+add_eval_cost_n (int32 added_cost, uint repetitions)
+
+/* Increase the evaluation cost by *. Return TRUE if
+ * this would exceed max_eval_cost, return FALSE if not.
+ *
+ * Passing explicitely guards against situations where
+ * * itself would overflow.
+ *
+ * To safeguard the driver against ridiculous executions, the actual eval_cost
+ * is capped at max_eval_cost+1.
+ */
+
+{
+ if (repetitions == 0)
+ return MY_FALSE;
+
+ if (max_eval_cost)
+ {
+ /* Test the evaluation cost against the limit.
+ * eval_cost < 0 signify a wrap-around - unlikely, but with these crazy
+ * wizards everything is possible.
+ */
+ if (eval_cost >= max_eval_cost || eval_cost < 0)
+ return MY_TRUE;
+
+ if (max_eval_cost - eval_cost < added_cost
+ || (int32)((max_eval_cost - eval_cost) / repetitions) < added_cost
+ )
+ {
+ total_evalcost += max_eval_cost - eval_cost + 1;
+ eval_cost = max_eval_cost+1;
+ return MY_TRUE;
+ }
+ }
+
+ eval_cost += added_cost * repetitions;
+ total_evalcost += added_cost * repetitions;
+
+ return MY_FALSE;
+} /* add_eval_cost_n() */
+
+/*-------------------------------------------------------------------------*/
+
+/* --- Macros --- */
+
+/* Increase the eval cost for a non-repetitive action.
+ */
+#define add_eval_cost(cost) add_eval_cost_n(cost, 1)
+
+/* Reset the evaluation cost/time counter.
+ */
+#define CLEAR_EVAL_COST (assigned_eval_cost = eval_cost = 0)
+
+/* Check if the current evaluation took too long
+ */
+#define EVALUATION_TOO_LONG() \
+ (max_eval_cost && (eval_cost >= max_eval_cost || eval_cost < 0))
+
+/* Return the amount of remaining evaluation costs, or MAX_INT if there
+ * is no real maximum.
+ */
+#define GET_REMAINING_EVAL_COST() \
+ ( max_eval_cost ? ((eval_cost >= max_eval_cost || eval_cost < 0) ? 0 : (max_eval_cost - eval_cost)) : INT32_MAX)
+
+/***************************************************************************/
+
+#endif /* I_EVAL_COST__ */
diff --git a/src/i-svalue_cmp.h b/src/i-svalue_cmp.h
index 21f7543..0bc7cd4 100644
--- a/src/i-svalue_cmp.h
+++ b/src/i-svalue_cmp.h
@@ -37,7 +37,7 @@ svalue_cmp (svalue_t *left, svalue_t *right)
*/
{
- register int d;
+ register p_int d;
if ( 0 != (d = left->type - right->type) ) return d;
diff --git a/src/interpret.c b/src/interpret.c
index 4e450e8..92ec6ee 100644
--- a/src/interpret.c
+++ b/src/interpret.c
@@ -242,6 +242,8 @@
#include "wiz_list.h"
#include "xalloc.h"
+#include "i-eval_cost.h"
+
#include "../mudlib/sys/driver_hook.h"
#include "../mudlib/sys/debug_info.h"
#include "../mudlib/sys/trace.h"
@@ -269,6 +271,11 @@ struct catch_context
svalue_t * save_sp;
/* The saved global values
*/
+
+ svalue_t catch_value;
+ /* Holds the value throw()n from within a catch() while the throw
+ * is executed.
+ */
};
/* --- struct cache: one entry of the apply cache
@@ -329,11 +336,19 @@ struct cache
#endif
/* Number of entries in the apply cache.
*/
-
+#if CACHE_SIZE > INT_MAX
+#error CACHE_SIZE is > INT_MAX.
+#endif
+ /* sanity check - some function rely that CACHE_SIZE fits into int */
/*-------------------------------------------------------------------------*/
/* Tracing */
+#if TOTAL_TRACE_LENGTH > INT_MAX
+#error TOTAL_TRACE_LENGTH is > INT_MAX.
+#endif
+/* sanity check - some function rely that TOTAL_TRACE_LENGTH fits into int */
+
int tracedepth;
/* Current depth of traced functions.
*/
@@ -555,6 +570,10 @@ svalue_t apply_return_value = { T_NUMBER };
*/
#define SIZEOF_STACK (EVALUATOR_STACK_SIZE<<1)
+#if SIZEOF_STACK > INT_MAX
+#error SIZEOF_STACK is > INT_MAX.
+#endif
+/* sanity check - some function rely that SIZEOF_STACK fits into int */
static svalue_t value_stack_array[SIZEOF_STACK+1];
#define VALUE_STACK (value_stack_array+1)
@@ -569,12 +588,9 @@ static svalue_t value_stack_array[SIZEOF_STACK+1];
* is the real bottom of the stack.
*/
-svalue_t catch_value = { T_INVALID } ;
- /* Holds the value throw()n from within a catch() while the throw
- * is executed.
- */
-
-
+#if MAX_TRACE > INT_MAX
+#error MAX_TRACE is > INT_MAX.
+#endif
#if MAX_USER_TRACE >= MAX_TRACE
#error MAX_USER_TRACE value must be smaller than MAX_TRACE!
#endif
@@ -611,8 +627,8 @@ static Bool runtime_array_range_check = MY_FALSE;
*/
#ifdef APPLY_CACHE_STAT
-p_int apply_cache_hit = 0;
-p_int apply_cache_miss = 0;
+p_uint apply_cache_hit = 0;
+p_uint apply_cache_miss = 0;
/* Number of hits and misses in the apply cache.
*/
#endif
@@ -730,39 +746,45 @@ static void check_extra_ref_in_vector(svalue_t *svp, size_t num);
*
* This function must be called at least whenever the execution leaves
* one object for another one.
+ *
+ * assign_eval_cost_inl() is the inlinable version used here,
+ * assign_eval_cost() is used by other compilation units.
*/
-#define ASSIGN_EVAL_COST \
- if (current_object->user)\
- {\
- unsigned long carry;\
- current_object->user->cost += eval_cost - assigned_eval_cost;\
- carry = current_object->user->cost / 1000000000;\
- if (carry)\
- {\
- current_object->user->gigacost += carry;\
- current_object->user->cost %= 1000000000;\
- }\
- current_object->user->total_cost += eval_cost - assigned_eval_cost;\
- carry = current_object->user->total_cost / 1000000000;\
- if (carry)\
- {\
- current_object->user->total_gigacost += carry;\
- current_object->user->total_cost %= 1000000000;\
- }\
- }\
- current_object->ticks += eval_cost - assigned_eval_cost;\
- {\
- unsigned long carry = current_object->ticks / 1000000000;\
- if (carry)\
- {\
- current_object->gigaticks += carry;\
- current_object->ticks %= 1000000000;\
- }\
- }\
+static INLINE void
+assign_eval_cost_inl(void)
+{
+ unsigned long carry;
+ if (current_object->user)
+ {
+ current_object->user->cost += eval_cost - assigned_eval_cost;
+ carry = current_object->user->cost / 1000000000;
+ if (carry)
+ {
+ current_object->user->gigacost += carry;
+ current_object->user->cost %= 1000000000;
+ }
+ current_object->user->total_cost += eval_cost - assigned_eval_cost;
+ carry = current_object->user->total_cost / 1000000000;
+ if (carry)
+ {
+ current_object->user->total_gigacost += carry;
+ current_object->user->total_cost %= 1000000000;
+ }
+ }
+ current_object->ticks += eval_cost - assigned_eval_cost;
+ {
+ carry = current_object->ticks / 1000000000;
+ if (carry)
+ {
+ current_object->gigaticks += carry;
+ current_object->ticks %= 1000000000;
+ }
+ }
assigned_eval_cost = eval_cost;
+}
-void assign_eval_cost(void) { ASSIGN_EVAL_COST }
+void assign_eval_cost(void) { assign_eval_cost_inl(); }
/*-------------------------------------------------------------------------*/
void
@@ -934,7 +956,10 @@ struct protected_lvalue
/* .v.type: T_PROTECTED_LVALUE
* .v.u.lvalue: the protected value
*/
- svalue_t protector; /* protects .v.u.lvalue (or its holder) */
+ svalue_t protector;
+ /* additional reference .v.u.lvalue (or its holder) as means of
+ * protection
+ */
};
/* --- struct protected_char_lvalue: protect a char in a string
@@ -962,12 +987,12 @@ struct protected_range_lvalue {
*/
svalue_t protector; /* protects .lvalue */
svalue_t *lvalue; /* the original svalue holding the range */
- int index1, index2; /* first and last index of the range */
+ int index1, index2; /* first and last index of the range in .lvalue */
int size; /* original size of .lvalue */
/* On creation, .v.u.{vec,str} == .lvalue->u.{vec,str}.
- * If that condition no longer holds, the target has been changed and
- * the range information (index, size) is no longer valid.
+ * If that condition no longer holds, the target in .v has been changed
+ * and the range information (index, size) is no longer valid.
*/
};
@@ -1546,7 +1571,7 @@ inl_copy_svalue_no_free (svalue_t *to, svalue_t *from)
DYN_MAPPING_COST(MAP_SIZE(old));
new = copy_mapping(old);
if (!new)
- errorf("Out of memory: mapping[%lu] for copy.\n"
+ errorf("Out of memory: mapping[%"PRIdPINT"] for copy.\n"
, MAP_SIZE(old));
free_mapping(old);
to->u.map = new;
@@ -1565,8 +1590,8 @@ inl_copy_svalue_no_free (svalue_t *to, svalue_t *from)
DYN_ARRAY_COST(size);
new = allocate_uninit_array((int)size);
if (!new)
- errorf("Out of memory: array[%lu] for copy.\n"
- , (unsigned long) size);
+ errorf("Out of memory: array[%zu] for copy.\n"
+ , size);
for (i = 0; i < size; i++)
assign_svalue_no_free( &new->item[i]
, &old->item[i]);
@@ -1812,8 +1837,8 @@ assign_svalue (svalue_t *dest, svalue_t *v)
{
/* Free the svalue.
- * If is a lvalue, the loop will traverse the lvalue chain until
- * the actual svalue is found.
+ * If is a (protected) lvalue, the loop will traverse the lvalue
+ * chain until the actual svalue is found.
* If a T_xxx_LVALUE is found, the assignment will be done here
* immediately.
*/
@@ -2132,8 +2157,8 @@ transfer_pointer_range (svalue_t *source)
#ifdef NO_NEGATIVE_RANGES
if (index1 > index2)
- errorf("Illegal range [%ld..%ld] for assignment.\n"
- , index1, index2-1
+ errorf("Illegal range [%"PRIdMPINT"..%"PRIdMPINT
+ "] for assignment.\n", index1, index2-1
);
#endif /* NO_NEGATIVE_RANGES */
@@ -2248,8 +2273,8 @@ transfer_protected_pointer_range ( struct protected_range_lvalue *dest
#ifdef NO_NEGATIVE_RANGES
if (index1 > index2)
- errorf("Illegal range [%ld..%ld] for assignment.\n"
- , index1, index2-1
+ errorf("Illegal range [%"PRIdMPINT"..%"PRIdMPINT
+ "] for assignment.\n", index1, index2-1
);
#endif /* NO_NEGATIVE_RANGES */
@@ -2318,7 +2343,9 @@ transfer_protected_pointer_range ( struct protected_range_lvalue *dest
}
else
{
- /* Not a pointer: just free it */
+ /* Not a pointer, or the protected range has changed in size before:
+ * just free it
+ */
free_svalue(source);
}
@@ -2357,8 +2384,8 @@ assign_string_range (svalue_t *source, Bool do_free)
#ifdef NO_NEGATIVE_RANGES
if (index1 > index2)
- errorf("Illegal range [%ld..%ld] for assignment.\n"
- , index1, index2-1
+ errorf("Illegal range [%"PRIdMPINT"..%"PRIdMPINT
+ "] for assignment.\n", index1, index2-1
);
#endif /* NO_NEGATIVE_RANGES */
@@ -2430,8 +2457,8 @@ assign_protected_string_range ( struct protected_range_lvalue *dest
#ifdef NO_NEGATIVE_RANGES
if (index1 > index2)
- errorf("Illegal range [%ld..%ld] for assignment.\n"
- , index1, index2-1
+ errorf("Illegal range [%"PRIdMPINT"..%"PRIdMPINT
+ "] for assignment.\n", index1, index2-1
);
#endif /* NO_NEGATIVE_RANGES */
@@ -2606,7 +2633,7 @@ inter_add_array (vector_t *q, vector_t **vpp)
if (max_array_size && p_size + q_size > max_array_size)
{
- errorf("Illegal array size: %ld.\n", (long)(p_size + q_size));
+ errorf("Illegal array size: %zu.\n", (p_size + q_size));
}
/* The optimized array-adding will transfer elements around, rendering
@@ -2699,6 +2726,7 @@ inter_add_array (vector_t *q, vector_t **vpp)
return r;
} /* inter_add_array() */
+
/*=========================================================================*/
/* S T A C K */
@@ -2807,7 +2835,8 @@ _pop_stack (void)
{
#ifdef DEBUG
if (inter_sp < VALUE_STACK)
- fatal("VM Stack underflow: %ld too low.\n", (long)(VALUE_STACK - inter_sp));
+ fatal("VM Stack underflow: %"PRIdMPINT" too low.\n",
+ (mp_int)(VALUE_STACK - inter_sp));
#endif
free_svalue(inter_sp--);
}
@@ -2839,6 +2868,8 @@ svalue_t * pop_n_elems (int n, svalue_t *sp)
{ return _pop_n_elems(n, sp); }
/*-------------------------------------------------------------------------*/
+static void stack_overflow (svalue_t *sp, svalue_t *fp, bytecode_p pc)
+ NORETURN;
static void
stack_overflow (svalue_t *sp, svalue_t *fp, bytecode_p pc)
@@ -2850,8 +2881,8 @@ stack_overflow (svalue_t *sp, svalue_t *fp, bytecode_p pc)
{
if (sp >= &VALUE_STACK[SIZEOF_STACK])
- fatal("Fatal stack overflow: %ld too high.\n"
- , (long)(sp - &VALUE_STACK[SIZEOF_STACK])
+ fatal("Fatal stack overflow: %"PRIdMPINT" too high.\n"
+ , (mp_int)(sp - &VALUE_STACK[SIZEOF_STACK])
);
sp = _pop_n_elems(sp-fp, sp);
ERROR("stack overflow\n");
@@ -2871,13 +2902,14 @@ push_referenced_mapping (mapping_t *m)
}
/*-------------------------------------------------------------------------*/
-void
+svalue_t *
push_error_handler(void (*errorhandler)(svalue_t *), svalue_t *arg)
/* Push the () with the argument as error handler
* onto the stack.
* This means that a new T_LVALUE is created on the stack, pointing
* to . itself is setup to be a T_ERROR_HANDLER value.
+ * Returns new inter_sp.
*/
{
@@ -2887,6 +2919,7 @@ push_error_handler(void (*errorhandler)(svalue_t *), svalue_t *arg)
inter_sp++;
inter_sp->type = T_LVALUE;
inter_sp->u.lvalue = arg;
+ return inter_sp;
} /* push_error_handler() */
/*-------------------------------------------------------------------------*/
@@ -3021,7 +3054,7 @@ get_vector_item (vector_t * vec, svalue_t * i, svalue_t *sp, bytecode_p pc)
*/
{
- int ind;
+ p_int ind;
svalue_t * item;
if (i->type != T_NUMBER)
@@ -3042,8 +3075,9 @@ get_vector_item (vector_t * vec, svalue_t * i, svalue_t *sp, bytecode_p pc)
}
if (ind >= VEC_SIZE(vec))
{
- ERRORF(("Index for [] out of bounds: %ld, vector size: %lu\n"
- , (long)ind, VEC_SIZE(vec)));
+ ERRORF(("Index for [] out of bounds: %"PRIdPINT
+ ", vector size: %"PRIdPINT"\n"
+ , ind, VEC_SIZE(vec)));
/* NOTREACHED */
return NULL;
}
@@ -3070,7 +3104,7 @@ get_vector_r_item (vector_t * vec, svalue_t * i, svalue_t *sp, bytecode_p pc)
*/
{
- int ind;
+ p_int ind;
svalue_t * item;
if (i->type != T_NUMBER)
@@ -3085,12 +3119,12 @@ get_vector_r_item (vector_t * vec, svalue_t * i, svalue_t *sp, bytecode_p pc)
ERROR("Illegal index for [<]: not a positive number.\n");
return NULL;
}
- if ( (ind = (mp_int)VEC_SIZE(vec) - ind) < 0
- || ind >= (mp_int)VEC_SIZE(vec)
+ if ( (ind = VEC_SIZE(vec) - ind) < 0
+ || ind >= VEC_SIZE(vec)
)
{
- ERRORF(("Index out of bounds for [<]: %ld, vector size: %lu.\n"
- , (long)(i->u.number), VEC_SIZE(vec)));
+ ERRORF(("Index out of bounds for [<]: %"PRIdPINT", vector size: %"
+ PRIdPINT".\n", i->u.number, VEC_SIZE(vec)));
return NULL;
}
@@ -3115,7 +3149,7 @@ get_vector_a_item (vector_t * vec, svalue_t * i, svalue_t *sp, bytecode_p pc)
*/
{
- int ind;
+ p_int ind;
svalue_t * item;
if (i->type != T_NUMBER)
@@ -3126,11 +3160,12 @@ get_vector_a_item (vector_t * vec, svalue_t * i, svalue_t *sp, bytecode_p pc)
return NULL;
}
if (0 > (ind = i->u.number))
- ind = (mp_int)VEC_SIZE(vec) + ind;
- if (ind < 0 || ind >= (mp_int)VEC_SIZE(vec))
+ ind = VEC_SIZE(vec) + ind;
+ if (ind < 0 || ind >= VEC_SIZE(vec))
{
- ERRORF(("Index out of bounds for [>]: %ld, vector size: %lu.\n"
- , (long)(i->u.number), VEC_SIZE(vec)));
+ ERRORF(("Index out of bounds for [>]: %"PRIdPINT", vector size: %"
+ PRIdPINT".\n"
+ , i->u.number, VEC_SIZE(vec)));
return NULL;
}
@@ -3181,8 +3216,9 @@ get_string_item ( svalue_t * svp, svalue_t * i, Bool make_singular
if (ind > (mp_int)mstrsize(svp->u.str) )
{
- ERRORF(("Index out for [] of bounds: %ld, string length: %ld.\n"
- , (long)ind, (long)mstrsize(svp->u.str)));
+ ERRORF(("Index out for [] of bounds: %"PRIdMPINT
+ ", string length: %zu.\n"
+ , ind, mstrsize(svp->u.str)));
return NULL;
}
@@ -3190,14 +3226,15 @@ get_string_item ( svalue_t * svp, svalue_t * i, Bool make_singular
{
if (!allow_one_past)
{
- ERRORF(("Index out of bounds for []: %ld, string length: %ld.\n"
- , (long)ind, (long)mstrsize(svp->u.str)));
+ ERRORF(("Index out of bounds for []: %"PRIdMPINT
+ ", string length: %zu.\n"
+ , ind, mstrsize(svp->u.str)));
return NULL;
}
else if (!runtime_no_warn_deprecated)
warnf( "Warning: Indexing past string end is deprecated: "
- "index %ld, string length: %ld.\n"
- , (long)ind, (long)mstrsize(svp->u.str)
+ "index %"PRIdMPINT", string length: %zu.\n"
+ , ind, mstrsize(svp->u.str)
);
}
}
@@ -3263,8 +3300,9 @@ get_string_r_item (svalue_t * svp, svalue_t * i, Bool make_singular
|| ind > (mp_int)mstrsize(svp->u.str)
)
{
- ERRORF(("Index out of bounds for [<]: %ld, string length: %ld\n"
- , (long) i->u.number, (long)mstrsize(svp->u.str)));
+ ERRORF(("Index out of bounds for [<]: %"PRIdPINT
+ ", string length: %zu\n"
+ , i->u.number, mstrsize(svp->u.str)));
return NULL;
}
@@ -3272,14 +3310,15 @@ get_string_r_item (svalue_t * svp, svalue_t * i, Bool make_singular
{
if (!allow_one_past)
{
- ERRORF(("Index out for [<] of bounds: %ld, string length: %ld.\n"
- , (long)ind, (long)mstrsize(svp->u.str)));
+ ERRORF(("Index out for [<] of bounds: %"PRIdMPINT
+ ", string length: %zu.\n"
+ , ind, mstrsize(svp->u.str)));
return NULL;
}
else if (!runtime_no_warn_deprecated)
warnf( "Warning: Indexing past string end is deprecated: "
- "index %ld, string length: %ld.\n"
- , (long)ind, (long)mstrsize(svp->u.str)
+ "index %"PRIdMPINT", string length: %zu.\n"
+ , ind, mstrsize(svp->u.str)
);
}
}
@@ -3340,8 +3379,9 @@ get_string_a_item (svalue_t * svp, svalue_t * i, Bool make_singular
}
if (ind < 0 || ind > (mp_int)mstrsize(svp->u.str))
{
- ERRORF(("Index out of bounds for [>]: %ld, string length: %ld\n"
- , (long) i->u.number, (long)mstrsize(svp->u.str)));
+ ERRORF(("Index out of bounds for [>]: %"PRIdPINT
+ ", string length: %zu\n"
+ , i->u.number, mstrsize(svp->u.str)));
return NULL;
}
@@ -3349,14 +3389,15 @@ get_string_a_item (svalue_t * svp, svalue_t * i, Bool make_singular
{
if (!allow_one_past)
{
- ERRORF(("Index out for [>] of bounds: %ld, string length: %ld.\n"
- , (long)ind, (long)mstrsize(svp->u.str)));
+ ERRORF(("Index out for [>] of bounds: %"PRIdMPINT
+ ", string length: %zu.\n"
+ , ind, mstrsize(svp->u.str)));
return NULL;
}
else if (!runtime_no_warn_deprecated)
warnf( "Warning: Indexing past string end is deprecated: "
- "index %ld, string length: %ld.\n"
- , (long)ind, (long)mstrsize(svp->u.str)
+ "index %"PRIdMPINT", string length: %zu.\n"
+ , ind, mstrsize(svp->u.str)
);
}
}
@@ -3412,8 +3453,8 @@ check_struct_op (svalue_t * sp, int off_type, int off_value, bytecode_p pc)
if (sp[off_type].u.number >= 0
&& sp[off_type].u.number >= current_prog->num_structs)
{
- ERRORF(("Too big struct index: %ld, max %hu\n"
- , (long)sp[off_type].u.number, current_prog->num_structs
+ ERRORF(("Too big struct index: %"PRIdPINT", max %hu\n"
+ , sp[off_type].u.number, current_prog->num_structs
));
}
@@ -3516,7 +3557,7 @@ get_struct_item (struct_t * st, svalue_t * i, svalue_t *sp, bytecode_p pc)
*/
{
- int ind;
+ p_int ind;
svalue_t * item;
if (i->type == T_SYMBOL || i->type == T_STRING)
@@ -3555,9 +3596,9 @@ get_struct_item (struct_t * st, svalue_t * i, svalue_t *sp, bytecode_p pc)
if (ind >= struct_size(st))
{
ERRORF(("Illegal struct '%s'->: out of bounds: "
- "%ld, struct sized: %lu.\n"
+ "%"PRIdPINT", struct sized: %lu.\n"
, get_txt(struct_name(st))
- , (long)ind
+ , ind
, (unsigned long)struct_size(st)
));
/* NOTREACHED */
@@ -4089,8 +4130,8 @@ push_protected_indexed_map_lvalue (svalue_t *sp, bytecode_p pc)
/* using uints automagically checks for negative indices */
)
{
- ERRORF(("Too big subindex for []: value %ld, width %ld.\n"
- , sp->u.number, (long)m->num_values));
+ ERRORF(("Too big subindex for []: value %"PRIdPINT", width %"
+ PRIdPINT".\n", sp->u.number, m->num_values));
return NULL;
}
@@ -4407,7 +4448,7 @@ aindex_lvalue (svalue_t *sp, bytecode_p pc)
} /* aindex_lvalue() */
/*-------------------------------------------------------------------------*/
-static INLINE svalue_t *
+static svalue_t *
protected_index_lvalue (svalue_t *sp, bytecode_p pc)
/* Operator F_PROTECTED_INDEX_LVALUE (string|vector &v=sp[0], int i=sp[-1])
@@ -5140,8 +5181,9 @@ range_lvalue (int code, svalue_t *sp)
if (++ind2 < 0 || ind2 > size+1)
{
inter_sp = sp;
- errorf("Upper range index out of bounds: %ld, size: %ld.\n"
- , (long)i->u.number, (long)size);
+ errorf("Upper range index out of bounds: %"PRIdPINT
+ ", size: %"PRIdMPINT".\n"
+ , i->u.number, size);
return NULL;
}
@@ -5174,8 +5216,9 @@ range_lvalue (int code, svalue_t *sp)
if (ind1 < 0 || ind1 > size)
{ /* Appending (ind1 == size) is allowed */
inter_sp = sp;
- errorf("Lower range index out of bounds: %ld, size: %ld.\n"
- , (long)i->u.number, (long)size);
+ errorf("Lower range index out of bounds: %"PRIdPINT
+ ", size: %"PRIdMPINT".\n"
+ , i->u.number, size);
return NULL;
}
@@ -5185,8 +5228,9 @@ range_lvalue (int code, svalue_t *sp)
if (ind2 < ind1)
{
inter_sp = sp;
- errorf("Range of negative size given: %ld..%ld .\n"
- , (long)i->u.number, (long)(i+1)->u.number);
+ errorf("Range of negative size given: %"PRIdPINT
+ "..%"PRIdPINT" .\n"
+ , i->u.number, (i+1)->u.number);
return NULL;
}
@@ -5195,8 +5239,9 @@ range_lvalue (int code, svalue_t *sp)
else if (ind2 > size)
{
inter_sp = sp;
- errorf("Upper range index out of bounds: %ld, size: %ld.\n"
- , (long)(i+1)->u.number, (long)size);
+ errorf("Upper range index out of bounds: %"PRIdPINT
+ ", size: %"PRIdMPINT".\n"
+ , (i+1)->u.number, size);
return NULL;
}
@@ -5351,8 +5396,9 @@ protected_range_lvalue (int code, svalue_t *sp)
if (++ind2 < 0 || ind2 > size) {
inter_sp = sp;
- errorf("Upper range index out of bounds: %ld, size: %ld.\n"
- , (long)i->u.number, (long)size);
+ errorf("Upper range index out of bounds: %"PRIdPINT
+ ", size: %"PRIdMPINT".\n"
+ , i->u.number, size);
return NULL;
}
@@ -5386,8 +5432,9 @@ protected_range_lvalue (int code, svalue_t *sp)
{
/* Appending (ind1 == size) is allowed */
inter_sp = sp;
- errorf("Lower range index out of bounds: %ld, size: %ld.\n"
- , (long)i->u.number, (long)size);
+ errorf("Lower range index out of bounds: %"PRIdPINT
+ ", size: %"PRIdMPINT".\n"
+ , i->u.number, size);
return NULL;
}
@@ -6020,15 +6067,18 @@ efun_arg_typename (long type)
* string and return it. The type encoding is the one used in
* efun_lpc_types[].
* Result is a pointer to a static buffer.
+ * TODO: this function should use snprintf() for preventing buffer overflows,
+ * TODO::especially changing svalue_typename is otherwise risky.
*/
{
static char result[400];
int numtypes, i;
-
+
+ /* TODO: better write into result and return the static buffer */
if (type == TF_ANYTYPE)
return "mixed";
-
+
result[0] = '\0';
numtypes = sizeof(svalue_typename)/sizeof(svalue_typename[0]);
@@ -6378,6 +6428,55 @@ test_efun_args (int instr, int args, svalue_t *argp)
} /* test_efun_args() */
+/*-------------------------------------------------------------------------*/
+/* general errorhandler */
+static void
+generic_error_handler( svalue_t * arg)
+/* The error handler: free the allocated buffer and the errorhandler structure.
+ * Note: it is static, but the compiler will have to emit a function and
+ * symbol for this because the address of the function is taken and it is
+ * therefore not suitable to be inlined.
+ */
+{
+ errorhandler_t *handler = (errorhandler_t *)arg;
+ if (handler->buff)
+ xfree(handler->buff);
+ xfree(handler);
+} /* general_error_handler() */
+
+/*-------------------------------------------------------------------------*/
+void *
+xalloc_with_error_handler(size_t size)
+/* Allocates bytes from the heap. Additionally an error handler is
+ * pushed onto the value stack so that the requested memory is safely freed,
+ * either by manually freeing the svalue on the stack or during stack
+ * unwinding during errorf().
+ * inter_sp has to point to the top-of-stack before calling and is updated to
+ * point to the error handler svalue (new top-of-stack)!
+ */
+{
+ void *buffer;
+ errorhandler_t *handler;
+ /* get the memory for the handler first and fail if out-of-memory */
+ handler = xalloc(sizeof(*handler));
+ if (!handler)
+ {
+ return NULL;
+ }
+ /* then get the requested memory - upon error de-allocate the handler */
+ buffer = xalloc(size);
+ if (!buffer)
+ {
+ xfree(handler);
+ return NULL;
+ }
+ handler->buff = buffer;
+ /* now push error handler onto the value stack */
+ push_error_handler(generic_error_handler, &(handler->head));
+ return buffer;
+} /* alloc_with_error_handler */
+
+
/*=========================================================================*/
/*-------------------------------------------------------------------------*/
Bool
@@ -6699,7 +6798,8 @@ push_error_context (svalue_t *sp, int catch_flags)
p->recovery_info.rt.last = rt_context;
p->recovery_info.rt.type = ERROR_RECOVERY_CATCH;
p->recovery_info.flags = catch_flags;
- rt_context = (rt_context_t *)&p->recovery_info;
+ p->catch_value.type = T_INVALID;
+ rt_context = (rt_context_t *)&p->recovery_info.rt;
return &p->recovery_info.con;
} /* push_error_context() */
@@ -6733,7 +6833,7 @@ pop_error_context (void)
/*-------------------------------------------------------------------------*/
svalue_t *
-pull_error_context (svalue_t *sp)
+pull_error_context (svalue_t *sp, svalue_t *msg)
/* Restore the context saved by a catch() after a throw() or runtime error
* occured. is the current stackpointer and is used to pop the elements
@@ -6742,6 +6842,8 @@ pull_error_context (svalue_t *sp)
* The function pops the topmost recovery entry, which must be the catch
* recovery entry, restores the important global variables and returns
* the saved stack pointer.
+ *
+ * If is not NULL the caught error message is put there.
*/
{
@@ -6780,6 +6882,12 @@ pull_error_context (svalue_t *sp)
csp = p->save_csp;
pop_n_elems(sp - p->save_sp);
command_giver = p->save_command_giver;
+
+ /* Save the error message */
+ if (msg)
+ transfer_svalue_no_free(msg, &p->catch_value);
+ else
+ free_svalue(&p->catch_value);
/* Remove the context from the context stack */
rt_context = p->recovery_info.rt.last;
@@ -6788,6 +6896,19 @@ pull_error_context (svalue_t *sp)
return sp;
} /* pull_error_context() */
+/*-------------------------------------------------------------------------*/
+void
+transfer_error_message (svalue_t *v, rt_context_t *rt)
+ /* Saves the message in the error context