From f5fe7dda77f4168dd016b24e8cbc81dae141dff5 Mon Sep 17 00:00:00 2001 From: martin Date: Sat, 8 Aug 2009 15:57:26 +0200 Subject: [PATCH] Confparse: Add confparse/ libconfuse soon useless. --- src/config_new.c | 539 +++++++++++++++++++++++++++++++++++++ src/confparse/confparse.c | 225 ++++++++++++++++ src/confparse/confparse.c~ | 225 ++++++++++++++++ src/confparse/confparse.h | 71 +++++ src/confparse/confparse.h~ | 68 +++++ src/confparse/util.c | 167 ++++++++++++ src/confparse/util.c~ | 167 ++++++++++++ 7 files changed, 1462 insertions(+) create mode 100644 src/config_new.c create mode 100644 src/confparse/confparse.c create mode 100644 src/confparse/confparse.c~ create mode 100644 src/confparse/confparse.h create mode 100644 src/confparse/confparse.h~ create mode 100644 src/confparse/util.c create mode 100644 src/confparse/util.c~ diff --git a/src/config_new.c b/src/config_new.c new file mode 100644 index 0000000..a4e6120 --- /dev/null +++ b/src/config_new.c @@ -0,0 +1,539 @@ +/* +* config.c +* Copyright © 2008 Martin Duquesnoy +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following disclaimer +* in the documentation and/or other materials provided with the +* distribution. +* * Neither the name of the nor the names of its +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "config_struct.h" + +void +conf_init_func_list(void) +{ + int i; + + func_name_list_t tmp_list[] = + { + {"spawn", uicb_spawn }, + {"client_kill", uicb_client_kill }, + {"client_prev", uicb_client_prev }, + {"client_next", uicb_client_next }, + {"client_swap_next", uicb_client_swap_next }, + {"client_swap_prev", uicb_client_swap_prev }, + {"client_screen_next", uicb_client_screen_next }, + {"client_screen_prev", uicb_client_screen_prev }, + {"toggle_max", uicb_togglemax }, + {"layout_next", uicb_layout_next }, + {"layout_prev", uicb_layout_prev }, + {"tag", uicb_tag }, + {"tag_next", uicb_tag_next }, + {"tag_prev", uicb_tag_prev }, + {"tag_transfert", uicb_tagtransfert }, + {"set_mwfact", uicb_set_mwfact }, + {"set_nmaster", uicb_set_nmaster }, + {"quit", uicb_quit }, + {"toggle_infobar_position", uicb_infobar_togglepos }, + {"toggle_resizehint", uicb_toggle_resizehint }, + {"mouse_move", uicb_mouse_move }, + {"mouse_resize", uicb_mouse_resize }, + {"client_raise", uicb_client_raise }, + {"toggle_free", uicb_togglefree }, + {"screen_select", uicb_screen_select }, + {"screen_next", uicb_screen_next }, + {"screen_prev", uicb_screen_prev }, + {"reload", uicb_reload }, + {"launcher", uicb_launcher }, + {"set_layout", uicb_set_layout }, + {"menu", uicb_menu } + }; + + func_list = emalloc(LEN(tmp_list), sizeof(func_name_list_t)); + + for(i = 0; i < LEN(tmp_list); ++i) + func_list[i] = tmp_list[i]; + + return; +} + +void +mouse_section(MouseBinding mb[], char *src, int ns) +{ + int i; + char *tmp; + + for(i = 0; i < ns; ++i) + { + tmp = get_nsec(src, "mouse", i); + mb[i].tag = get_opt(tmp, "-1", "tag").num; + mb[i].screen = get_opt(tmp, "-1", "screen").num; + mb[i].button = char_to_button(get_opt(tmp, "1", "button").str, mouse_button_list); + mb[i].func = name_to_func(get_opt(tmp, "", "func").str, func_list); + mb[i].cmd = get_opt(tmp, "", "cmd").str; + } + + return; +} + +void +conf_misc_section(char *src) +{ + int pad = 12; + + conf.font = get_opt(src, "sans-9", "font").str; + conf.raisefocus = get_opt(src, "false", "raisefocus").bool; + conf.raiseswitch = get_opt(src, "false", "raiseswitch").bool; + conf.focus_fmouse = get_opt(src, "true", "focus_follow_mouse").bool; + pad = get_opt(src, "12", "pad").num; + + if(pad > 24 || pad < 1) + { + fprintf(stderr, "WMFS Configuration: pad value (%d) incorrect.\n", pad); + + pad = 12; + } + + conf.pad = pad; + + return; +} + +void +conf_bar_section(char *src) +{ + conf.border.bar = get_opt(src, "false", "border").bool; + conf.bars.height = get_opt(src, "-1", "height").num; + conf.colors.bar = getcolor(get_opt(src, "#000000", "bg").str); + conf.colors.text = get_opt(src, "#ffffff", "fg").str; + + if((conf.bars.nmouse = get_size_sec(src, "mouse"))) + { + conf.bars.mouse = emalloc(conf.bars.nmouse, sizeof(MouseBinding)); + mouse_section(conf.bars.mouse, src, conf.bars.nmouse); + } + + return; +} + +void +conf_root_section(char *src) +{ + conf.root.background_command = get_opt(src, "", "background_command").str; + + if((conf.root.nmouse = get_size_sec(src, "mouse"))) + { + conf.root.mouse = emalloc(conf.root.nmouse, sizeof(MouseBinding)); + mouse_section(conf.root.mouse, src, conf.root.nmouse); + } + + return; +} + +void +conf_client_section(char *src) +{ + int i, j, d; + char *tmp, *tmp2, *tmp3; + opt_type *buf; + + /* Client misc */ + conf.client.borderheight = (get_opt(src, "1", "border_height").num) ? get_opt(src, "1", "border_height").num : 1; + conf.client.border_shadow = get_opt(src, "false", "border_shadow").bool; + conf.client.place_at_mouse = get_opt(src, "false", "place_at_mouse").bool; + conf.client.bordernormal = getcolor(get_opt(src, "#000000", "border_normal").str); + conf.client.borderfocus = getcolor(get_opt(src, "#ffffff", "border_focus").str); + conf.client.resizecorner_normal = getcolor(get_opt(src, "#222222", "resize_corner_normal").str); + conf.client.resizecorner_focus = getcolor(get_opt(src, "#DDDDDD", "resize_corner_focus").str); + conf.client.mod |= char_to_modkey(get_opt(src, "Alt", "modifier").str, key_list); + + if((conf.client.nmouse = get_size_sec(src, "mouse"))) + { + printf("conf.client.nmouse = %d\n", conf.client.nmouse); + conf.client.mouse = emalloc(conf.client.nmouse, sizeof(MouseBinding)); + mouse_section(conf.client.mouse, src, conf.client.nmouse); + } + + /* Titlebar part {{ */ + tmp = get_sec(src, "titlebar"); + conf.titlebar.height = get_opt(tmp, "0", "height").num; + conf.titlebar.fg_normal = get_opt(tmp, "#ffffff", "fg_normal").str; + conf.titlebar.fg_focus = get_opt(tmp, "#000000", "fg_focus").str; + + /* Stipple */ + conf.titlebar.stipple.active = get_opt(tmp, "false", "stipple").bool; + + if(!strcmp(get_opt(tmp, "-1", "stipple_normal").str, "-1")) + conf.titlebar.stipple.colors.normal = getcolor(conf.titlebar.fg_normal); + else + conf.titlebar.stipple.colors.normal = getcolor(get_opt(tmp, "-1", "stipple_normal").str); + + if(!strcmp(get_opt(tmp, "-1", "stipple_focus").str, "-1")) + conf.titlebar.stipple.colors.focus = getcolor(conf.titlebar.fg_focus); + else + conf.titlebar.stipple.colors.focus = getcolor(get_opt(tmp, "-1", "stipple_focus").str); + + if((conf.titlebar.nmouse = get_size_sec(tmp, "mouse"))) + { + conf.titlebar.mouse = emalloc(conf.titlebar.nmouse, sizeof(MouseBinding)); + mouse_section(conf.titlebar.mouse, tmp, conf.titlebar.nmouse); + } + + /* Multi button part */ + if((conf.titlebar.nbutton = get_size_sec(tmp, "button"))) + { + conf.titlebar.button = emalloc(conf.titlebar.nbutton, sizeof(Button)); + for(i = 0; i < conf.titlebar.nbutton; ++i) + { + tmp2 = get_nsec(tmp, "button", i); + + /* Multi mouse section */ + if((conf.titlebar.button[i].nmouse = get_size_sec(tmp2, "mouse"))) + { + conf.titlebar.button[i].mouse = emalloc(conf.titlebar.button[i].nmouse, sizeof(MouseBinding)); + mouse_section(conf.titlebar.button[i].mouse, tmp2, conf.titlebar.button[i].nmouse); + } + + /* Multi line section */ + if((conf.titlebar.button[i].nlines = get_size_sec(tmp2, "line"))) + { + conf.titlebar.button[i].linecoord = emalloc(conf.titlebar.button[i].nlines, sizeof(XSegment)); + + for(j = 0; j < conf.titlebar.button[i].nlines; ++j) + { + tmp3 = get_nsec(tmp2, "line", j); + buf = get_list_opt(tmp3, "{0, 0, 0, 0}", "coord", &d); + + conf.titlebar.button[i].linecoord[j].x1 = buf[0].num; + conf.titlebar.button[i].linecoord[j].y1 = buf[1].num; + conf.titlebar.button[i].linecoord[j].x2 = buf[2].num; + conf.titlebar.button[i].linecoord[j].y2 = buf[3].num; + } + } + } + } + /* }} */ + + return; +} + +void +conf_layout_section(char *src) +{ + int i; + char *tmp = NULL; + + /* Set conf.layout NULL for conf reload */ + for(i = 0; i < NUM_OF_LAYOUT; ++i) + { + conf.layout[i].symbol = NULL; + conf.layout[i].func = NULL; + } + + conf.border.layout = get_opt(src, "false", "border").bool; + conf.colors.layout_fg = get_opt(src, "#ffffff", "fg").str; + conf.colors.layout_bg = getcolor((get_opt(src, "#000000", "bg").str)); + + if(strcmp(get_opt(src, "menu", "system").str, "menu") == 0) + conf.layout_system = True; + + if((conf.nlayout = get_size_sec(src, "layout")) > NUM_OF_LAYOUT + || !(conf.nlayout = get_size_sec(src, "layout"))) + { + fprintf(stderr, "WMFS Configuration: Too many or no layouts (%d)\n", conf.nlayout); + conf.nlayout = 1; + conf.layout[0].symbol = _strdup("TILE"); + conf.layout[0].func = tile; + } + + if(conf.layout_system && conf.nlayout > 1) + { + menu_init(&menulayout, "menulayout", conf.nlayout, + /* Colors */ + conf.colors.layout_bg, + conf.colors.layout_fg, + conf.colors.bar, + conf.colors.text); + + if(!conf.layout[0].symbol + && !conf.layout[0].func) + { + for(i = 0; i < conf.nlayout; ++i) + { + tmp = get_nsec(src, "layout", i); + + if(!name_to_func(get_opt(tmp, "", "type").str, layout_list)) + { + fprintf(stderr, "WMFS Configuration: Unknow Layout type: \"%s\"\n", + get_opt(tmp, "", "type").str); + /* exit(EXIT_FAILURE); */ + } + else + { + if(conf.layout_system && conf.nlayout > 1) + menu_new_item(&menulayout.item[i], get_opt(tmp, "", "symbol").str, + uicb_set_layout, + get_opt(tmp, "", "type").str); + + conf.layout[i].symbol = get_opt(tmp, "", "symbol").str; + conf.layout[i].func = name_to_func(get_opt(tmp, "", "type").str, layout_list); + } + } + } + } + + return; +} + +void +conf_tag_section(char *src) +{ + int i, j, k, l = 0, m, n; + char *cfgtmp, *tmp; + opt_type *buf; + + /* If there is no tag in the conf or more than + * MAXTAG (32) print an error and create only one. + */ + Tag default_tag = { "WMFS", NULL, 0, + 0.50, 1, False, False, IB_Top, + layout_name_to_struct(conf.layout, "tile_right", conf.nlayout, layout_list) }; + + conf.tag_round = get_opt(src, "false", "tag_round").bool; + conf.colors.tagselfg = get_opt(src, "#ffffff", "sel_fg").str; + conf.colors.tagselbg = getcolor(get_opt(src, "#000000", "sel_bg").str); + conf.colors.tag_occupied_bg = getcolor(get_opt(src, "#222222", "occupied_bg").str); + conf.border.tag = get_opt(src, "false", "border").bool; + + /* Alloc all */ + conf.ntag = emalloc(screen_count(), sizeof(int)); + tags = emalloc(screen_count(), sizeof(Tag*)); + seltag = emalloc(screen_count(), sizeof(int)); + + for(i = 0; i < screen_count(); ++i) + seltag[i] = 1; + + for(i = 0; i < screen_count(); ++i) + tags[i] = emalloc(get_size_sec(src, "tag") + 2, sizeof(Tag)); + + for(i = 0; i < get_size_sec(src, "tag"); ++i) + { + cfgtmp = get_nsec(src, "tag", i); + j = get_opt(cfgtmp, "-1", "screen").num; + + if(j < 0 || j > screen_count() - 1) + j = -1; + + for(k = ((j == -1) ? 0 : j); + ((j == -1) ? (k < screen_count()) : !l); + ((j == -1) ? ++k : --l)) + { + ++conf.ntag[k]; + tags[k][conf.ntag[k]].name = get_opt(cfgtmp, "", "name").str; + tags[k][conf.ntag[k]].mwfact = get_opt(cfgtmp, "0.65", "mwfact").fnum; + tags[k][conf.ntag[k]].nmaster = get_opt(cfgtmp, "1", "nmaster").num; + tags[k][conf.ntag[k]].resizehint = get_opt(cfgtmp, "false", "resizehint").bool; + + tmp = _strdup(get_opt(cfgtmp, "top", "infobar_position").str); + + if(!strcmp(tmp ,"none") || !strcmp(tmp, "hide") || !strcmp(tmp, "hidden")) + tags[k][conf.ntag[k]].barpos = IB_Hide; + else if(!strcmp(tmp, "bottom") || !strcmp(tmp, "down")) + tags[k][conf.ntag[k]].barpos = IB_Bottom; + else + tags[k][conf.ntag[k]].barpos = IB_Top; + + tags[k][conf.ntag[k]].layout = layout_name_to_struct(conf.layout, + get_opt(cfgtmp, "tile_right", "layout").str, + conf.nlayout, + layout_list); + + /* Clients list */ + buf = get_list_opt(cfgtmp, "", "clients", &n); + if(n) + { + tags[k][conf.ntag[k]].nclients = n; + tags[k][conf.ntag[k]].clients = emalloc(n, sizeof(char *)); + for(m = 0; m < n; ++m) + tags[k][conf.ntag[k]].clients[m] = (buf[m].str) ? buf[m].str : NULL; + } + + } + l = 0; + } + + for(i = 0; i < screen_count(); ++i) + if(!conf.ntag[i] || conf.ntag[i] > MAXTAG) + { + fprintf(stderr, "WMFS Configuration: Too many or no tag" + " (%d) in the screen %d\n", conf.ntag[i], i); + + conf.ntag[i] = 1; + tags[i][1] = default_tag; + } + + return; +} + +void +conf_menu_section(char *src) +{ + char *tmp, *tmp2; + int i, j; + + CHECK((conf.nmenu = get_size_sec(src, "set_menu"))); + + conf.menu = calloc(conf.nmenu, sizeof(Menu)); + + for(i = 0; i < conf.nmenu; ++i) + { + tmp = get_nsec(src, "set_menu", i); + + conf.menu[i].name = get_opt(tmp, "menu_wname", "name").str; + + if(!(conf.menu[i].place_at_mouse = get_opt(tmp, "true", "place_at_mouse").bool)) + { + conf.menu[i].x = get_opt(cfgtmp, "0", "x").num; + conf.menu[i].y = get_opt(cfgtmp, "0", "y").num; + } + + conf.menu[i].colors.focus.bg = getcolor(get_opt(tmp, "#000000", "bg_focus").str); + conf.menu[i].colors.focus.fg = get_opt(tmp, "#ffffff", "fg_focus").str; + conf.menu[i].colors.normal.bg = getcolor(get_opt(tmp, "#000000", "bg_normal").str); + conf.menu[i].colors.normal.fg = get_opt(tmp, "#ffffff", "fg_normal").str; + + if((conf.menu[i].nitem = get_size_sec(tmp, "item"))) + { + conf.menu[i].item = emalloc(conf.menu[i].nitem, sizeof(MenuItem)); + for(j = 0; j < get_size_sec(tmp, "item"); ++j) + { + tmp2 = get_nsec(tmp, "item", j); + + conf.menu[i].item[j].name = get_opt(tmp2, "item_wname", "name").str; + conf.menu[i].item[j].func = name_to_func(get_opt(tmp2, "", "func").str, func_list); + conf.menu[i].item[j].cmd = (!get_opt(tmp2, "", "cmd").str) ? NULL : get_opt(tmp2, "", "cmd").str; + } + } + } + + return; +} + +void +conf_launcher_section(char *src) +{ + int i; + char *tmp; + + CHECK((conf.nlauncher = get_size_sec(src, "set_launcher"))); + + conf.launcher = emalloc(conf.nlauncher, sizeof(Launcher)); + + for(i = 0; i < conf.nlauncher; ++i) + { + tmp = get_nsec(src, "set_launcher", i); + + conf.launcher[i].name = get_opt(tmp, "launcher", "name").str; + conf.launcher[i].prompt = get_opt(tmp, "Exec:", "prompt").str; + conf.launcher[i].command = get_opt(tmp, "exec", "command").str; + } + + return; +} + +void +conf_keybind_section(char *src) +{ + int i, j, n = 0; + char *tmp; + opt_type *buf; + + conf.nkeybind = get_size_sec(src, "key"); + keys = emalloc(conf.nkeybind, sizeof(Key)); + + for(i = 0; i < conf.nkeybind; ++i) + { + tmp = get_nsec(src, "key", i); + buf = get_list_opt(tmp, "{Control}", "mod", &n); + + for(j = 0; j < n; ++j) + keys[i].mod |= char_to_modkey(buf[j].str, key_list); + + keys[i].keysym = XStringToKeysym(get_opt(tmp, "None", "key").str); + keys[i].func = name_to_func(get_opt(tmp, "", "func").str, func_list); + + if(keys[i].func == NULL) + { + fprintf(stderr, "WMFS Configuration error: Unknow Function \"%s\"\n", get_opt(tmp, "", "func").str); + keys[i].func = uicb_spawn; + } + keys[i].cmd = (!get_opt(tmp, "", "cmd").str) ? NULL : get_opt(tmp, "", "cmd").str; + + } + + return; +} + +/** Configuration initialization +*/ +void +init_conf(void) +{ + FILE *f; + char *file; + + if(!(f = fopen(conf.confpath, "r"))) + { + fprintf(stderr, "WMFS: parsing configuration file (%s) failed\n", conf.confpath); + sprintf(conf.confpath, "%s/wmfs/wmfsrc", XDG_CONFIG_DIR); + fprintf(stderr, "Use the default configuration (%s).\n", conf.confpath); + f = fopen(conf.confpath, "r"); + } + + file = file_to_str(f); + + conf_init_func_list(); + + /* conf_alias_section(get_sec(file, "alias")); */ + + conf_misc_section(get_sec(file, "misc")); + conf_bar_section(get_sec(file, "bar")); + conf_root_section(get_sec(file, "root")); + conf_client_section(get_sec(file, "client")); + conf_layout_section(get_sec(file, "layouts")); + conf_tag_section(get_sec(file, "tags")); + conf_menu_section(get_sec(file, "menu")); + conf_launcher_section(get_sec(file, "launcher")); + conf_keybind_section(get_sec(file, "keys")); + + free(file); + + return; +} + + + + diff --git a/src/confparse/confparse.c b/src/confparse/confparse.c new file mode 100644 index 0000000..3e67b8c --- /dev/null +++ b/src/confparse/confparse.c @@ -0,0 +1,225 @@ +/* + * confparse/confparse.c + * Copyright © 2008,2009 Martin Duquesnoy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "confparse.h" + +char* +file_to_str(FILE *f) +{ + char c; + char *ret; + int i; + + for(i = 1; fgetc(f) != EOF; ++i); + + ret = emalloc(i, sizeof(char)); + + rewind(f); + + for(i = 0; (c = fgetc(f)) != EOF; ret[i++] = c); + + fclose(f); + + return ret; +} + +char* +get_sec(char *src, char *name) +{ + char *ret, *p; + char *secn; + + if(!src) + return NULL; + + if(!name) + return src; + + secn = emalloc((strlen(name) + 2), sizeof(char)); + sprintf(secn, "%c%s%c", SEC_DEL_S, name, SEC_DEL_E); + + ret = _strdup(src); + + if((p = strstr(erase_delim_content(src), secn))) + { + ret += strlen(ret) - strlen(p) + strlen(secn) + 1; + + if((p = strstr(erase_delim_content(ret), secn))) + *(ret + (strlen(ret) - strlen(p))) = '\0'; + else + ret = NULL; + } + else + ret = NULL; + + free(secn); + + return ret; +} + +char* +get_nsec(char *src, char *name, int n) +{ + int i; + char *ret, *buf, *secn; + char *buf2; + + if(!src) + return NULL; + + if(!name) + return src; + + if(!n) + return get_sec(src, name); + + secn = emalloc((strlen(name) + 2), sizeof(char)); + sprintf(secn, "%c%s%c", SEC_DEL_S, name, SEC_DEL_E); + + buf = erase_delim_content(src); + buf2 = erase_sec_content(buf); + + for(i = 0; i < n * 2 && (buf = strstr(buf, secn)); ++i, buf += strlen(secn)); + + ret = get_sec(src + strlen(src) - strlen(buf), name); + + free(secn); + + return ret; +} + +int +get_size_sec(char *src, char *name) +{ + int ret; + char *secn, *buf; + + if(!src || !name) + return 0; + + secn = emalloc(strlen(name), sizeof(char)); + sprintf(secn, "%c%s%c", SEC_DEL_S, name, SEC_DEL_E); + + buf = erase_sec_content(src); + + for(ret = 0; (buf = strstr(buf, secn)); ++ret, buf += strlen(secn)); + + /* If a section is not closed */ + for(; ret % 2; --ret); + + free(secn); + + return ret / 2; +} + +opt_type +get_opt(char *src, char *def, char *name) +{ + int i; + char *p = NULL; + opt_type ret = null_opt_type; + + if(!src || !name) + return (def) ? str_to_opt(def) : null_opt_type; + + if((p = opt_srch(erase_sec_content(src), name))) + { + for(i = 0; p[i] && p[i] != '\n'; ++i); + p[i] = '\0'; + + if((p = strchr(p, '=')) && !is_in_delimiter(p, 0)) + ret = str_to_opt(clean_value(++p)); + } + else + ret = str_to_opt(def); + + return ret; +} + +/* option = {val1, val2, val3} */ +opt_type* +get_list_opt(char *src, char *def, char *name, int *n) +{ + int i, j; + char *p, *p2; + opt_type *ret; + + if(!src || !name) + return NULL; + + *n = 0; + + if(!(p = get_opt(src, def, name).str)) + return NULL; + + for(i = 0; p[i] && (p[i] != '}' || is_in_delimiter(p, i)); ++i); + p[i + 1] = '\0'; + + /* Syntax of list (val1, val2, ..., valx) */ + if(*p != '{' || *(p + strlen(p) - 1) != '}') + return NULL; + + /* Erase ( ) */ + ++p; + *(p + strlen(p) - 1) = '\0'; + + /* > 1 value in list */ + if(strchr(p, ',')) + { + /* Count ',' */ + for(i = 0, *n = 1; i < strlen(p); ++i) + if(p[i] == ',' && !is_in_delimiter(p, i)) + ++(*n); + + ret = emalloc(*n, sizeof(opt_type)); + + p2 = _strdup(p); + + /* Set all value in return array */ + for(i = j = 0; i < *n; ++i, p2 += ++j + 1) + { + for(j = 0; j < strlen(p2) && (p2[j] != ',' || is_in_delimiter(p2, j)); ++j); + p2[j] = '\0'; + + ret[i] = str_to_opt(clean_value(p2)); + } + } + else + { + ret = emalloc(1, sizeof(opt_type)); + *ret = str_to_opt(clean_value(p)); + + *n = 1; + } + + return ret; +} diff --git a/src/confparse/confparse.c~ b/src/confparse/confparse.c~ new file mode 100644 index 0000000..4688123 --- /dev/null +++ b/src/confparse/confparse.c~ @@ -0,0 +1,225 @@ +/* + * confparse/confparse.c + * Copyright © 2008,2009 Martin Duquesnoy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "confparse.h" + +char* +file_to_str(FILE *f) +{ + char c; + char *ret; + int i; + + for(i = 1; fgetc(f) != EOF; ++i); + + ret = emalloc(i, sizeof(char)); + + rewind(f); + + for(i = 0; (c = fgetc(f)) != EOF; ret[i++] = c); + + fclose(f); + + return ret; +} + +char* +get_sec(char *src, char *name) +{ + char *ret, *p; + char *secn; + + if(!src) + return NULL; + + if(!name) + return src; + + secn = emalloc((strlen(name) + 2), sizeof(char)); + sprintf(secn, "(%s)", name); + + ret = _strdup(src); + + if((p = strstr(erase_delim_content(src), secn))) + { + ret += strlen(ret) - strlen(p) + strlen(secn) + 1; + + if((p = strstr(erase_delim_content(ret), secn))) + *(ret + (strlen(ret) - strlen(p))) = '\0'; + else + ret = NULL; + } + else + ret = NULL; + + free(secn); + + return ret; +} + +char* +get_nsec(char *src, char *name, int n) +{ + int i; + char *ret, *buf, *secn; + char *buf2; + + if(!src) + return NULL; + + if(!name) + return src; + + if(!n) + return get_sec(src, name); + + secn = emalloc((strlen(name) + 2), sizeof(char)); + sprintf(secn, "(%s)", name); + + buf = erase_delim_content(src); + buf2 = erase_sec_content(buf); + + for(i = 0; i < n * 2 && (buf = strstr(buf, secn)); ++i, buf += strlen(secn)); + + ret = get_sec(src + strlen(src) - strlen(buf), name); + + free(secn); + + return ret; +} + +int +get_size_sec(char *src, char *name) +{ + int ret; + char *secn, *buf; + + if(!src || !name) + return 0; + + secn = emalloc(strlen(name), sizeof(char)); + sprintf(secn, "(%s)", name); + + buf = erase_sec_content(src); + + for(ret = 0; (buf = strstr(buf, secn)); ++ret, buf += strlen(secn)); + + /* If a section is not closed */ + for(; ret % 2; --ret); + + free(secn); + + return ret / 2; +} + +opt_type +get_opt(char *src, char *def, char *name) +{ + int i; + char *p = NULL; + opt_type ret = null_opt_type; + + if(!src || !name) + return (def) ? str_to_opt(def) : null_opt_type; + + if((p = opt_srch(erase_sec_content(src), name))) + { + for(i = 0; p[i] && p[i] != '\n'; ++i); + p[i] = '\0'; + + if((p = strchr(p, '=')) && !is_in_delimiter(p, 0)) + ret = str_to_opt(clean_value(++p)); + } + else + ret = str_to_opt(def); + + return ret; +} + +/* option = {val1, val2, val3} */ +opt_type* +get_list_opt(char *src, char *def, char *name, int *n) +{ + int i, j; + char *p, *p2; + opt_type *ret; + + if(!src || !name) + return NULL; + + *n = 0; + + if(!(p = get_opt(src, def, name).str)) + return NULL; + + for(i = 0; p[i] && (p[i] != '}' || is_in_delimiter(p, i)); ++i); + p[i + 1] = '\0'; + + /* Syntax of list (val1, val2, ..., valx) */ + if(*p != '{' || *(p + strlen(p) - 1) != '}') + return NULL; + + /* Erase ( ) */ + ++p; + *(p + strlen(p) - 1) = '\0'; + + /* > 1 value in list */ + if(strchr(p, ',')) + { + /* Count ',' */ + for(i = 0, *n = 1; i < strlen(p); ++i) + if(p[i] == ',' && !is_in_delimiter(p, i)) + ++(*n); + + ret = emalloc(*n, sizeof(opt_type)); + + p2 = _strdup(p); + + /* Set all value in return array */ + for(i = j = 0; i < *n; ++i, p2 += ++j + 1) + { + for(j = 0; j < strlen(p2) && (p2[j] != ',' || is_in_delimiter(p2, j)); ++j); + p2[j] = '\0'; + + ret[i] = str_to_opt(clean_value(p2)); + } + } + else + { + ret = emalloc(1, sizeof(opt_type)); + *ret = str_to_opt(clean_value(p)); + + *n = 1; + } + + return ret; +} diff --git a/src/confparse/confparse.h b/src/confparse/confparse.h new file mode 100644 index 0000000..26d3cfc --- /dev/null +++ b/src/confparse/confparse.h @@ -0,0 +1,71 @@ +/* + * confparse/confparse.h + * Copyright © 2008,2009 Martin Duquesnoy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CONFPARSE_H +#define CONFPARSE_H + +#include +#include +#include + +#include "../wmfs.h" + +#define SEC_DEL_S '[' +#define SEC_DEL_E ']' + +typedef struct +{ + long int num; + float fnum; + Bool bool; + char *str; +} opt_type; + +/* util.c */ +char *erase_delim_content(char *buf); +Bool is_in_delimiter(char *buf, int p); +char *erase_sec_content(char *buf); +char *opt_srch(char *buf, char *opt); +opt_type str_to_opt(char *str); +char *clean_value(char *str); + +/* confparse.c */ +char *file_to_str(FILE *f); +char *get_sec(char *src, char *name); +char *get_nsec(char *src, char *name, int n); +int get_size_sec(char *src, char *name); +opt_type get_opt(char *src, char *def, char *name); +opt_type *get_list_opt(char *src, char *def, char *name, int *n); + +static const opt_type null_opt_type = {0, 0, 0, NULL}; + +#endif /* CONFPARSE_H */ diff --git a/src/confparse/confparse.h~ b/src/confparse/confparse.h~ new file mode 100644 index 0000000..cef8403 --- /dev/null +++ b/src/confparse/confparse.h~ @@ -0,0 +1,68 @@ +/* + * confparse/confparse.h + * Copyright © 2008,2009 Martin Duquesnoy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CONFPARSE_H +#define CONFPARSE_H + +#include +#include +#include + +#include "../wmfs.h" + +typedef struct +{ + long int num; + float fnum; + Bool bool; + char *str; +} opt_type; + +/* util.c */ +char *erase_delim_content(char *buf); +Bool is_in_delimiter(char *buf, int p); +char *erase_sec_content(char *buf); +char *opt_srch(char *buf, char *opt); +opt_type str_to_opt(char *str); +char *clean_value(char *str); + +/* confparse.c */ +char *file_to_str(FILE *f); +char *get_sec(char *src, char *name); +char *get_nsec(char *src, char *name, int n); +int get_size_sec(char *src, char *name); +opt_type get_opt(char *src, char *def, char *name); +opt_type *get_list_opt(char *src, char *def, char *name, int *n); + +static const opt_type null_opt_type = {0, 0, 0, NULL}; + +#endif /* CONFPARSE_H */ diff --git a/src/confparse/util.c b/src/confparse/util.c new file mode 100644 index 0000000..b0ae5b0 --- /dev/null +++ b/src/confparse/util.c @@ -0,0 +1,167 @@ +/* + * confparse/util.c + * Copyright © 2008,2009 Martin Duquesnoy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "confparse.h" + +char* +erase_delim_content(char *buf) +{ + int i, j; + char *str, c; + + if(!buf) + return NULL; + + str = _strdup(buf); + + for(i = 0; i < strlen(str); ++i) + if((c = str[i]) == '"' || (c = str[i]) == '\'') + { + for(str[(j = i)] = ' '; str[j] && str[j] != c; str[j++] = ' '); + str[j] = ' '; + } + + return str; +} + +/* Erase all content of all delimiters, put it + * int str, and check if buf[p] is in an delimiter. */ +Bool +is_in_delimiter(char *buf, int p) +{ + if(*(erase_delim_content(buf) + p) != buf[p]) + return True; + + return False; +} + +char* +erase_sec_content(char *buf) +{ + int i, j; + char *p, *str, *name, *ret; + + if(!buf) + return NULL; + + str = erase_delim_content(buf); + ret = _strdup(buf); + + for(i = 1, name = _strdup(str + i); strchr(str + i, SEC_DEL_S); ++i, name = _strdup(str + i)) + { + for(; str[i] && str[i] != SEC_DEL_S; ++i); + for(j = 0; str[i] && str[i - 1] != SEC_DEL_E; name[j++] = str[i++]); + name[j] = '\0'; + + if((p = strstr(str + i, name))) + for(++i; i < strlen(ret) - strlen(p); ret[i++] = ' '); + else + return ret; + } + + return ret; +} + +/* To get the RIGHT name of an option; if option needed is + * pwet and there is tagadapwettagada in the configuration, + * with strstr(), the name will matchs */ +char* +opt_srch(char *buf, char *opt) +{ + char *p, c1, c2; + + if(!buf || !opt) + return NULL; + + if((p = strstr(erase_delim_content(buf), opt))) + { + c1 = *(p + strlen(opt)); + c2 = *(p - 1); + + if((c1 == ' ' || c1 == '=') + && (c2 == ' ' || c2 == '\n' || c2 == '\t' || !c2)) + return _strdup(buf + (strlen(buf) - strlen(p))); + } + + return NULL; +} + +opt_type +str_to_opt(char *str) +{ + opt_type ret = null_opt_type; + + if(!strlen(str)) + return ret; + + /* Integer */ + ret.num = atoi(str); + + /* Float */ + sscanf(str, "%f", &ret.fnum); + + /* Boolean */ + if(strstr(str, "true") || strstr(str, "True") + || strstr(str, "TRUE") || strstr(str, "1")) + ret.bool = True; + + /* String */ + ret.str = _strdup(str); + + return ret; +} + +char* +clean_value(char *str) +{ + int i; + char c, *p; + + if(!str) + return NULL; + + p = _strdup(str); + + /* Remove useless spaces */ + for(; *p == ' '; ++p); + for(; *(p + strlen(p) - 1) == ' '; *(p + strlen(p) - 1) = '\0'); + + /* For string delimiter (" or ') */ + if(((c = *p) == '"' || (c = *p) == '\'') + && strchr(p + 1, c)) + { + for(++p, i = 0; p[i] && p[i] != c; ++i); + p[i] = '\0'; + } + + return p; +} diff --git a/src/confparse/util.c~ b/src/confparse/util.c~ new file mode 100644 index 0000000..6018caf --- /dev/null +++ b/src/confparse/util.c~ @@ -0,0 +1,167 @@ +/* + * confparse/util.c + * Copyright © 2008,2009 Martin Duquesnoy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "confparse.h" + +char* +erase_delim_content(char *buf) +{ + int i, j; + char *str, c; + + if(!buf) + return NULL; + + str = _strdup(buf); + + for(i = 0; i < strlen(str); ++i) + if((c = str[i]) == '"' || (c = str[i]) == '\'') + { + for(str[(j = i)] = ' '; str[j] && str[j] != c; str[j++] = ' '); + str[j] = ' '; + } + + return str; +} + +/* Erase all content of all delimiters, put it + * int str, and check if buf[p] is in an delimiter. */ +Bool +is_in_delimiter(char *buf, int p) +{ + if(*(erase_delim_content(buf) + p) != buf[p]) + return True; + + return False; +} + +char* +erase_sec_content(char *buf) +{ + int i, j; + char *p, *str, *name, *ret; + + if(!buf) + return NULL; + + str = erase_delim_content(buf); + ret = _strdup(buf); + + for(i = 1, name = _strdup(str + i); strchr(str + i, '('); ++i, name = _strdup(str + i)) + { + for(; str[i] && str[i] != '('; ++i); + for(j = 0; str[i] && str[i - 1] != ')'; name[j++] = str[i++]); + name[j] = '\0'; + + if((p = strstr(str + i, name))) + for(++i; i < strlen(ret) - strlen(p); ret[i++] = ' '); + else + return ret; + } + + return ret; +} + +/* To get the RIGHT name of an option; if option needed is + * pwet and there is tagadapwettagada in the configuration, + * with strstr(), the name will matchs */ +char* +opt_srch(char *buf, char *opt) +{ + char *p, c1, c2; + + if(!buf || !opt) + return NULL; + + if((p = strstr(erase_delim_content(buf), opt))) + { + c1 = *(p + strlen(opt)); + c2 = *(p - 1); + + if((c1 == ' ' || c1 == '=') + && (c2 == ' ' || c2 == '\n' || c2 == '\t' || !c2)) + return _strdup(buf + (strlen(buf) - strlen(p))); + } + + return NULL; +} + +opt_type +str_to_opt(char *str) +{ + opt_type ret = null_opt_type; + + if(!strlen(str)) + return ret; + + /* Integer */ + ret.num = atoi(str); + + /* Float */ + sscanf(str, "%f", &ret.fnum); + + /* Boolean */ + if(strstr(str, "true") || strstr(str, "True") + || strstr(str, "TRUE") || strstr(str, "1")) + ret.bool = True; + + /* String */ + ret.str = _strdup(str); + + return ret; +} + +char* +clean_value(char *str) +{ + int i; + char c, *p; + + if(!str) + return NULL; + + p = _strdup(str); + + /* Remove useless spaces */ + for(; *p == ' '; ++p); + for(; *(p + strlen(p) - 1) == ' '; *(p + strlen(p) - 1) = '\0'); + + /* For string delimiter (" or ') */ + if(((c = *p) == '"' || (c = *p) == '\'') + && strchr(p + 1, c)) + { + for(++p, i = 0; p[i] && p[i] != c; ++i); + p[i] = '\0'; + } + + return p; +}