Date: Tue, 08 Feb 2000 09:01:45 -0700 From: Zwirch Subject: H_MODIFY_OUTPUT Type: Feature State: New From: Zwirch@PK-Mud Cc: Subject: H_MODIFY_OUTPUT-driverhook Date: Tue Feb 8 14:15:20 2000 Du kannst das Diff zu LDMud-dev164 im PK-Mud-Ftp ziehen (ftp pk.mud.de 4713, anonymous login, Software/Driver/diff-dev164-outputhook). Folgendes macht der Hook: --------------------------------------------------------------------------- H_MODIFY_OUTPUT Optional hook to modify every output that is send to an interactive user (except prompts or binary_message()). Hook setting can be an closure or the name of the function to call in the object. === More: (38%) Page 1, 1..16 [CR,u,f,l,q,/<regexp>,<page>,?] If the hook is a closure, it is called as string <closure>(string output, object player) with the output as first, and the receiving player as second argument. If the hook is a string, it is used as the name of an lfun in the command giving player, which is called as string <name>(string output) If the result is a string it is the new output, which will be sent to the player, otherwise the original output is sent. ---------------------------------------------------------------------- ----- Getestet hab ichs mit dem Hook als string und als unbound-lambda oder lfun-closure im Master. Ich hab auch mal Laufzeitfehler im Hook erzeugt bzw. vom Hook selber Textausgaben gemacht (ergibt too-deep-recursion). Beides hat zumindest mal nicht gecrasht. Ciao, Zwirch PS: ich schick die Diffs auch noch an lars@bearnip ----------diffs------------- --- ldmud-164/src/comm.c Sat Dec 18 01:43:46 1999 +++ ldmud-164-outputhook/src/comm.c Tue Feb 8 12:42:57 2000 @@ -823,6 +823,61 @@ } /*-------------------------------------------------------------------------*/ + +char * +call_modify_output(char *buff) +/* Calls the H_MODIFY_OUTPUT-driverhook (if there is one). + * Returns an xalloced copy of the modified string or + * NULL if there was no hook. + * (The inputstring itself cannot be modified) + */ +{ + svalue_t *svp; + char *output; + + svp = NULL; + output=NULL; + + if (closure_hook[H_MODIFY_OUTPUT].type == T_CLOSURE) + { + lambda_t *l; + + l = closure_hook[H_MODIFY_OUTPUT].u.lambda; + if (closure_hook[H_MODIFY_OUTPUT].x.closure_type == CLOSURE_LAMBDA) + l->ob = command_giver; + push_volatile_string(buff); + push_object(command_giver); + call_lambda(&closure_hook[H_MODIFY_OUTPUT], 2); + transfer_svalue(svp = &apply_return_value, inter_sp--); + if (!command_giver) + return NULL; + } + else if (closure_hook[H_MODIFY_OUTPUT].type == T_STRING + && !(O_DESTRUCTED & command_giver->flags)) + { + push_volatile_string(buff); + svp = + sapply(closure_hook[H_MODIFY_OUTPUT].u.string, command_giver, 1); + if (!command_giver) + return NULL; + } + + /* If svp is not NULL, it contains the new, modified output. + */ + if (svp && svp->type == T_STRING) + { + output=xalloc(svalue_strlen(svp)+1); + if(!output) + { + error("Out of memory.\n"); + /* NOTREACHED */ + return NULL; + } + strcpy(output, svp->u.string); + } + return output; +} + void add_message (char *fmt, ...) @@ -870,6 +925,7 @@ * TODO: Actually, it is used just as a flag for flush/non-flush. */ int old_message_length; /* accumulated message length so far */ + char *tmp; char *source; /* Pointer to the final message to add */ char *end; /* One char past the end of .message_buf[] */ char *dest; /* First free char in .message_buf[] */ @@ -878,6 +934,7 @@ object_t *snooper; /* Snooper of <ip> */ int n; + tmp=NULL; va_start(va, fmt); /* Test if the command_giver is a real, living, undestructed user, @@ -950,7 +1007,6 @@ if (!sending_telnet_command) { - /* If there's a shadow successfully handling the * message, return. * This may cause a recursive call to add_message()!. @@ -959,6 +1015,13 @@ if (shadow_catch_message(command_giver, source)) return; + /* call the H_MODIFY_OUTPUT-hook + * If the hook modified the output we continue with + * the modified string + */ + if(tmp=call_modify_output(source)) + source=tmp; + /* If there's a snooper, send it the new message prepended * with a '%'. * For interactive snoopers this means a recursion with @@ -1118,6 +1181,7 @@ "%s comm: write EINTR. Message discarded.\n", time_stamp()); if (old_message_length) remove_flush_entry(ip); + if(tmp) xfree(tmp); return; case EWOULDBLOCK: @@ -1125,10 +1189,12 @@ "%s comm: write EWOULDBLOCK. Message discarded.\n", time_stamp()); if (old_message_length) remove_flush_entry(ip); + if(tmp) xfree(tmp); return; case EMSGSIZE: fprintf(stderr, "%s comm: write EMSGSIZE.\n", time_stamp()); + if(tmp) xfree(tmp); return; case EINVAL: @@ -1158,6 +1224,7 @@ if (old_message_length) remove_flush_entry(ip); ip->do_close = FLAG_DO_CLOSE; + if(tmp) xfree(tmp); return; } /* for (retries) */ @@ -1177,7 +1244,8 @@ } while (*source); /* --- Final touches --- */ - + if(tmp) xfree(tmp); + ip->message_length = length = dest - ip->message_buf; /* Update the ring of interactives with pending data */ --- ldmud-164/src/make_func.y Mon Dec 6 18:41:06 1999 +++ ldmud-164-outputhook/src/make_func.y Tue Feb 1 15:10:34 2000 @@ -1284,6 +1284,8 @@ return H_MODIFY_COMMAND_FNAME; if ( !strcmp(name, "COMMAND") ) return H_COMMAND; + if ( !strcmp(name, "MODIFY_OUTPUT") ) + return H_MODIFY_OUTPUT; return -1; } --- ldmud-164/src/prolang.y Fri Dec 17 02:05:54 1999 +++ ldmud-164-outputhook/src/prolang.y Tue Feb 1 14:40:42 2000 @@ -180,7 +180,7 @@ H_ERQ_STOP: SH(T_CLOSURE), \ H_MODIFY_COMMAND_FNAME: SH(T_STRING), \ H_COMMAND: SH(T_CLOSURE) SH(T_STRING), \ - + H_MODIFY_OUTPUT: SH(T_CLOSURE) SH(T_STRING), \ #undef SH /*-------------------------------------------------------------------------*/ --- ldmud-164/mudlib/sys/driver_hook.h Tue Sep 28 23:11:40 1999 +++ ldmud-164-outputhook/mudlib/sys/driver_hook.h Tue Feb 1 14:39:25 2000 @@ -22,8 +22,9 @@ #define H_ERQ_STOP 15 #define H_MODIFY_COMMAND_FNAME 16 #define H_COMMAND 17 +#define H_MODIFY_OUTPUT 18 -#define NUM_CLOSURE_HOOKS 18 /* Number of hooks */ +#define NUM_CLOSURE_HOOKS 19 /* Number of hooks */ #endif /* _DRIVER_HOOK_ */ ---------------------------