/
CDC-1.2b/
CDC-1.2b/src/
parent $libraries
object $arg_opts

var $root child_index 0
var $root owners [$arg_opts]
var $root fertile 1
var $root inited 1
var $root owned [$arg_opts]
var $arg_opts opt_rec []
var $root manager $arg_opts
var $root writable [$arg_opts]
var $root readable ['parameters, 'methods, 'code]
var $root dbref 'arg_opts

method from_str
    arg opt_str, [subs];
    var opts_given, opt_ret, opt, prefix, colon_pos, opt_val, match_opt, opt_type, opt_default, opt_trans_dict, opt_id;
    
    opts_given = explode(opt_str);
    opt_ret = #[];
    for opt in (opts_given) {
        switch (opt[1]) {
            case "!", "-":
                prefix = 'minus;
            case "+":
                prefix = 'plus;
            default:
                prefix = 'none;
        }
        if (prefix != 'none)
            opt = substr(opt, 2);
        colon_pos = ":" in opt;
        opt_val = prefix;
        if (colon_pos) {
            opt_val = substr(opt, colon_pos + 1);
            opt = substr(opt, 1, colon_pos - 1);
        }
        opt_id = 0;
        for match_opt in (opt_rec) {
            if (match_template(match_opt[2], opt)) {
                opt_type = match_opt[3];
                opt_default = match_opt[4];
                opt_trans_dict = match_opt[5];
                opt_id = match_opt[1];
                break;
    
                // out of for loop
            }
        }
        if (!opt_id)
            break;
        opt_val = ._get_opt_val(opt_val, opt_type, opt_default, opt_trans_dict, prefix);
        opt_val = ._val_subs(opt_val, opt_default, subs);
    
        // may throw duplicate key (which is ok)
        catch any {
            opt_ret = dict_add(opt_ret, opt_id, opt_val);
        }
    }
    
    // account for missing options:
    for match_opt in (opt_rec) {
        opt_id = match_opt[1];
        if (!(opt_id in dict_keys(opt_ret))) {
            opt_type = match_opt[3];
            opt_default = match_opt[4];
            if (opt_type == 'check_presence)
                opt_val = ['val, 0];
            else
                opt_val = opt_default;
            opt_val = ._val_subs(opt_val, opt_default, subs);
            opt_ret = dict_add(opt_ret, opt_id, opt_val);
        }
    }
    return opt_ret;
.

method _get_opt_val
    arg opt_val, opt_type, opt_default, opt_trans_dict, prefix;
    
    switch (opt_type) {
        case 'check_presence:
            opt_val = ['val, 1];
        case 'on_off_dict:
            opt_val = opt_trans_dict[prefix];
        case 'obj:
            if (opt_val)
                opt_val = ['val, (| get_objnum(tosym(substr(opt_val, 2))) |)];
            else
                opt_val = opt_default;
        case 'num:
            if (opt_val)
                opt_val = ['val, toint(opt_val)];
            else
                opt_val = opt_default;
        case 'obj_or_dict:
            if ((opt_val[1]) == "$") {
                // may throw namenf
                opt_val = (| get_objnum(tosym(substr(opt_val, 2))) |);
                opt_val = opt_val ? ['val, opt_val] | opt_default;
            } else {
                // may throw keynf
                opt_val = (| opt_trans_dict[opt_val] |) || opt_default;
            }
        default:
            opt_val = opt_default;
    }
    return opt_val;
.

method _val_subs
    arg opt_val, opt_default, subs;
    
    switch (opt_val[1]) {
        case 'sub:
            if (type(opt_val[2]) == 'integer) {
                if (((opt_val[2]) <= listlen(subs)) && ((opt_val[2]) > 0))
                    opt_val = subs[opt_val[2]];
                else
                    throw(~range, "Sub index out of range.");
            } else if (((opt_default[1]) != 'sub) || (type(opt_default[2]) == 'integer)) {
                opt_val = ((opt_default[1]) in ['sub, 'val]) ? ._val_subs(opt_default, opt_default, subs) | (opt_default[2]);
            }
        case 'val:
            opt_val = opt_val[2];
        default:
            opt_val = ((opt_default[1]) in ['sub, 'val]) ? ._val_subs(opt_default, opt_default, subs) | (opt_default[2]);
    }
    return opt_val;
.