To contents Next section

17.1 The master object

Pike is a very dynamic language. Sometimes that is not enough, sometimes you want to change the way Pike handles errors, loads modules or start scripts. All this and much more can be changed by modifying the master object. The master object is a Pike object like any other object, but it is loaded before anything else and is expected to perform certain things for the Pike executable. The Pike executable cannot function without a master object to take care of these things. Here is a list of the methods needed in the master object:
program cast_to_program(string program_name, string current_file)
This function is called whenever someone performs a cast from a string to a program.
program handle_inherit(string program_name, string current_file)
This is called whenever a Pike program which uses inherit with a string argument is called. It is expected to return the program to inherit.
void handle_error(array trace)
This function is expected to write the error messages when a run time error occurs. The argument is of the form ({"error_description", backtrace() }). If any error occurs in this routine Pike will dump core.
program cast_to_program(string program_name, string current_file)
This function is called whenever someone performs a cast from a string to an object.
mixed resolv(string identifier, string current_file)
This function is called whenever the compiler finds an unknown identifier in a program. It is normally used for loading modules. It is supposed to return ([])[0] if the master doesn't know what the value should be, and the value in question otherwise.
void _main(array(string) argv, array(string) env)
This function is supposed to start a Pike script. It receives all the command line arguments in the first array and all environment variables on the form "var=value". _main is called as soon as all modules and setup is done.
void compile_error(string file, int line, string err)
This function is called whenever a compile error is encountered. Normally it just writes a message to stderr.
string handle_include(string file, string current_file, int local_include)
This function is used to locate include files. file is the file name the user wants to include, and local_include is 1 if the user used double quotes rather than lesser-than, greater-than to quote the file name. Otherwise it is zero.

Aside from the above functions, which are expected from the Pike binary, the master object is also expected to provide functions used by Pike scripts. The current master object adds the following global functions:

add_include_path, remove_include_path, add_module_path, remove_module_path, add_program_path, remove_program_path, master, describe_backtrace, mkmultiset, strlen, new, clone, UNDEFINED, write, getenv and putenv.

There are at least two ways to change the behavior of the master object. (Except for editing it directly, which would cause other Pike scripts not to run in most cases.) You can either copy the master object, modify it and use the command line option -m to load your file instead of the default master object. However, since there might be more functionality added to the master object in the future I do not recommend this.

A better way is to write an object that inherits the master and then calls replace_master with the new object as argument. This should be far more future-safe. Although I can not guarantee that the interface between Pike and the master object will not change in the future, so be careful if you do this.

Let's look an example:

#!/usr/local/bin/pike

class new_master {
    inherit "/master";

    void create()
    {
        /* You need to copy the values from the old master to the new */
        /* NOTE: At this point we are still using the old master */
        object old_master = master();
        object new_master = this_object();

        foreach(indices(old_master), string varname)
        {
            /* The catch is needed since we can't assign constants */
            catch { new_master[varname] = old_master[varname]; };
        }
    }

    void handle_error(array trace)
    {
        Stdio.write_file("error log",describe_backtrace(trace));
    }
};

int main(int argc, array(string) argv)
{
    replace_master(new_master());
    /* Run rest of program */
    exit(0);
}
This example installs a master object which logs run time errors to file instead of writing them to stderr.


To contents Next section