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); }
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; }