diff --git a/src/Makefile.am b/src/Makefile.am index 1ba1d12c..6470c2fb 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -143,7 +143,8 @@ conky_SOURCES = \ $(smapi) \ temphelper.c \ temphelper.h \ - text_object.h + text_object.h \ + text_object.c conky_LDFLAGS = \ $(PTHREAD_LIBS) \ diff --git a/src/conky.c b/src/conky.c index 0317bd88..94980da2 100644 --- a/src/conky.c +++ b/src/conky.c @@ -1097,98 +1097,9 @@ static void human_readable(long long num, char *buf, int size, const char *func_ } while (len >= (short_units ? SHORT_WIDTH : WIDTH) || len >= size); } -/* text_object_list - * - * this list is special. it looks like this: - * NULL <-- obj1 <--> obj2 <--> ... <--> objN --> NULL - * ^-------root_object----------^ - * directions are reversed here - * - * why this is cool: - * - root_object points both to the start and end of the list - * - while traversing, the end of the list is always a NULL pointer - * (this works in BOTH directions) - */ +/* global object list root element */ static struct text_object global_root_object; -static int append_object(struct text_object *root, struct text_object *obj) -{ - struct text_object *end; - - end = root->prev; - obj->prev = end; - obj->next = NULL; - - if (end) { - if (end->next) - CRIT_ERR("huston, we have a lift-off"); - end->next = obj; - } else { - root->next = obj; - } - root->prev = obj; - return 0; -} - -/* ifblock handlers for the object list - * - * - each if points to it's else or endif - * - each else points to it's endif - */ -enum ifblock_type { - IFBLOCK_IF = 1, - IFBLOCK_ELSE, - IFBLOCK_ENDIF, -}; -struct ifblock_stack_obj { - enum ifblock_type type; - struct text_object *obj; - struct ifblock_stack_obj *next; -}; -static struct ifblock_stack_obj *ifblock_stack_top = NULL; - -static int push_ifblock(struct text_object *obj, enum ifblock_type type) -{ - struct ifblock_stack_obj *stackobj; - - switch (type) { - case IFBLOCK_ENDIF: - if (!ifblock_stack_top) - CRIT_ERR("got an endif without matching if"); - ifblock_stack_top->obj->data.ifblock.next = obj; - /* if there's some else in between, remove and free it */ - if (ifblock_stack_top->type == IFBLOCK_ELSE) { - stackobj = ifblock_stack_top; - ifblock_stack_top = stackobj->next; - free(stackobj); - } - /* finally remove and free the if object */ - stackobj = ifblock_stack_top; - ifblock_stack_top = stackobj->next; - free(stackobj); - break; - case IFBLOCK_ELSE: - if (!ifblock_stack_top) - CRIT_ERR("got an else without matching if"); - ifblock_stack_top->obj->data.ifblock.next = obj; - /* fall through */ - case IFBLOCK_IF: - stackobj = malloc(sizeof(struct ifblock_stack_obj)); - stackobj->type = type; - stackobj->obj = obj; - stackobj->next = ifblock_stack_top; - ifblock_stack_top = stackobj; - break; - default: - CRIT_ERR("push_ifblock() missuse detected!"); - } - return 0; -} -static int obj_be_ifblock_if(struct text_object *obj) -{ - return push_ifblock(obj, IFBLOCK_IF); -} - static void generate_text_internal(char *p, int p_max_size, struct text_object text_object, struct information *cur); @@ -2024,9 +1935,9 @@ static struct text_object *construct_text_object(const char *s, obj->data.net = get_net_stat(buf); free(buf); END OBJ(else, 0) - push_ifblock(obj, IFBLOCK_ELSE); + obj_be_ifblock_else(obj); END OBJ(endif, 0) - push_ifblock(obj, IFBLOCK_ENDIF); + obj_be_ifblock_endif(obj); END OBJ(image, 0) obj->data.s = strndup(arg ? arg : "", text_buffer_size); #ifdef HAVE_POPEN @@ -3511,7 +3422,7 @@ static int extract_variable_text_internal(struct text_object *retval, const char append_object(retval, obj); } - if (ifblock_stack_top) { + if (!ifblock_stack_empty()) { ERR("one or more $endif's are missing"); } diff --git a/src/text_object.c b/src/text_object.c new file mode 100644 index 00000000..e473e67a --- /dev/null +++ b/src/text_object.c @@ -0,0 +1,162 @@ +/* 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) 2004, Hannu Saransaari and Lauri Hakkarainen + * Copyright (c) 2005-2008 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 . + * + */ +#include "text_object.h" +#include "conky.h" /* not as worse: only for the printing macros */ + +/* text_object_list + * + * this list is special. it looks like this: + * NULL <-- obj1 <--> obj2 <--> ... <--> objN --> NULL + * ^-------root_object----------^ + * directions are reversed here + * + * why this is cool: + * - root_object points both to the start and end of the list + * - while traversing, the end of the list is always a NULL pointer + * (this works in BOTH directions) + */ + +/* append an object to the given root object's list */ +int append_object(struct text_object *root, struct text_object *obj) +{ + struct text_object *end; + + end = root->prev; + obj->prev = end; + obj->next = NULL; + + if (end) { + if (end->next) + CRIT_ERR("huston, we have a lift-off"); + end->next = obj; + } else { + root->next = obj; + } + root->prev = obj; + return 0; +} + +/* ifblock handlers for the object list + * + * - each if points to it's else or endif + * - each else points to it's endif + * + */ + +/* possible ifblock types + * only used internally, so no need to make this public + */ +enum ifblock_type { + IFBLOCK_IF = 1, + IFBLOCK_ELSE, + IFBLOCK_ENDIF, +}; + +/* linked list of ifblock objects, building a stack + * only used internally, so no need to make this public + */ +struct ifblock_stack_obj { + enum ifblock_type type; + struct text_object *obj; + struct ifblock_stack_obj *next; +}; + +/* top of the internal ifblock stack + * initially contains only one "object", i.e. a NULL pointer + * indicating the end of the stack. + */ +static struct ifblock_stack_obj *ifblock_stack_top = NULL; + +/* push an ifblock object onto the stack + * in fact, this does a lot more: + * - IFBLOCK_IF is just pushed onto the stack + * - IFBLOCK_ELSE updates the "next" pointer of the upmost + * object in the stack and is then pushed onto the stack + * - IFBLOCK_ENDIF updates the "next" pointer of the upmost + * object in the stack and then triggers stack popping of + * any optional IFBLOCK_ELSE along with it's IFBLOCK_IF + */ +static int push_ifblock(struct text_object *obj, enum ifblock_type type) +{ + struct ifblock_stack_obj *stackobj; + + switch (type) { + case IFBLOCK_ENDIF: + if (!ifblock_stack_top) + CRIT_ERR("got an endif without matching if"); + ifblock_stack_top->obj->data.ifblock.next = obj; + /* if there's some else in between, remove and free it */ + if (ifblock_stack_top->type == IFBLOCK_ELSE) { + stackobj = ifblock_stack_top; + ifblock_stack_top = stackobj->next; + free(stackobj); + } + /* finally remove and free the if object */ + stackobj = ifblock_stack_top; + ifblock_stack_top = stackobj->next; + free(stackobj); + break; + case IFBLOCK_ELSE: + if (!ifblock_stack_top) + CRIT_ERR("got an else without matching if"); + ifblock_stack_top->obj->data.ifblock.next = obj; + /* fall through */ + case IFBLOCK_IF: + stackobj = malloc(sizeof(struct ifblock_stack_obj)); + stackobj->type = type; + stackobj->obj = obj; + stackobj->next = ifblock_stack_top; + ifblock_stack_top = stackobj; + break; + default: + CRIT_ERR("push_ifblock() missuse detected!"); + } + return 0; +} + +/* public functions for client use */ + +int obj_be_ifblock_if(struct text_object *obj) +{ + return push_ifblock(obj, IFBLOCK_IF); +} +int obj_be_ifblock_else(struct text_object *obj) +{ + return push_ifblock(obj, IFBLOCK_ELSE); +} +int obj_be_ifblock_endif(struct text_object *obj) +{ + return push_ifblock(obj, IFBLOCK_ENDIF); +} + +/* check if ifblock stack is empty + * if so, return true (!= 0) + */ +int ifblock_stack_empty(void) +{ + return ifblock_stack_top == NULL; +} diff --git a/src/text_object.h b/src/text_object.h index 0e3e216b..27fa67aa 100644 --- a/src/text_object.h +++ b/src/text_object.h @@ -482,4 +482,13 @@ struct text_object { char global_mode; }; +/* text object list helpers */ +int append_object(struct text_object *root, struct text_object *obj); + +/* ifblock helpers */ +int obj_be_ifblock_if(struct text_object *); +int obj_be_ifblock_else(struct text_object *); +int obj_be_ifblock_endif(struct text_object *); +int ifblock_stack_empty(void); + #endif /* _TEXT_OBJECT_H */