void
relay_weechat_msg_add_hdata (struct t_relay_weechat_msg *msg,
                             const char *path, const char *keys)
{
    struct t_hdata *ptr_hdata_head, *ptr_hdata;
    char *hdata_head, *pos, **list_keys, *keys_types, **list_path;
    char *path_returned;
    const char *hdata_name, *array_size;
    void *pointer, **path_pointers;
    long unsigned int value;
    int num_keys, num_path, i, type, pos_count, count, rc;
    uint32_t count32;

    hdata_head = NULL;
    list_keys = NULL;
    num_keys = 0;
    keys_types = NULL;
    list_path = NULL;
    num_path = 0;
    path_returned = NULL;

    /* extract hdata name (head) from path */
    pos = strchr (path, ':');
    if (!pos)
        goto end;
    hdata_head = weechat_strndup (path, pos - path);
    if (!hdata_head)
        goto end;
    ptr_hdata_head = weechat_hdata_get (hdata_head);
    if (!ptr_hdata_head)
        goto end;

    /* split path */
    list_path = weechat_string_split (pos + 1, "/", 0, 0, &num_path);
    if (!list_path)
        goto end;

    /* extract pointer from first path (direct pointer or list name) */
    pointer = NULL;
    pos = strchr (list_path[0], '(');
    if (pos)
        pos[0] = '\0';
    if (strncmp (list_path[0], "0x", 2) == 0)
    {
        rc = sscanf (list_path[0], "%lx", &value);
        if ((rc != EOF) && (rc != 0))
            pointer = (void *)value;
    }
    else
        pointer = weechat_hdata_get_list (ptr_hdata_head, list_path[0]);
    if (pos)
        pos[0] = '(';
    if (!pointer)
        goto end;

    /*
     * build string with path where:
     * - counters are removed
     * - variable names are replaced by hdata name
     */
    path_returned = malloc (strlen (path) * 2);
    if (!path_returned)
        goto end;
    ptr_hdata = ptr_hdata_head;
    strcpy (path_returned, hdata_head);
    hdata_name = hdata_head;
    for (i = 1; i < num_path; i++)
    {
        pos = strchr (list_path[i], '(');
        if (pos)
            pos[0] = '\0';
        hdata_name = weechat_hdata_get_var_hdata (ptr_hdata, list_path[i]);
        if (!hdata_name)
            goto end;
        ptr_hdata = weechat_hdata_get (hdata_name);
        if (!ptr_hdata)
            goto end;
        strcat (path_returned, "/");
        strcat (path_returned, hdata_name);
        if (pos)
            pos[0] = '(';
    }

    /* split keys */
    if (!keys)
        keys = weechat_hdata_get_string (ptr_hdata, "var_keys");
    list_keys = weechat_string_split (keys, ",", 0, 0, &num_keys);
    if (!list_keys)
        goto end;

    /* build string with list of keys with types: "key1:type1,key2:type2,..." */
    keys_types = malloc (strlen (keys) + (num_keys * 8) + 1);
    if (!keys_types)
        goto end;
    keys_types[0] = '\0';
    for (i = 0; i < num_keys; i++)
    {
        type = weechat_hdata_get_var_type (ptr_hdata, list_keys[i]);
        if ((type >= 0) && (type != WEECHAT_HDATA_OTHER))
        {
            if (keys_types[0])
                strcat (keys_types, ",");
            strcat (keys_types, list_keys[i]);
            strcat (keys_types, ":");
            array_size = weechat_hdata_get_var_array_size_string (ptr_hdata,
                                                                  NULL,
                                                                  list_keys[i]);
            if (array_size)
                strcat (keys_types, RELAY_WEECHAT_MSG_OBJ_ARRAY);
            else
            {
                switch (type)
                {
                    case WEECHAT_HDATA_CHAR:
                        strcat (keys_types, RELAY_WEECHAT_MSG_OBJ_CHAR);
                        break;
                    case WEECHAT_HDATA_INTEGER:
                        strcat (keys_types, RELAY_WEECHAT_MSG_OBJ_INT);
                        break;
                    case WEECHAT_HDATA_LONG:
                        strcat (keys_types, RELAY_WEECHAT_MSG_OBJ_LONG);
                        break;
                    case WEECHAT_HDATA_STRING:
                        strcat (keys_types, RELAY_WEECHAT_MSG_OBJ_STRING);
                        break;
                    case WEECHAT_HDATA_POINTER:
                        strcat (keys_types, RELAY_WEECHAT_MSG_OBJ_POINTER);
                        break;
                    case WEECHAT_HDATA_TIME:
                        strcat (keys_types, RELAY_WEECHAT_MSG_OBJ_TIME);
                        break;
                    case WEECHAT_HDATA_HASHTABLE:
                        strcat (keys_types, RELAY_WEECHAT_MSG_OBJ_HASHTABLE);
                        break;
                }
            }
        }
    }
    if (!keys_types[0])
        goto end;

    /* start hdata in message */
    relay_weechat_msg_add_type (msg, RELAY_WEECHAT_MSG_OBJ_HDATA);
    relay_weechat_msg_add_string (msg, path_returned);
    relay_weechat_msg_add_string (msg, keys_types);

    /* "count" will be set later, with number of objects in hdata */
    pos_count = msg->data_size;
    count = 0;
    relay_weechat_msg_add_int (msg, 0);
    path_pointers = malloc (sizeof (*path_pointers) * num_path);
    if (path_pointers)
    {
        count = relay_weechat_msg_add_hdata_path (msg,
                                                  list_path,
                                                  0,
                                                  path_pointers,
                                                  ptr_hdata_head,
                                                  pointer,
                                                  list_keys);
        free (path_pointers);
    }
    count32 = htonl ((uint32_t)count);
    relay_weechat_msg_set_bytes (msg, pos_count, &count32, 4);

end:
    if (list_keys)
        weechat_string_free_split (list_keys);
    if (keys_types)
        free (keys_types);
    if (list_path)
        weechat_string_free_split (list_path);
    if (path_returned)
        free (path_returned);
    if (hdata_head)
        free (hdata_head);
}
Beispiel #2
0
struct t_weelist *
script_buffer_get_script_usage (struct t_script_repo *script)
{
    struct t_weelist *list;
    char hdata_name[128], str_option[256], str_info[1024];
    int config_files;
    const char *ptr_name_hdata_callback, *type;
    struct t_hdata *ptr_hdata_script, *ptr_hdata_callback;
    struct t_hdata *ptr_hdata_config_file, *ptr_hdata_bar_item;
    void *ptr_script, *ptr_callback;
    struct t_config_file *ptr_config_file;
    struct t_hook *ptr_hook;
    struct t_gui_bar_item *ptr_bar_item;
    struct t_infolist *infolist;

    config_files = 0;

    snprintf (hdata_name, sizeof (hdata_name),
              "%s_script", script_language[script->language]);
    ptr_hdata_script = weechat_hdata_get (hdata_name);
    if (!ptr_hdata_script)
        return NULL;

    ptr_script = script_buffer_get_script_pointer (script, ptr_hdata_script);
    if (!ptr_script)
        return NULL;

    ptr_name_hdata_callback = weechat_hdata_get_var_hdata (ptr_hdata_script,
                                                           "callbacks");
    if (!ptr_name_hdata_callback)
        return NULL;
    ptr_hdata_callback = weechat_hdata_get (ptr_name_hdata_callback);
    if (!ptr_hdata_callback)
        return NULL;

    list = weechat_list_new ();

    ptr_hdata_config_file = weechat_hdata_get ("config_file");
    ptr_hdata_bar_item = weechat_hdata_get ("bar_item");

    ptr_callback = weechat_hdata_pointer (ptr_hdata_script,
                                          ptr_script,
                                          "callbacks");
    while (ptr_callback)
    {
        str_info[0] = '\0';
        ptr_config_file = weechat_hdata_pointer (ptr_hdata_callback,
                                                 ptr_callback,
                                                 "config_file");
        ptr_hook = weechat_hdata_pointer (ptr_hdata_callback,
                                          ptr_callback,
                                          "hook");
        ptr_bar_item = weechat_hdata_pointer (ptr_hdata_callback,
                                              ptr_callback,
                                              "bar_item");
        if (ptr_config_file)
        {
            snprintf (str_info, sizeof (str_info),
                      _("configuration file \"%s\" (options %s.*)"),
                      weechat_hdata_string (ptr_hdata_config_file,
                                            ptr_config_file,
                                            "filename"),
                      weechat_hdata_string (ptr_hdata_config_file,
                                            ptr_config_file,
                                            "name"));
            config_files++;
        }
        else if (ptr_hook)
        {
            infolist = weechat_infolist_get ("hook", ptr_hook, NULL);
            if (infolist)
            {
                if (weechat_infolist_next (infolist))
                {
                    type = weechat_infolist_string (infolist, "type");
                    if (type)
                    {
                        if (strcmp (type, "command") == 0)
                        {
                            snprintf (str_info, sizeof (str_info),
                                      _("command /%s"),
                                      weechat_infolist_string (infolist,
                                                               "command"));
                        }
                        else if (strcmp (type, "completion") == 0)
                        {
                            snprintf (str_info, sizeof (str_info),
                                      _("completion %%(%s)"),
                                      weechat_infolist_string (infolist,
                                                               "completion_item"));
                        }
                        else if (strcmp (type, "info") == 0)
                        {
                            snprintf (str_info, sizeof (str_info),
                                      "info \"%s\"",
                                      weechat_infolist_string (infolist,
                                                               "info_name"));
                        }
                        else if (strcmp (type, "info_hashtable") == 0)
                        {
                            snprintf (str_info, sizeof (str_info),
                                      "info_hashtable \"%s\"",
                                      weechat_infolist_string (infolist,
                                                               "info_name"));
                        }
                        else if (strcmp (type, "infolist") == 0)
                        {
                            snprintf (str_info, sizeof (str_info),
                                      "infolist \"%s\"",
                                      weechat_infolist_string (infolist,
                                                               "infolist_name"));
                        }
                    }
                }
                weechat_infolist_free (infolist);
            }
        }
        else if (ptr_bar_item)
        {
            snprintf (str_info, sizeof (str_info),
                      _("bar item \"%s\""),
                      weechat_hdata_string (ptr_hdata_bar_item,
                                            ptr_bar_item,
                                            "name"));
        }
        if (str_info[0])
        {
            weechat_list_add (list, str_info,
                              WEECHAT_LIST_POS_END, NULL);
        }
        ptr_callback = weechat_hdata_move (ptr_hdata_callback,
                                           ptr_callback,
                                           1);
    }

    snprintf (str_option, sizeof (str_option),
              "plugins.var.%s.%s.*",
              script_language[script->language],
              weechat_hdata_string (ptr_hdata_script, ptr_script, "name"));
    infolist = weechat_infolist_get ("option", NULL, str_option);
    if (infolist)
    {
        if (weechat_infolist_next (infolist))
        {
            snprintf (str_info, sizeof (str_info),
                      _("options %s%s%s"),
                      str_option,
                      (config_files > 0) ? " " : "",
                      (config_files > 0) ? _("(old options?)") : "");
            weechat_list_add (list, str_info,
                              WEECHAT_LIST_POS_END, NULL);
        }
        weechat_infolist_free (infolist);
    }

    return list;
}
int
relay_weechat_msg_add_hdata_path (struct t_relay_weechat_msg *msg,
                                  char **list_path,
                                  int index_path,
                                  void **path_pointers,
                                  struct t_hdata *hdata,
                                  void *pointer,
                                  char **list_keys)
{
    int num_added, i, j, count, count_all, var_type, array_size, max_array_size;
    int length;
    char *pos, *pos2, *str_count, *error, *name;
    void *sub_pointer;
    struct t_hdata *sub_hdata;
    const char *sub_hdata_name;

    num_added = 0;

    count_all = 0;
    count = 0;
    pos = strchr (list_path[index_path], '(');
    if (pos)
    {
        pos2 = strchr (pos + 1, ')');
        if (pos2 && (pos2 > pos + 1))
        {
            str_count = weechat_strndup (pos + 1, pos2 - (pos + 1));
            if (str_count)
            {
                if (strcmp (str_count, "*") == 0)
                    count_all = 1;
                else
                {
                    error = NULL;
                    count = (int)strtol (str_count, &error, 10);
                    if (error && !error[0])
                    {
                        if (count > 0)
                            count--;
                        else if (count < 0)
                            count++;
                    }
                    else
                        count = 0;
                }
                free (str_count);
            }
        }
    }

    while (pointer)
    {
        path_pointers[index_path] = pointer;

        if (list_path[index_path + 1])
        {
            /* recursive call with next path */
            pos = strchr (list_path[index_path + 1], '(');
            if (pos)
                pos[0] = '\0';
            sub_pointer = weechat_hdata_pointer (hdata, pointer, list_path[index_path + 1]);
            sub_hdata_name = weechat_hdata_get_var_hdata (hdata, list_path[index_path + 1]);
            if (pos)
                pos[0] = '(';
            if (sub_pointer && sub_hdata_name)
            {
                sub_hdata = weechat_hdata_get (sub_hdata_name);
                if (sub_hdata)
                {
                    num_added += relay_weechat_msg_add_hdata_path (msg,
                                                                   list_path,
                                                                   index_path + 1,
                                                                   path_pointers,
                                                                   sub_hdata,
                                                                   sub_pointer,
                                                                   list_keys);
                }
            }
        }
        else
        {
            /* last path? then get pointer + values and fill message with them */
            for (i = 0; list_path[i]; i++)
            {
                relay_weechat_msg_add_pointer (msg, path_pointers[i]);
            }
            for (i = 0; list_keys[i]; i++)
            {
                var_type = weechat_hdata_get_var_type (hdata, list_keys[i]);
                if ((var_type >= 0) && (var_type != WEECHAT_HDATA_OTHER))
                {
                    max_array_size = 1;
                    array_size = weechat_hdata_get_var_array_size (hdata,
                                                                   pointer,
                                                                   list_keys[i]);
                    if (array_size >= 0)
                    {
                        switch (var_type)
                        {
                            case WEECHAT_HDATA_CHAR:
                                relay_weechat_msg_add_type (msg, RELAY_WEECHAT_MSG_OBJ_CHAR);
                                break;
                            case WEECHAT_HDATA_INTEGER:
                                relay_weechat_msg_add_type (msg, RELAY_WEECHAT_MSG_OBJ_INT);
                                break;
                            case WEECHAT_HDATA_LONG:
                                relay_weechat_msg_add_type (msg, RELAY_WEECHAT_MSG_OBJ_LONG);
                                break;
                            case WEECHAT_HDATA_STRING:
                                relay_weechat_msg_add_type (msg, RELAY_WEECHAT_MSG_OBJ_STRING);
                                break;
                            case WEECHAT_HDATA_POINTER:
                                relay_weechat_msg_add_type (msg, RELAY_WEECHAT_MSG_OBJ_POINTER);
                                break;
                            case WEECHAT_HDATA_TIME:
                                relay_weechat_msg_add_type (msg, RELAY_WEECHAT_MSG_OBJ_TIME);
                                break;
                            case WEECHAT_HDATA_HASHTABLE:
                                relay_weechat_msg_add_type (msg, RELAY_WEECHAT_MSG_OBJ_HASHTABLE);
                                break;
                        }
                        relay_weechat_msg_add_int (msg, array_size);
                        max_array_size = array_size;
                    }
                    length = 16 + strlen (list_keys[i]) + 1;
                    name = malloc (length);
                    if (name)
                    {
                        for (j = 0; j < max_array_size; j++)
                        {
                            snprintf (name, length, "%d|%s", j, list_keys[i]);
                            switch (var_type)
                            {
                                case WEECHAT_HDATA_CHAR:
                                    relay_weechat_msg_add_char (msg,
                                                                weechat_hdata_char (hdata,
                                                                                    pointer,
                                                                                    name));
                                    break;
                                case WEECHAT_HDATA_INTEGER:
                                    relay_weechat_msg_add_int (msg,
                                                               weechat_hdata_integer (hdata,
                                                                                      pointer,
                                                                                      name));
                                    break;
                                case WEECHAT_HDATA_LONG:
                                    relay_weechat_msg_add_long (msg,
                                                                weechat_hdata_long (hdata,
                                                                                    pointer,
                                                                                    name));
                                    break;
                                case WEECHAT_HDATA_STRING:
                                    relay_weechat_msg_add_string (msg,
                                                                  weechat_hdata_string (hdata,
                                                                                        pointer,
                                                                                        name));
                                    break;
                                case WEECHAT_HDATA_POINTER:
                                    relay_weechat_msg_add_pointer (msg,
                                                                   weechat_hdata_pointer (hdata,
                                                                                          pointer,
                                                                                          name));
                                    break;
                                case WEECHAT_HDATA_TIME:
                                    relay_weechat_msg_add_time (msg,
                                                                weechat_hdata_time (hdata,
                                                                                    pointer,
                                                                                    name));
                                    break;
                                case WEECHAT_HDATA_HASHTABLE:
                                    relay_weechat_msg_add_hashtable (msg,
                                                                     weechat_hdata_hashtable (hdata,
                                                                                              pointer,
                                                                                              name));
                                    break;
                            }
                        }
                        free (name);
                    }
                }
            }
            num_added++;
        }
        if (count_all)
        {
            pointer = weechat_hdata_move (hdata, pointer, 1);
        }
        else if (count == 0)
            pointer = NULL;
        else if (count > 0)
        {
            pointer = weechat_hdata_move (hdata, pointer, 1);
            count--;
        }
        else
        {
            pointer = weechat_hdata_move (hdata, pointer, -1);
            count++;
        }
        if (!pointer)
            break;
    }

    return num_added;
}