More lua stuff.
authorBrenden Matthews <brenden@rty.ca>
Sat, 16 May 2009 23:04:26 +0000 (17:04 -0600)
committerBrenden Matthews <brenden@rty.ca>
Sat, 16 May 2009 23:04:26 +0000 (17:04 -0600)
doc/variables.xml
src/conky.c
src/llua.c
src/llua.h
src/text_object.h

index 1cd145f..35e9bf2 100644 (file)
                        <option>function_name (function parameters)</option>
                </term>
                <listitem>
-                       Executes a Lua function with given parameters and prints the result value.  See also 'lua_load' on how to load scripts.
+                       Executes a Lua function with given parameters, then prints the returned string.  See also 'lua_load' on how to load scripts.
+                       <para></para></listitem>
+       </varlistentry>
+
+       <varlistentry>
+               <term>
+                       <command><option>lua_parse</option></command>
+                       <option>function_name (function parameters)</option>
+               </term>
+               <listitem>
+                       Executes a Lua function with given parameters as per $lua, then parses and prints the result value as per the syntax for Conky's TEXT section.  See also 'lua_load' on how to load scripts.
+                       <para></para></listitem>
+       </varlistentry>
+
+       <varlistentry>
+               <term>
+                       <command><option>lua_read</option></command>
+                       <option>function_name (conky text)</option>
+               </term>
+               <listitem>
+                       Executes a Lua function per $lua, except takes a 2nd argument which is first evaluated as per Conky's TEXT section and passed to the function first.  The return value is then parsed and prints the result value as per the syntax for Conky's TEXT section.  See also 'lua_load' on how to load scripts.
                        <para></para></listitem>
        </varlistentry>
 
index 368731e..cd234c7 100644 (file)
@@ -631,8 +631,11 @@ static struct text_object *new_text_object_internal(void)
        return obj;
 }
 
-/* free the list of text objects root points to */
-static void free_text_objects(struct text_object *root)
+/*
+ * Frees the list of text objects root points to.  When internal = 1, it won't
+ * free global objects.
+ */
+static void free_text_objects(struct text_object *root, int internal)
 {
        struct text_object *obj;
 
@@ -704,7 +707,7 @@ static void free_text_objects(struct text_object *root)
                                break;
                        case OBJ_if_empty:
                        case OBJ_if_match:
-                               free_text_objects(obj->sub);
+                               free_text_objects(obj->sub, 1);
                                free(obj->sub);
                                /* fall through */
                        case OBJ_if_existing:
@@ -854,6 +857,8 @@ static void free_text_objects(struct text_object *root)
 #endif
 #ifdef HAVE_LUA
                        case OBJ_lua:
+                       case OBJ_lua_parse:
+                       case OBJ_lua_read_parse:
 #ifdef X11
                        case OBJ_lua_bar:
                        case OBJ_lua_graph:
@@ -895,10 +900,11 @@ static void free_text_objects(struct text_object *root)
                        case OBJ_top:
                        case OBJ_top_mem:
                        case OBJ_top_time:
-                               if (info.first_process) {
+                               if (info.first_process && !internal) {
                                        free_all_processes();
                                        info.first_process = NULL;
                                }
+                               if (data.top.s) free(data.top.s);
                                break;
 #ifdef HDDTEMP
                        case OBJ_hddtemp:
@@ -988,14 +994,14 @@ static void free_text_objects(struct text_object *root)
 #endif
                        case OBJ_scroll:
                                free(data.scroll.text);
-                               free_text_objects(obj->sub);
+                               free_text_objects(obj->sub, 1);
                                free(obj->sub);
                                break;
                        case OBJ_combine:
                                free(data.combine.left);
                                free(data.combine.seperation);
                                free(data.combine.right);
-                               free_text_objects(obj->sub);
+                               free_text_objects(obj->sub, 1);
                                free(obj->sub);
                                break;
 #ifdef APCUPSD
@@ -1063,6 +1069,74 @@ static const char *dev_name(const char *path)
 #undef DEV_NAME
 }
 
+static int parse_top_args(const char *s, const char *arg, struct text_object *obj)
+{
+       char buf[64];
+       int n;
+
+       if (obj->data.top.was_parsed) {
+               return 1;
+       }
+       obj->data.top.was_parsed = 1;
+
+       if (arg && !obj->data.top.s) {
+               obj->data.top.s = strndup(arg, text_buffer_size);
+       }
+
+       need_mask |= (1 << INFO_TOP);
+
+       if (s[3] == 0) {
+               obj->type = OBJ_top;
+               top_cpu = 1;
+       } else if (strcmp(&s[3], "_mem") == EQUAL) {
+               obj->type = OBJ_top_mem;
+               top_mem = 1;
+       } else if (strcmp(&s[3], "_time") == EQUAL) {
+               obj->type = OBJ_top_time;
+               top_time = 1;
+       } else {
+               ERR("Must be top, top_mem or top_time");
+               return 0;
+       }
+
+       if (!arg) {
+               ERR("top needs arguments");
+               return 0;
+       }
+
+       if (sscanf(arg, "%63s %i", buf, &n) == 2) {
+               if (strcmp(buf, "name") == EQUAL) {
+                       obj->data.top.type = TOP_NAME;
+               } else if (strcmp(buf, "cpu") == EQUAL) {
+                       obj->data.top.type = TOP_CPU;
+               } else if (strcmp(buf, "pid") == EQUAL) {
+                       obj->data.top.type = TOP_PID;
+               } else if (strcmp(buf, "mem") == EQUAL) {
+                       obj->data.top.type = TOP_MEM;
+               } else if (strcmp(buf, "time") == EQUAL) {
+                       obj->data.top.type = TOP_TIME;
+               } else if (strcmp(buf, "mem_res") == EQUAL) {
+                       obj->data.top.type = TOP_MEM_RES;
+               } else if (strcmp(buf, "mem_vsize") == EQUAL) {
+                       obj->data.top.type = TOP_MEM_VSIZE;
+               } else {
+                       ERR("invalid type arg for top");
+                       ERR("must be one of: name, cpu, pid, mem, time, mem_res, mem_vsize");
+                       return 0;
+               }
+               if (n < 1 || n > 10) {
+                       ERR("invalid num arg for top. Must be between 1 and 10.");
+                       return 0;
+               } else {
+                       obj->data.top.num = n - 1;
+               }
+       } else {
+               ERR("invalid argument count for top");
+               return 0;
+       }
+       return 1;
+}
+
 /* construct_text_object() creates a new text_object */
 static struct text_object *construct_text_object(const char *s,
                const char *arg, long line, char allow_threaded, void **ifblock_opaque)
@@ -1775,58 +1849,7 @@ static struct text_object *construct_text_object(const char *s,
         * avoid having almost-same code three times, we have this special
         * handler. */
        if (strncmp(s, "top", 3) == EQUAL) {
-               char buf[64];
-               int n;
-
-               need_mask |= (1 << INFO_TOP);
-
-               if (s[3] == 0) {
-                       obj->type = OBJ_top;
-                       top_cpu = 1;
-               } else if (strcmp(&s[3], "_mem") == EQUAL) {
-                       obj->type = OBJ_top_mem;
-                       top_mem = 1;
-               } else if (strcmp(&s[3], "_time") == EQUAL) {
-                       obj->type = OBJ_top_time;
-                       top_time = 1;
-               } else {
-                       ERR("Must be top, top_mem or top_time");
-                       return NULL;
-               }
-
-               if (!arg) {
-                       ERR("top needs arguments");
-                       return NULL;
-               }
-
-               if (sscanf(arg, "%63s %i", buf, &n) == 2) {
-                       if (strcmp(buf, "name") == EQUAL) {
-                               obj->data.top.type = TOP_NAME;
-                       } else if (strcmp(buf, "cpu") == EQUAL) {
-                               obj->data.top.type = TOP_CPU;
-                       } else if (strcmp(buf, "pid") == EQUAL) {
-                               obj->data.top.type = TOP_PID;
-                       } else if (strcmp(buf, "mem") == EQUAL) {
-                               obj->data.top.type = TOP_MEM;
-                       } else if (strcmp(buf, "time") == EQUAL) {
-                               obj->data.top.type = TOP_TIME;
-                       } else if (strcmp(buf, "mem_res") == EQUAL) {
-                               obj->data.top.type = TOP_MEM_RES;
-                       } else if (strcmp(buf, "mem_vsize") == EQUAL) {
-                               obj->data.top.type = TOP_MEM_VSIZE;
-                       } else {
-                               ERR("invalid type arg for top");
-                               ERR("must be one of: name, cpu, pid, mem, time, mem_res, mem_vsize");
-                               return NULL;
-                       }
-                       if (n < 1 || n > 10) {
-                               ERR("invalid num arg for top. Must be between 1 and 10.");
-                               return NULL;
-                       } else {
-                               obj->data.top.num = n - 1;
-                       }
-               } else {
-                       ERR("invalid argument count for top");
+               if (!parse_top_args(s, arg, obj)) {
                        return NULL;
                }
        } else OBJ(addr, INFO_NET)
@@ -1855,13 +1878,13 @@ static struct text_object *construct_text_object(const char *s,
                }
        END OBJ(lines, 0)
                if (arg) {
-                       obj->data.s = strdup(arg);
+                       obj->data.s = strndup(arg, text_buffer_size);
                }else{
                        CRIT_ERR("lines needs a argument");
                }
        END OBJ(words, 0)
                if (arg) {
-                       obj->data.s = strdup(arg);
+                       obj->data.s = strndup(arg, text_buffer_size);
                }else{
                        CRIT_ERR("words needs a argument");
                }
@@ -2588,7 +2611,18 @@ static struct text_object *construct_text_object(const char *s,
                } else {
                        CRIT_ERR("lua needs arguments: <function name> [function parameters]");
                }
-
+       END OBJ(lua_parse, 0)
+               if (arg) {
+                       obj->data.s = strndup(arg, text_buffer_size);
+               } else {
+                       CRIT_ERR("lua_parse needs arguments: <function name> [function parameters]");
+               }
+       END OBJ(lua_read_parse, 0)
+               if (arg) {
+                       obj->data.s = strndup(arg, text_buffer_size);
+               } else {
+                       CRIT_ERR("lua_read_parse needs arguments: <function name> <string to pass>");
+               }
 #ifdef X11
        END OBJ(lua_bar, 0)
                if (arg) {
@@ -3138,7 +3172,7 @@ static int extract_variable_text_internal(struct text_object *retval, const char
 
 static void extract_variable_text(const char *p)
 {
-       free_text_objects(&global_root_object);
+       free_text_objects(&global_root_object, 0);
        if (tmpstring1) {
                free(tmpstring1);
                tmpstring1 = 0;
@@ -3814,8 +3848,8 @@ static void generate_text_internal(char *p, int p_max_size,
                                DBGP("evaluated '%s' to '%s'", obj->data.s, p);
                                parse_conky_vars(&subroot2, p, p, tmp_info);
 
-                               free_text_objects(&subroot);
-                               free_text_objects(&subroot2);
+                               free_text_objects(&subroot, 1);
+                               free_text_objects(&subroot2, 1);
                                free(tmp_info);
                        }
                        OBJ(exec) {
@@ -3832,7 +3866,7 @@ static void generate_text_internal(char *p, int p_max_size,
                                memcpy(tmp_info, cur, sizeof(struct information));
                                parse_conky_vars(&subroot, p, p, tmp_info);
 
-                               free_text_objects(&subroot);
+                               free_text_objects(&subroot, 1);
                                free(tmp_info);
                        }
 #ifdef X11
@@ -3958,7 +3992,7 @@ static void generate_text_internal(char *p, int p_max_size,
                                        parse_conky_vars(&subroot, obj->data.execi.buffer, p, tmp_info);
                                        obj->data.execi.last_update = current_update_time;
                                }
-                               free_text_objects(&subroot);
+                               free_text_objects(&subroot, 1);
                                free(tmp_info);
                        }
                        OBJ(texeci) {
@@ -4209,6 +4243,13 @@ static void generate_text_internal(char *p, int p_max_size,
                        OBJ(lua) {
                                char *str = llua_getstring(obj->data.s);
                                if (str) {
+                                       snprintf(p, p_max_size, "%s", str);
+                                       free(str);
+                               }
+                       }
+                       OBJ(lua_parse) {
+                               char *str = llua_getstring(obj->data.s);
+                               if (str) {
                                        struct information *tmp_info;
                                        struct text_object subroot;
 
@@ -4216,12 +4257,37 @@ static void generate_text_internal(char *p, int p_max_size,
                                        memcpy(tmp_info, cur, sizeof(struct information));
                                        parse_conky_vars(&subroot, str, p, tmp_info);
 
-                                       free_text_objects(&subroot);
+                                       free_text_objects(&subroot, 1);
                                        free(tmp_info);
                                        free(str);
                                }
                        }
+                       OBJ(lua_read_parse) {
+                               struct information *tmp_info;
+                               struct text_object subroot, subroot2;
+                               char func[64];
+                               char *text, *str;
+                               sscanf(obj->data.s, "%64s", func);
+                               text = obj->data.s + strlen(func);
 
+                               tmp_info = malloc(sizeof(struct information));
+                               memcpy(tmp_info, cur, sizeof(struct information));
+                               parse_conky_vars(&subroot, text, p, tmp_info);
+                               DBGP("evaluated '%s' to '%s'", text, p);
+
+                               str = llua_getstring_read(func, p);
+                               if (str) {
+                                       free_text_objects(&subroot, 1);
+//                                     memcpy(tmp_info, cur, sizeof(struct information));
+                                       parse_conky_vars(&subroot2, str, p, tmp_info);
+                                       DBGP("evaluated '%s' to '%s'", str, p);
+
+                                       free(str);
+                                       free_text_objects(&subroot2, 1);
+                               }
+                               free_text_objects(&subroot, 1);
+                               free(tmp_info);
+                       }
 #ifdef X11
                        OBJ(lua_bar) {
                                int per;
@@ -4965,12 +5031,14 @@ static void generate_text_internal(char *p, int p_max_size,
                         * times, we have this special handler. */
                        break;
                        case OBJ_top:
+                               parse_top_args("top", obj->data.top.s, obj);
                                if (!needed) needed = cur->cpu;
                        case OBJ_top_mem:
+                               parse_top_args("top_mem", obj->data.top.s, obj);
                                if (!needed) needed = cur->memu;
                        case OBJ_top_time:
+                               parse_top_args("top_time", obj->data.top.s, obj);
                                if (!needed) needed = cur->time;
-
                                {
                                        char *timeval;
 
@@ -6770,7 +6838,7 @@ static void clean_up(void)
        }
 #endif /* X11 */
 
-       free_text_objects(&global_root_object);
+       free_text_objects(&global_root_object, 0);
        if (tmpstring1) {
                free(tmpstring1);
                tmpstring1 = 0;
index 45e8714..61e3dac 100644 (file)
@@ -30,7 +30,7 @@
 
 lua_State *lua_L = NULL;
 
-void llua_init()
+void llua_init(void)
 {
        if(lua_L) return;
        lua_L = lua_open();
@@ -92,6 +92,29 @@ char *llua_do_call(const char *string, int retc)
        return func;
 }
 
+/*
+ * same as llua_do_call() except passes everything after func as one arg.
+ */
+char *llua_do_read_call(const char *function, const char *arg, int retc)
+{
+       static char func[64];
+       snprintf(func, 64, "conky_%s", function);
+       
+       /* push the function name to stack */
+       lua_getglobal(lua_L, func);
+
+       /* push function parameter to the stack */
+       lua_pushstring(lua_L, arg);
+
+       if (lua_pcall(lua_L, 1, retc, 0) != 0) {
+               ERR("llua_do_call: function %s execution failed: %s", func, lua_tostring(lua_L, -1));
+               lua_pop(lua_L, -1);
+               return NULL;
+       }
+
+       return func;
+}
+
 char *llua_getstring(const char *args)
 {
        char *func;
@@ -104,7 +127,27 @@ char *llua_getstring(const char *args)
                if(!lua_isstring(lua_L, -1)) {
                        ERR("llua_getstring: function %s didn't return a string, result discarded", func);
                } else {
-                       ret = strdup((char *)lua_tostring(lua_L, -1));
+                       ret = strdup(lua_tostring(lua_L, -1));
+                       lua_pop(lua_L, 1);
+               }
+       }
+
+       return ret;
+}
+
+char *llua_getstring_read(const char *function, const char *arg)
+{
+       char *func;
+       char *ret = NULL;
+
+       if(!lua_L) return NULL;
+
+       func = llua_do_read_call(function, arg, 1);
+       if (func) {
+               if(!lua_isstring(lua_L, -1)) {
+                       ERR("llua_getstring_read: function %s didn't return a string, result discarded", func);
+               } else {
+                       ret = strdup(lua_tostring(lua_L, -1));
                        lua_pop(lua_L, 1);
                }
        }
@@ -131,7 +174,7 @@ int llua_getinteger(const char *args, int *per)
        return 0;
 }
 
-void llua_close()
+void llua_close(void)
 {
        if(!lua_L) return;
        lua_close(lua_L);
index 6a26bac..763eb4f 100644 (file)
@@ -1,3 +1,30 @@
+/* Conky, a system monitor, based on torsmo
+ *
+ * Any original torsmo code is licensed under the BSD license
+ *
+ * All code written since the fork of torsmo is licensed under the GPL
+ *
+ * Please see COPYING for details
+ *
+ * Copyright (c) 2009 Toni Spets
+ * Copyright (c) 2005-2009 Brenden Matthews, Philip Kovacs, et. al.
+ *     (see AUTHORS)
+ * All rights reserved.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
 #ifndef LUA_H_
 #define LUA_H_
 
 #include <lauxlib.h>
 #include <lualib.h>
 
-void llua_init();
+void llua_init(void);
 void llua_load(const char *script);
 char *llua_getstring(const char *args);
+char *llua_getstring_read(const char *function, const char *arg);
 int llua_getinteger(const char *args, int *per);
-void llua_close();
+void llua_close(void);
 
 #endif /* LUA_H_*/
index b185ba4..f6c07b0 100644 (file)
@@ -382,6 +382,8 @@ enum text_object_type {
 #endif
 #ifdef HAVE_LUA
        OBJ_lua,
+       OBJ_lua_parse,
+       OBJ_lua_read_parse,
 #ifdef X11
        OBJ_lua_bar,
        OBJ_lua_graph,
@@ -481,6 +483,8 @@ struct text_object {
                struct {
                        int num;
                        int type;
+                       int was_parsed;
+                       char *s;
                } top;
 
                struct {