The general solution to error handling is actually quite simple. I have thought about adding it, but never got around to it. 1. A new sub-type of int would be created called ERROR. 2. A new predicate function would exist called errorp(). 3. All efuns would return an int/error svalue when an error is detected during efun processing. 4. A new mudlib-imported error.h file would exist to define error numbers in terms of #defines (the #defines would be used in both the driver and mudlib code) 5. A function (call it perror()) would exist that accepted an error wvalue and returned a printable string. 6. All efuns would be converted to use these new error svalues and associated numbers. All mudlib code that did things that could error out would either: data = efun(..); if (!data-type-expectedp(data)) return; or: data = efun(..); if (errorp(data)) return; return would be replaced with whatever error recovery action would need to take place in that context. Errors could then be trated in an integrated fashion throughout the driver/mudlib. Cygnus Comment: Don't forget the perror() efun mentioned in the man page. ### I'm not sure this is the best way to go. -Beek ----- we need to made a single-user option for MudOS that doesn't use sockets at all so that people wanting to run MudOS at schools where programs aren't allowed to listen on socket (anti-mud policies) can use MudOS for developing LPC code for another mud. --john ----- From: John Garnett <garnett@gestalt.austin.tx.us> It'd be cool if there were efuns like this: mapping x; attach_mapping(mapping x, string filename); detach_mapping(x); which would attach mapping x to the database named by filename. any accesses to the mapping x would in fact manipulate the database. This would work much the way attached mappings work in Perl. We could use the dbm database code in UNIX(tm). Only problem is not all UNIX's have dbm's that support multiple databases per UNIX process. ----- In message <9303080120.AA26940@rock.concert.net> Dank writes: >powerful. This seems "grossly unfair" to our more serious gamers. That's >why i need to know the best way to implement (either in the driver or in LPC) >an hb_call_out() efun, that operates exactly as call_out() does, except that >it calls its function after a set number of _heartbeats_ have elapsed, not >after a set number of seconds. > I ran this by Mobydick, and he thought the solution should be sought from >you driver folks rather than in the mudlib (course, that may be because >he's a mudlib coder :) I agree; it does seem that we need a variant of call_out that operates in terms of number of heartbeats rather than absolute # of seconds. A few ways to do this. // optionally change the way call_out() works so that muds can change it if // they like. #define CALL_OUT_UNITS_EQUAL_HEARTBEAT /* or some shorter similar thing */ Or we could make a call_out2() efun that operates in the desired heartbeat units (name it something more appropriate than call_out2()). ----- 1) Have the z command in the editor check the user's PAGER settings. ie: getenv("LINES") much like the mudlib's more command does. If there isn't any setting, you can have it default back to the standard z length. --watcher ----- hmm, save_object() should probably somehow save the subtype of numbers. (ie null, undefined, error, etc) ucs_brf@pip.shsu.edu Comment: with some of the optimizations lately, the subtype of numbers is not always reliable longterm ... ----- An option for persistent swap files (that the driver can restore/recover from), saving clones and the contents of variables. ### This seems to be a fad and a bad idea, but I'll get flamed for saying that ... ----- mudlib_stats uses a linked list, it is fast for insertion; however lookup is O(n)...this should be hacked to use an AVL tree (ala uid.c) -- robo ----- #pragma no_inherit #pragma no_clone -- Cygnus & Descartes Comment: Unlike regular C, should these two pragmas should generate warnings (or error out) if the driver wasn't compiled with this option enabled? Also, adapt Tensor's idea for uniquep() efun...which queries these flags, telling whether an object is cloneable and/or inheritable (or not, depending on your point of view). These aren't object flags as first believed...they have to be stored in the program structure, so that it can be restored from binaries. pragma_no_inherit & pragma_no_clone flags should probably be in simulate.c, disjoint from those in lex.c. clone_object() ob = find_object_no_load() if (ob->prog->flags & P_NO_CLONE) error("Illegal object to clone\n"); find_object() find_object2() <- avoid calling this again (for performance) load_object() inheritance: (compiler/grammar & lpc_compiler/grammar) ob = find_object2() if (ob->prog->flags & P_NO_INHERIT) yyerror("Illegal object to inherit\n"); lex.c init pragma_no_inherit pragma_no_clone compiler/grammar & lpc_compiler/grammar set prog flags ----- Implement compile stacks so we don't have to dump an object (and later restart the compile) if an inherited object isn't defined yet. Note: This would entail requiring the use of bison or pre-yacc'ed grammars since most versions of yacc parsers aren't reentrant. -Beek Actually, I take this back. One could make the inherit rule look like: inheritance: type_modifier_list L_INHERIT string_con1 ';' { ... ob = find_object2(file); if (ob == 0) { push_compiler_globals(); lex_inherit_hook(file); } else { lex_loaded_inherit_hook(); } } program terminator { ... import symbols ... } terminator: L_ALREADY_LOADED | L_JUST_LOADED { pop_compiler_globals(); } etc ... lex_inherit_hook() cues lex to push it's globals and start a new file; lex_loaded_inherit_hook() cues lex to just return L_ALREADY_LOADED as the next token (note: in deep inherits this could require a rather deep yacc stack) Use parse trees to simplify compile time optimizations. Rewrite strings to use counted strings (strlen and refcount). Set up grammar dir for pre-byacc'd and/or pre-bison'd parsers for people with broken 'yacc's. Support L_ARRAY_CLOSE, L_FUNCTION_CLOSE, and L_MAPPING_CLOSE for consistency; L_MAPPING_CLOSE requires a bit more work... -- robo ----- Add an option to log the amount of input/output. -- Leto Comment: number of packets and total output is already logged; it's hidden off in a corner tho. A better interface for the mud info stuff, maybe? ----- Add params to call_out_info() to limit info to particular functions and/or objects. ----- Threads :) ----- Exceptions :) ----- Use shared string comparison in searching for commands ----- A make_mapping() efun that obeys the tautology: make_mapping( keys(m), values(m) ) == m ----- include_list() efun; also, BINARIES saves a list of includes, but error line numbers do as well; the former should be modified to use the latter's list (which was added after binaries were) ----- Anonymous functions which do not reference globals etc should be rebindable. Currently, non of the are, because the compile time checks aren't done. I.e. bind(function(int i){return i;}, this_player()) should work. ----- How about: private: int foo; void bar() { ... } need some way to turn it off, tho, since 'public' has a different meaning. (i.e. there is no specifier for the 'no modifier' state.) ----- varargs foo(int bar, int *rest ... ) foo(1, 2, 3) would give bar == 1, rest = ({ 2, 3 }) Also allow foo( ({ 1, 2 })... ) ? ----- foreach (i, x in ({ 1, 2 })) foreach (x in ([ 1 : 2, 3 : 4 ])) --- The handling of || and && is still suboptimal; it tests twice, and does a uneccessary pop for expressions like: (x && y); it completely blows it on expressions like 1 || 1 || 1;