Author Topic: printable() sefun  (Read 1715 times)

Offline chaos

  • BFF
  • ***
  • Posts: 291
  • Job, school, social life, sleep. Pick 2.5.
    • View Profile
    • Lost Souls
printable() sefun
« on: June 16, 2008, 12:26:29 PM »
This is the printable() sefun that I used to be able to unconditionally come up with some at least marginally helpful debugging representation of an arbitrary value, mainly so that error messages will not ever themselves error out in generation and need not trouble themselves about type checking.  It is written for LDmud and refers to lib-specific functionality, but should be easily portable.  I post it mainly to facilitate posting other things that refer to it.

'man printable':
Quote
printable - returns a printable string corresponding to any input

SYNOPSIS
    string printable(mixed value)

DESCRIPTION
    May be passed any value, and is guaranteed to return a printable string,
    not of excessive length, which describes its input in some way, if only
    by its data type.

    Use of this function allows debug information regarding variables to
    be embedded in error messages and so forth without any fear that the
    execution will hit an error because of an unexpected data type in the
    variables or that the error message will be unreadable.

SEE ALSO
    raise_error(efun)

printable():
Code: [Select]
#include <lpctypes.h>

string printable(mixed value) {
    switch(typeof(value)) {
    case T_POINTER      :
        {
            object dmn = find_object(Daemon("descriptor"));
            if(dmn) {
                object def = dmn->identify_descriptor(value);
                if(def) {
                    string out = "<" + def->query_descriptor_name() + " descriptor/array[" + sizeof(value) + "]";
                    int array public_fields = def->query_descriptor_public_fields();
                    if(sizeof(public_fields)) {
                        int field = public_fields[0];
                        out += ", " + def->query_descriptor_field_name(field) + ": ";
                        mixed what = def->query(value, field);
                        if(what == value) {
                            out += "self";
                        } else {
                            string rep = printable(what);
                            if(strlen(rep) > 60)
                                rep = rep[..56] + "...";
                            out += rep;
                        }
                    }
                    out += ">";
                    return out;
                }
            }
            string out = "<array[" + sizeof(value) + "]";
            string sub = 0;
            foreach(mixed item : value) {
                string rep = printable(item);
                if(sub)
                    sub += ", " + rep;
                else
                    sub = rep;
                if(strlen(sub) > 60) {
                    sub = sub[..56] + "...";
                    break;
                }
            }
            if(sub && sub != "")
                out += ": ({ " + sub + " })";
            out += ">";
            return out;
        }
    case T_MAPPING      :
        {
            string out = "<mapping[" + sizeof(value) + "x" + widthof(value) + "]";
            string sub = 0;
            foreach(mixed key, mixed item : value) {
                string key_rep = printable(key);
                string item_rep = printable(item);
                if(sub)
                    sub += ", " + key_rep + " : " + item_rep;
                else
                    sub = key_rep + " : " + item_rep;
                if(strlen(sub) > 60) {
                    sub = sub[..56] + "...";
                    break;
                }
            }
            if(sub && sub != "")
                out += ": ([ " + sub + " ])";
            out += ">";
            return out;
        }
    case T_CLOSURE      :
        {
            int cltype = get_type_info(value, 1);
            status unbound;
            string array items = ({});
            if(CLOSURE_IS_LFUN(cltype)) {
                if(cltype & 1)
                    items += ({ "foreign" });
                items += ({ "lfun" });
            } else if(CLOSURE_IS_IDENTIFIER(cltype)) {
                items += ({ "identifier" });
            } else if(CLOSURE_IS_BOUND_LAMBDA(cltype)) {
            } else if(CLOSURE_IS_LAMBDA(cltype)) {
            } else if(CLOSURE_IS_UNBOUND_LAMBDA(cltype)) {
                unbound = True;
            } else if(CLOSURE_IS_SIMUL_EFUN(cltype)) {
                items += ({ "simul_efun" });
            } else if(CLOSURE_IS_EFUN(cltype)) {
                items += ({ "efun" });
            } else if(CLOSURE_IS_OPERATOR(cltype)) {
                items += ({ "operator" });
            } else {
                items += ({ "unknown" });
            }
            string what = to_string(value);
            if(what)
                items += ({ what });
            if(!unbound) {
                object bound = to_object(value);
                if(bound && bound != get_type_info(value, 2))
                    items += ({ "bound to " + project_file(bound) });
            }
            return "<closure: " + implode(items, " ") + ">";
        }
    case T_QUOTED_ARRAY :
        {
            int count = 0;
            do {
                value = unquote(value);
                count++;
            } while(!arrayp(value));
            string out = "<quoted array[" + sizeof(value) + ", " + count + "x]";
            string sub = 0;
            foreach(mixed item : value) {
                string rep = printable(item);
                if(sub)
                    sub += ", " + rep;
                else
                    sub = rep;
                if(strlen(sub) > 60) {
                    sub = sub[..56] + "...";
                    break;
                }
            }
            if(sub && sub != "")
                out += ": ({ " + sub + " })";
            out += ">";
            return out;
        }
    case T_SYMBOL       :
        {
            int count = 0;
            do {
                value = unquote(value);
                count++;
            } while(!stringp(value));
            return "<symbol[" + count + "x]: " + printable(value) + ">";
        }
    case T_OBJECT       :
        {
            string out = project_file(value);
            if(value->is_incarnos()) {
                string atman = value->query_atman_name();
                if(atman)
                    out += " (/usr/atman/" + atman + ")";
            }
            mixed ext = value->extends();
            if(ext && objectp(ext))
                out += " extending " + project_file(ext);
            return out;
        }
    case T_NUMBER       :
    case T_FLOAT        :
        return to_string(value);
    case T_STRING       :
        value = regreplace(value, "[\0x01-\0x1f{}]", (:
            switch($1) {
            case "\a" :
                return "\\a";
            case "\e" :
                return "\\e";
            case "\f" :
                return "\\f";
            case "\n" :
                return "\\n";
            case "\t" :
                return "\\t";
            case "\r" :
                return "\\r";
            case "{"  :
                return "\e{";
            case "}"  :
                return "\e}";
            default   :
                return sprintf("0x%02x", $1[0]);
            }
            return 0;
        :), 1);
        if(strlen(value) > 70)
            value = value[..66] + "...";
        return "\"" + value + "\"";
    default             :
        return "(type " + typeof(value) + ")";
    }
    return 0;
}