diff --git a/lib/master.pike.in b/lib/master.pike.in index 96fd216e637343f5869bb832c9b2535d22d15aff..51ff0660e8e794a9889d7fb4349756211c0ea527 100644 --- a/lib/master.pike.in +++ b/lib/master.pike.in @@ -6,7 +6,7 @@ // Pike is distributed under GPL, LGPL and MPL. See the file COPYING // for more information. // -// $Id: master.pike.in,v 1.288 2003/06/05 13:11:13 mast Exp $ +// $Id: master.pike.in,v 1.289 2003/06/05 14:18:21 mast Exp $ #pike __REAL_VERSION__ @@ -1051,7 +1051,7 @@ class dirnode { resolv_debug ("dirnode(%O)->module_checker()->`!()\n",dirname); INC_RESOLV_MSG_DEPTH(); - if (catch { + if (mixed err = catch { if(module=findmodule(dirname+"/module", handler)) { if(mixed tmp=module->_module_value) @@ -1069,6 +1069,8 @@ class dirnode dirname, !module ? "doesn't exist" : "exists"); return !module; }) { + //werror ("findmodule error: " + describe_backtrace (err)); + // findmodule() failed. This can occur due to circularities // between encode_value()'ed programs. // The error will then typically be: @@ -1108,7 +1110,10 @@ class dirnode dirname, index, o); return o; } + resolv_debug ("dirnode(%O)->ind(%O) => not found in module\n", dirname, index); } + else + resolv_debug ("dirnode(%O)->ind(%O) => no module\n", dirname, index); if(!files) get_files(); @@ -1291,7 +1296,10 @@ class joinnode (ret->is_resolv_dirnode || ret->is_resolv_joinnode)) { // Only join directorynodes (or joinnodes). - res += ({ ret }); + if (ret->is_resolv_joinnode) + res += ret->joined_modules; + else + res += ({ ret }); } else if ( !zero_type(ret) ) { DEC_RESOLV_MSG_DEPTH(); resolv_debug ("joinnode(%O)->ind(%O) => found %O\n", @@ -1400,6 +1408,12 @@ class joinnode } } + int `== (mixed other) + { + return objectp (other) && other->is_resolv_joinnode && + equal (mkmultiset (joined_modules), mkmultiset (other->joined_modules)); + } + array(object) _encode() { return joined_modules; @@ -1674,7 +1688,10 @@ class CompatResolver if (mixed new_ret = ret->_module_value) { ret = new_ret; } - tmp += ({ ret }); + if (ret->is_resolv_joinnode) + tmp += ret->joined_modules; + else + tmp += ({ ret }); } else { if (mixed new_ret = ret->_module_value) { ret = new_ret; @@ -2661,8 +2678,8 @@ class Describer string program_path_to_name ( string path, - void|string module_prefix, void|string module_suffix, - void|string object_suffix ) + void|string module_prefix, void|string module_suffix, + void|string object_suffix ) //! Converts a module path on the form @expr{"Foo.pmod/Bar.pmod"@} or //! @expr{"/path/to/pike/lib/modules/Foo.pmod/Bar.pmod"@} to a module //! identifier on the form @expr{"Foo.Bar"@}. @@ -3170,6 +3187,7 @@ class Encoder //! //! 'c' Look up in all_constants(). //! 's' Look up in _static_modules. +//! 'r' Look up with resolv(). //! 'p' Look up in programs. //! 'o' Look up in programs, then look up the result in objects. //! 'f' Look up in fc. @@ -3178,6 +3196,7 @@ class Encoder //! the rest specify a series of things to do with the result: //! //! A string Look up this string in the result. +//! 'm' Get module object in dirnode. //! 'p' Do object_program(result). //! //! All lowercase letters and the symbols ':', '/' and '.' are @@ -3189,24 +3208,37 @@ class Encoder static mapping(mixed:string) rev_constants = ([]); static mapping(mixed:string) rev_static_modules = ([]); - static array find_index (object|program parent, mixed child) + static array find_index (object|program parent, mixed child, + array(object) module_object) { array id; find_id: { - array vals = values (parent); + array inds = indices (parent), vals = values (parent); int i = search (vals, child); - if (i >= 0) - id = ({indices (parent)[i]}); + if (i >= 0 && parent[inds[i]] == child) { + id = ({inds[i]}); + ENC_MSG (" found as parent value with index %O\n", id[0]); + } + else { // Try again with the programs of the objects in parent, since // it's common that only objects and not their programs are // accessible in modules. foreach (vals; i; mixed val) - if (objectp (val) && child == object_program (val)) { - id = ({indices (parent)[i], 'p'}); + if (objectp (val) && child == object_program (val) && + val == parent[inds[i]]) { + if (module_object) { + module_object[0] = val; + id = ({inds[i]}); + } + else + id = ({inds[i], 'p'}); + ENC_MSG (" found as program of parent value object %O with index %O\n", + val, id[0]); break find_id; } + error ("Cannot find %O in %O.\n", child, parent); } } @@ -3217,7 +3249,83 @@ class Encoder return id; } - string|array nameof (mixed what) + static string|array compare_resolved (string name, mixed what, + mixed resolved, array(object) module_object) + { + array append; + + compare: { + if (resolved == what) { + ENC_MSG (" compare_resolved: %O is %O\n", what, resolved); + break compare; + } + + if (objectp (resolved)) { + if (object_program (resolved) == what) { + ENC_MSG (" compare_resolved: %O is program of %O\n", what, resolved); + append = ({'p'}); + break compare; + } + + if (resolved->is_resolv_dirnode) + if (resolved->module == what) { + ENC_MSG (" compare_resolved: %O is dirnode module of %O\n", what, resolved); + append = ({'m'}); + resolved = resolved->module; + break compare; + } + else if (object_program (resolved->module) == what) { + ENC_MSG (" compare_resolved: %O is program of dirnode module of %O\n", + what, resolved); + append = ({'m', 'p'}); + break compare; + } + else + ENC_MSG (" compare_resolved: %O is different from dirnode module %O\n", + what, resolved->module); + +#if 0 + // This is only safe if the joinnode modules don't conflict, + // and we don't know that. + if (resolved->is_resolv_joinnode) { + ENC_MSG (" compare_resolved: searching for %O in joinnode %O\n", + what, resolved); + foreach (resolved->joined_modules, mixed part) + if (string|array name = compare_resolved (name, what, part, + module_object)) { + if (module_object) module_object[0] = resolved; + return name; + } + } +#endif + } + + ENC_MSG (" compare_resolved: %O is different from %O\n", what, resolved); + return 0; + } + + name = "r" + name; + string|array res = has_value (name, ".") ? name / "." : name; + + if (append) + if (module_object) { + // The caller is going to do subindexing. In both the 'p' and + // 'm' cases it's better to do that from the original + // object/dirnode, so just drop the suffixes. + module_object[0] = resolved; + return res; + } + else + return (arrayp (res) ? res : ({res})) + append; + else + return res; + } + + string|array nameof (mixed what, void|array(object) module_object) + //! When @[module_object] is set and the name would end with an + //! @expr{object_program@} step (i.e. @expr{'p'@}), then drop that + //! step so that the name corresponds to the object instead. + //! @expr{@[module_object][0]@} will receive the found object. { ENC_MSG ("nameof (%t %O)\n", what, what); @@ -3230,23 +3338,77 @@ class Encoder if (string id = rev_static_modules[what]) ENC_RETURN (id); if (objectp (what)) { - if (program prog = objects_reverse_lookup (what)) { + + if (what->is_resolv_dirnode) { + ENC_MSG (" is a dirnode\n"); + string name = program_path_to_name (what->dirname); + if (string|array ref = compare_resolved (name, what, resolv (name), + module_object)) + ENC_RETURN (ref); + } + + else if (what->is_resolv_joinnode) { + ENC_MSG (" is a joinnode\n"); + object modules = _static_modules.Builtin.array_iterator (what->joined_modules); + object|mapping value; + check_dirnode: + if (modules && objectp (value = modules->value()) && + value->is_resolv_dirnode) { + string name = program_path_to_name (value->dirname); + modules += 1; + foreach (modules;; value) + if (!objectp (value) || !value->is_resolv_dirnode || + program_path_to_name (value->dirname) != name) + break check_dirnode; + ENC_MSG (" joinnode has consistent name %O\n", name); + if (string|array ref = compare_resolved (name, what, resolv (name), + module_object)) + ENC_RETURN (ref); + } + } + + program prog; + if ((prog = objects_reverse_lookup (what))) + ENC_MSG (" found program in objects: %O\n", prog); +#if 0 + else if ((prog = object_program (what))) + ENC_MSG (" got program of object: %O\n", prog); +#endif + + if (prog) { if (prog == encoded) ENC_RETURN ("o"); if (string path = programs_reverse_lookup (prog)) { + ENC_MSG (" found path in programs: %O\n", path); + string name = program_path_to_name (path); + if (string|array ref = compare_resolved (name, + what->_module_value || what, + resolv (name), module_object)) + ENC_RETURN (ref); + else { + ENC_MSG (" Warning: Failed to resolve; encoding path\n"); #ifdef PIKE_MODULE_RELOC - ENC_RETURN ("o" + unrelocate_module (path)); + ENC_RETURN ("o" + unrelocate_module (path)); #else - ENC_RETURN ("o" + path); + ENC_RETURN ("o" + path); #endif + } } } if (string path = fc_reverse_lookup (what)) { + ENC_MSG (" found path in fc: %O\n", path); + string name = program_path_to_name (path); + if (string|array ref = compare_resolved (name, what, resolv (name), + module_object)) + ENC_RETURN (ref); + else { + ENC_MSG (" Warning: Failed to resolve; encoding path\n"); #ifdef PIKE_MODULE_RELOC - ENC_RETURN ("f" + unrelocate_module (path)); + ENC_RETURN ("f" + unrelocate_module (path)); #else - ENC_RETURN ("f" + path); + ENC_RETURN ("f" + path); #endif + } } if (what->_encode) { @@ -3254,60 +3416,87 @@ class Encoder return UNDEFINED; } - if (function|program prog = object_program (what)) + if (function|program prog = object_program (what)) { + ENC_MSG (" got program of object: %O\n", prog); if (object|program parent = function_object (prog) || function_program (prog)) { - string|array parent_name = nameof (parent); + ENC_MSG (" got parent of program: %O\n", parent); + // We're going to subindex the parent so we ask for the + // module object and not the program. That since we'll + // always be able to do a better job if we base the indexing + // on objects. + array parent_object = ({0}); + string|array parent_name = nameof (parent, parent_object); if (!parent_name) { ENC_MSG (" inside the thing to encode - encoding recursively\n"); return UNDEFINED; } else { - // If we did an object_program step in the recursive nameof to get - // the parent then we'll always be able to do a better job if we - // base the indexing on the corresponding object instead. - -#define CONVERT_PARENT_TO_OBJ(parent_name, parent) \ - if (arrayp (parent_name) && parent_name[-1] == 'p') { \ - object|program grandparent = \ - objectp (parent) ? object_program (parent) : parent; \ - grandparent = \ - function_object (grandparent) || function_program (grandparent); \ - parent = grandparent[parent_name[-2]]; \ - parent_name = parent_name[..sizeof (parent_name) - 2]; \ - } - - CONVERT_PARENT_TO_OBJ (parent_name, parent); - array id = find_index (parent, what); - ENC_RETURN ((arrayp (parent_name) ? parent_name : ({parent_name})) + id); + if (objectp (parent_object[0])) parent = parent_object[0]; + array id = find_index (parent, what, module_object); + if (equal (id, ({"_module_value"}))) + ENC_RETURN (parent_name); + else + ENC_RETURN ((arrayp (parent_name) ? parent_name : ({parent_name})) + id); } } + } error ("Failed to find name of unencodable object %O.\n", what); } if (programp (what) || functionp (what)) { if (string path = programs_reverse_lookup (what)) { + ENC_MSG (" found path in programs: %O\n", path); + string name = program_path_to_name (path); + if (string|array ref = compare_resolved (name, what, resolv (name), + module_object)) + ENC_RETURN (ref); + else { + ENC_MSG (" Warning: Failed to resolve; encoding path\n"); #ifdef PIKE_MODULE_RELOC - ENC_RETURN ("p" + unrelocate_module (path)); + ENC_RETURN ("p" + unrelocate_module (path)); #else - ENC_RETURN ("p" + path); + ENC_RETURN ("p" + path); #endif + } } if (object|program parent = function_object (what) || function_program (what)) { - string|array parent_name = nameof (parent); + ENC_MSG (" got parent: %O\n", parent); + if (!objectp (parent)) { + object parent_obj = objects[parent]; + if (objectp (parent_obj)) { + ENC_MSG (" found object for parent program in objects: %O\n", parent_obj); + parent = parent_obj; + } + } + + array parent_object = ({0}); + string|array parent_name = nameof (parent, parent_object); if (!parent_name) { ENC_MSG (" inside the thing to encode - encoding recursively\n"); return UNDEFINED; } + else { - string|array id = function_name (what); - if (stringp (id)) id = ({id}); + if (objectp (parent_object[0])) parent = parent_object[0]; + if (parent["_module_value"] == what && objects_reverse_lookup (parent)) { + ENC_MSG (" found as _module_value of parent module\n"); + ENC_RETURN (parent_name); + } else { - CONVERT_PARENT_TO_OBJ (parent_name, parent); - id = find_index (parent, what); + string|array id = function_name (what); + if (stringp (id) && parent[id] == what) { + ENC_MSG (" found function name in parent: %O\n", id); + id = ({id}); + } + else + id = find_index (parent, what, module_object); + if (equal (id, ({"_module_value"}))) + ENC_RETURN (parent_name); + else + ENC_RETURN ((arrayp (parent_name) ? parent_name : ({parent_name})) + id); } - ENC_RETURN ((arrayp (parent_name) ? parent_name : ({parent_name})) + id); } } @@ -3395,6 +3584,10 @@ class Decoder (void|string fname, void|int mkobj) if (zero_type (res = _static_modules[what[1..]])) error ("Cannot find %O in _static_modules.\n", what[1..]); break; + case 'r': + if (zero_type (res = resolv (what[1..]))) + error ("Cannot resolve %O.\n", what[1..]); + break; case 'p': if (!(res = low_cast_to_program (what[1..], fname, this))) error ("Cannot find program for %O.\n", what[1..]); @@ -3409,6 +3602,8 @@ class Decoder (void|string fname, void|int mkobj) break; } + DEC_MSG (" got %O\n", res); + if (sublist) { mixed subres = res; for (int i = 1; i < sizeof (sublist); i++) { @@ -3420,11 +3615,45 @@ class Decoder (void|string fname, void|int mkobj) if (zero_type (subres = subres[op])) error ("Cannot find %O in %O%{[%O]%}.\n", op, res, sublist[1..i-1]); + DEC_MSG (" indexed with %O: %O\n", op, subres); + } + else switch (op) { + case 'm': + if (objectp (subres) && subres->is_resolv_joinnode) { + dirnode found; + foreach (subres->joined_modules, object|mapping part) + if (objectp (part) && part->is_resolv_dirnode && part->module) { + if (found) + error ("There are ambiguous module objects in %O.\n", + subres); + else + found = part; + } + if (found) subres = found; + } + + if (objectp (subres) && subres->is_resolv_dirnode) { + if (subres->module) { + subres = subres->module; + DEC_MSG (" got dirnode module %O\n", subres); + } + else + error ("Cannot find module object in dirnode %O.\n", subres); + } + else + error ("Cannot get module object in thing that isn't " + "a dirnode or unambiguous joinnode: %O\n", subres); + + break; + + case 'p': + subres = object_program (subres); + DEC_MSG (" got object_program %O\n", subres); + break; + + default: + error ("Unknown sublist operation %O in %O\n", op, what); } - else if (op == 'p') - subres = object_program (subres); - else - error ("Unknown sublist operation %O in %O\n", op, what); } res = subres; } @@ -3435,25 +3664,19 @@ class Decoder (void|string fname, void|int mkobj) object objectof (string|array what) { DEC_MSG ("objectof (%O)\n", what); - mixed res = thingof (what); - if (!objectp (res)) error ("Expected object for %O, got %O.\n", what, res); - DEC_RETURN ([object] res); + DEC_RETURN ([object] thingof (what)); } function functionof (string|array what) { DEC_MSG ("functionof (%O)\n", what); - mixed res = thingof (what); - if (!functionp (res)) error ("Expected function for %O, got %O.\n", what, res); - DEC_RETURN ([function] res); + DEC_RETURN ([function] thingof (what)); } program programof (string|array what) { DEC_MSG ("programof (%O)\n", what); - mixed res = thingof (what); - if (!programp (res)) error ("Expected program for %O, got %O.\n", what, res); - DEC_RETURN ([program] res); + DEC_RETURN ([program] thingof (what)); } void decode_object(object o, mixed data) @@ -3490,6 +3713,9 @@ class Codec } } +// The master acts as the default codec. +inherit Codec; + //! Contains version information about a Pike version. class Version