create a generic tokenizer/sectionizer for the config file. pass off the token to functions registered for each section to parse them further. some fixes for the engine irt font shadows, and fixed a bug with rendering the iconify button when it was not in the layout
This commit is contained in:
parent
4875ff5f8e
commit
71c8b0b7b2
13 changed files with 384 additions and 178 deletions
|
@ -5,7 +5,6 @@ CPPFLAGS=$(XFT_CFLAGS) $(GLIB_CFLAGS) @CPPFLAGS@ \
|
||||||
-DENGINEDIR=\"$(enginedir)\" \
|
-DENGINEDIR=\"$(enginedir)\" \
|
||||||
-DTHEMEDIR=\"$(themedir)\" \
|
-DTHEMEDIR=\"$(themedir)\" \
|
||||||
-DDEFAULT_THEME=\"nyz\" \
|
-DDEFAULT_THEME=\"nyz\" \
|
||||||
-DDEFAULT_FONT=\"Sans-7\" \
|
|
||||||
-DG_LOG_DOMAIN=\"Openbox-Engine\"
|
-DG_LOG_DOMAIN=\"Openbox-Engine\"
|
||||||
|
|
||||||
engine_LTLIBRARIES=openbox.la
|
engine_LTLIBRARIES=openbox.la
|
||||||
|
|
|
@ -36,6 +36,7 @@ color_rgb *ob_s_titlebut_unfocused_color;
|
||||||
int ob_s_winfont_height;
|
int ob_s_winfont_height;
|
||||||
int ob_s_winfont_shadow;
|
int ob_s_winfont_shadow;
|
||||||
int ob_s_winfont_shadow_offset;
|
int ob_s_winfont_shadow_offset;
|
||||||
|
int ob_s_winfont_shadow_tint;
|
||||||
ObFont *ob_s_winfont;
|
ObFont *ob_s_winfont;
|
||||||
/* style settings - masks */
|
/* style settings - masks */
|
||||||
pixmap_mask *ob_s_max_set_mask;
|
pixmap_mask *ob_s_max_set_mask;
|
||||||
|
@ -495,7 +496,7 @@ void frame_adjust_area(ObFrame *self, gboolean moved, gboolean resized)
|
||||||
self->icon_x = -1;
|
self->icon_x = -1;
|
||||||
self->desk_x = -1;
|
self->desk_x = -1;
|
||||||
self->shade_x = -1;
|
self->shade_x = -1;
|
||||||
self->icon_x = -1;
|
self->iconify_x = -1;
|
||||||
self->label_x = -1;
|
self->label_x = -1;
|
||||||
self->max_x = -1;
|
self->max_x = -1;
|
||||||
self->close_x = -1;
|
self->close_x = -1;
|
||||||
|
@ -712,10 +713,8 @@ static void layout_title(ObFrame *self)
|
||||||
|
|
||||||
n = d = i = l = m = c = s = FALSE;
|
n = d = i = l = m = c = s = FALSE;
|
||||||
|
|
||||||
if (!config_get("titlebar.layout", Config_String, &layout)) {
|
if (!config_get("titlebar.layout", Config_String, &layout))
|
||||||
layout.string = "NDSLIMC";
|
g_assert_not_reached();
|
||||||
config_set("titlebar.layout", Config_String, layout);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* figure out whats being shown, and the width of the label */
|
/* figure out whats being shown, and the width of the label */
|
||||||
self->label_width = self->width - (ob_s_bevel + 1) * 2;
|
self->label_width = self->width - (ob_s_bevel + 1) * 2;
|
||||||
|
|
|
@ -30,6 +30,7 @@ extern color_rgb *ob_s_titlebut_unfocused_color;
|
||||||
extern int ob_s_winfont_height;
|
extern int ob_s_winfont_height;
|
||||||
extern int ob_s_winfont_shadow;
|
extern int ob_s_winfont_shadow;
|
||||||
extern int ob_s_winfont_shadow_offset;
|
extern int ob_s_winfont_shadow_offset;
|
||||||
|
extern int ob_s_winfont_shadow_tint;
|
||||||
extern ObFont *ob_s_winfont;
|
extern ObFont *ob_s_winfont;
|
||||||
|
|
||||||
extern pixmap_mask *ob_s_max_set_mask;
|
extern pixmap_mask *ob_s_max_set_mask;
|
||||||
|
|
|
@ -277,7 +277,7 @@ gboolean obtheme_load()
|
||||||
XrmDatabase db = NULL;
|
XrmDatabase db = NULL;
|
||||||
Justify winjust;
|
Justify winjust;
|
||||||
char *winjuststr;
|
char *winjuststr;
|
||||||
ConfigValue theme, shadow, offset, font;
|
ConfigValue theme, shadow, offset, font, tint;
|
||||||
|
|
||||||
if (config_get("theme", Config_String, &theme)) {
|
if (config_get("theme", Config_String, &theme)) {
|
||||||
db = loaddb(theme.string);
|
db = loaddb(theme.string);
|
||||||
|
@ -299,21 +299,21 @@ gboolean obtheme_load()
|
||||||
|
|
||||||
/* load the font, not from the theme file tho, its in the config */
|
/* load the font, not from the theme file tho, its in the config */
|
||||||
|
|
||||||
if (!config_get("font.shadow", Config_Bool, &shadow)) {
|
if (!config_get("font.shadow", Config_Bool, &shadow))
|
||||||
shadow.bool = TRUE; /* default */
|
g_assert_not_reached();
|
||||||
config_set("font.shadow", Config_Bool, shadow);
|
|
||||||
}
|
|
||||||
ob_s_winfont_shadow = shadow.bool;
|
ob_s_winfont_shadow = shadow.bool;
|
||||||
if (!config_get("font.shadow.offset", Config_Integer, &offset) ||
|
if (!config_get("font.shadow.offset", Config_Integer, &offset))
|
||||||
offset.integer < 0 || offset.integer >= 10) {
|
g_assert_not_reached();
|
||||||
offset.integer = 1; /* default */
|
|
||||||
config_set("font.shadow.offset", Config_Integer, offset);
|
|
||||||
}
|
|
||||||
ob_s_winfont_shadow_offset = offset.integer;
|
ob_s_winfont_shadow_offset = offset.integer;
|
||||||
if (!config_get("font", Config_String, &font)) {
|
if (!config_get("font.shadow.tint", Config_Integer, &tint))
|
||||||
font.string = DEFAULT_FONT;
|
g_assert_not_reached();
|
||||||
config_set("font", Config_String, font);
|
/* XXX put these checks into the config system somehow!!! */
|
||||||
}
|
if (tint.integer < -100) tint.integer = -100;
|
||||||
|
if (tint.integer > 100) tint.integer = 100;
|
||||||
|
config_set("font.shadow.tint", Config_Integer, tint);
|
||||||
|
ob_s_winfont_shadow_tint = tint.integer;
|
||||||
|
if (!config_get("font", Config_String, &font))
|
||||||
|
g_assert_not_reached();
|
||||||
ob_s_winfont = font_open(font.string);
|
ob_s_winfont = font_open(font.string);
|
||||||
ob_s_winfont_height = font_height(ob_s_winfont, ob_s_winfont_shadow,
|
ob_s_winfont_height = font_height(ob_s_winfont, ob_s_winfont_shadow,
|
||||||
ob_s_winfont_shadow_offset);
|
ob_s_winfont_shadow_offset);
|
||||||
|
@ -495,6 +495,7 @@ gboolean obtheme_load()
|
||||||
ob_a_focused_label->texture[0].data.text.shadow = ob_s_winfont_shadow;
|
ob_a_focused_label->texture[0].data.text.shadow = ob_s_winfont_shadow;
|
||||||
ob_a_focused_label->texture[0].data.text.offset =
|
ob_a_focused_label->texture[0].data.text.offset =
|
||||||
ob_s_winfont_shadow_offset;
|
ob_s_winfont_shadow_offset;
|
||||||
|
ob_a_focused_label->texture[0].data.text.tint = ob_s_winfont_shadow_tint;
|
||||||
ob_a_focused_label->texture[0].data.text.color = ob_s_title_focused_color;
|
ob_a_focused_label->texture[0].data.text.color = ob_s_title_focused_color;
|
||||||
|
|
||||||
ob_a_unfocused_label->texture[0].type = Text;
|
ob_a_unfocused_label->texture[0].type = Text;
|
||||||
|
@ -503,6 +504,7 @@ gboolean obtheme_load()
|
||||||
ob_a_unfocused_label->texture[0].data.text.shadow = ob_s_winfont_shadow;
|
ob_a_unfocused_label->texture[0].data.text.shadow = ob_s_winfont_shadow;
|
||||||
ob_a_unfocused_label->texture[0].data.text.offset =
|
ob_a_unfocused_label->texture[0].data.text.offset =
|
||||||
ob_s_winfont_shadow_offset;
|
ob_s_winfont_shadow_offset;
|
||||||
|
ob_a_unfocused_label->texture[0].data.text.tint = ob_s_winfont_shadow_tint;
|
||||||
ob_a_unfocused_label->texture[0].data.text.color =
|
ob_a_unfocused_label->texture[0].data.text.color =
|
||||||
ob_s_title_unfocused_color;
|
ob_s_title_unfocused_color;
|
||||||
|
|
||||||
|
|
|
@ -27,14 +27,18 @@ openbox3_LDADD=@LIBINTL@ ../render/librender.a
|
||||||
openbox3_LDFLAGS=-export-dynamic
|
openbox3_LDFLAGS=-export-dynamic
|
||||||
openbox3_SOURCES=client.c event.c extensions.c focus.c frame.c openbox.c \
|
openbox3_SOURCES=client.c event.c extensions.c focus.c frame.c openbox.c \
|
||||||
prop.c screen.c stacking.c xerror.c timer.c dispatch.c \
|
prop.c screen.c stacking.c xerror.c timer.c dispatch.c \
|
||||||
engine.c plugin.c action.c grab.c lex.cparse.c config.c menu.c
|
engine.c plugin.c action.c grab.c config.c menu.c \
|
||||||
|
y.tab.c lex.yy.c parse.c
|
||||||
|
|
||||||
noinst_HEADERS=client.h event.h extensions.h focus.h frame.h geom.h gettext.h \
|
noinst_HEADERS=client.h event.h extensions.h focus.h frame.h geom.h gettext.h \
|
||||||
openbox.h prop.h screen.h stacking.h xerror.h dispatch.h \
|
openbox.h prop.h screen.h stacking.h xerror.h dispatch.h \
|
||||||
timer.h engine.h plugin.h action.h grab.h config.h menu.h
|
timer.h engine.h plugin.h action.h grab.h config.h menu.h parse.h
|
||||||
|
|
||||||
lex.cparse.c: cparse.l
|
lex.yy.c: parse.l
|
||||||
$(FLEX) -Pcparse $^
|
$(FLEX) $^
|
||||||
|
|
||||||
|
y.tab.c: parse.yacc
|
||||||
|
$(YACC) -d $<
|
||||||
|
|
||||||
MAINTAINERCLEANFILES= Makefile.in
|
MAINTAINERCLEANFILES= Makefile.in
|
||||||
|
|
||||||
|
|
|
@ -25,26 +25,47 @@ void config_startup()
|
||||||
"Engine",
|
"Engine",
|
||||||
"The name of the theming engine to be used "
|
"The name of the theming engine to be used "
|
||||||
"to decorate windows."));
|
"to decorate windows."));
|
||||||
|
|
||||||
config_def_set(config_def_new("theme", Config_String,
|
config_def_set(config_def_new("theme", Config_String,
|
||||||
"Theme",
|
"Theme",
|
||||||
"The name of the theme to load with the "
|
"The name of the theme to load with the "
|
||||||
"chosen engine."));
|
"chosen engine."));
|
||||||
|
|
||||||
config_def_set(config_def_new("font", Config_String,
|
config_def_set(config_def_new("font", Config_String,
|
||||||
"Titlebar Font",
|
"Titlebar Font",
|
||||||
"The fontstring specifying the font to "
|
"The fontstring specifying the font to "
|
||||||
"be used in window titlebars."));
|
"be used in window titlebars."));
|
||||||
|
val.string = "Sans-7";
|
||||||
|
config_set("font", Config_String, val);
|
||||||
|
|
||||||
config_def_set(config_def_new("font.shadow", Config_Bool,
|
config_def_set(config_def_new("font.shadow", Config_Bool,
|
||||||
"Titlebar Font Shadow",
|
"Titlebar Font Shadow",
|
||||||
"Whether or not the text in the window "
|
"Whether or not the text in the window "
|
||||||
"titlebars gets a drop shadow."));
|
"titlebars gets a drop shadow."));
|
||||||
|
val.bool = FALSE;
|
||||||
|
config_set("font.shadow", Config_Bool, val);
|
||||||
|
|
||||||
config_def_set(config_def_new("font.shadow.offset", Config_Integer,
|
config_def_set(config_def_new("font.shadow.offset", Config_Integer,
|
||||||
"Titlebar Font Shadow Offset",
|
"Titlebar Font Shadow Offset",
|
||||||
"The offset of the drop shadow for text "
|
"The offset of the drop shadow for text "
|
||||||
"in the window titlebars."));
|
"in the window titlebars."));
|
||||||
|
val.integer = 1;
|
||||||
|
config_set("font.shadow.offset", Config_Integer, val);
|
||||||
|
|
||||||
|
config_def_set(config_def_new("font.shadow.tint", Config_Integer,
|
||||||
|
"Titlebar Font Shadow Tint",
|
||||||
|
"The percentage of tint/opacity to give the "
|
||||||
|
"the shadow(from -100(white) to "
|
||||||
|
"100(black))."));
|
||||||
|
val.integer = 25;
|
||||||
|
config_set("font.shadow.tint", Config_Integer, val);
|
||||||
|
|
||||||
config_def_set(config_def_new("titlebar.layout", Config_String,
|
config_def_set(config_def_new("titlebar.layout", Config_String,
|
||||||
"Titlebar Layout",
|
"Titlebar Layout",
|
||||||
"The ordering of the elements in the "
|
"The ordering of the elements in the "
|
||||||
"window titlebars."));
|
"window titlebars."));
|
||||||
|
val.string = "NDSLIMC";
|
||||||
|
config_set("titlebar.layout", Config_String, val);
|
||||||
|
|
||||||
config_def_set(config_def_new("focusNew", Config_Bool,
|
config_def_set(config_def_new("focusNew", Config_Bool,
|
||||||
"Focus New Windows",
|
"Focus New Windows",
|
||||||
|
@ -66,32 +87,6 @@ void config_shutdown()
|
||||||
g_datalist_clear(&config_def);
|
g_datalist_clear(&config_def);
|
||||||
}
|
}
|
||||||
|
|
||||||
void config_parse()
|
|
||||||
{
|
|
||||||
FILE *file;
|
|
||||||
char *path;
|
|
||||||
gboolean load = FALSE;
|
|
||||||
|
|
||||||
/* load the user rc */
|
|
||||||
path = g_build_filename(g_get_home_dir(), ".openbox", "rc3", NULL);
|
|
||||||
if ((file = fopen(path, "r")) != NULL) {
|
|
||||||
cparse_go(path, file);
|
|
||||||
fclose(file);
|
|
||||||
load = TRUE;
|
|
||||||
}
|
|
||||||
g_free(path);
|
|
||||||
|
|
||||||
if (!load) {
|
|
||||||
/* load the system wide rc */
|
|
||||||
path = g_build_filename(RCDIR, "rc3", NULL);
|
|
||||||
if ((file = fopen(path, "r")) != NULL) {
|
|
||||||
/*cparse_go(path, file);*/
|
|
||||||
fclose(file);
|
|
||||||
}
|
|
||||||
g_free(path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gboolean config_set(char *name, ConfigValueType type, ConfigValue value)
|
gboolean config_set(char *name, ConfigValueType type, ConfigValue value)
|
||||||
{
|
{
|
||||||
ConfigDefEntry *def;
|
ConfigDefEntry *def;
|
||||||
|
|
|
@ -54,6 +54,4 @@ gboolean config_def_add_value(ConfigDefEntry *entry, char *value);
|
||||||
FALSE. */
|
FALSE. */
|
||||||
gboolean config_def_set(ConfigDefEntry *entry);
|
gboolean config_def_set(ConfigDefEntry *entry);
|
||||||
|
|
||||||
void config_parse();
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
124
openbox/cparse.l
124
openbox/cparse.l
|
@ -1,124 +0,0 @@
|
||||||
%{
|
|
||||||
#include <glib.h>
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
static char *filename;
|
|
||||||
static int lineno = 1;
|
|
||||||
static gboolean haserror = FALSE;
|
|
||||||
static gboolean comment = FALSE;
|
|
||||||
static ConfigEntry entry = { NULL, -1 };
|
|
||||||
|
|
||||||
static void stringvalue();
|
|
||||||
static void numbervalue();
|
|
||||||
static void boolvalue();
|
|
||||||
static void identifier();
|
|
||||||
static void newline();
|
|
||||||
static int cparsewrap();
|
|
||||||
%}
|
|
||||||
|
|
||||||
number [0-9]+
|
|
||||||
string \"[^"\n]*\"
|
|
||||||
identifier [a-zA-Z][a-zA-Z0-9_.]*
|
|
||||||
white [ \t]*
|
|
||||||
assign {white}={white}
|
|
||||||
bool ([tT][rR][uU][eE]|[fF][aA][lL][sS][eE]|[yY][eE][sS]|[nN][oO]|[oO][nN]|[oO][fF][fF])
|
|
||||||
|
|
||||||
%%
|
|
||||||
|
|
||||||
^{white}# comment = TRUE;
|
|
||||||
{bool}/{white}\n boolvalue();
|
|
||||||
{string}/{white}\n stringvalue();
|
|
||||||
{number}/{white}\n numbervalue();
|
|
||||||
^{identifier}/{assign} identifier();
|
|
||||||
\n newline();
|
|
||||||
=
|
|
||||||
[ \t]
|
|
||||||
. if (!comment) haserror = TRUE;
|
|
||||||
|
|
||||||
%%
|
|
||||||
|
|
||||||
static void stringvalue()
|
|
||||||
{
|
|
||||||
if (!comment) {
|
|
||||||
if (!haserror && entry.name != NULL && (signed)entry.type < 0) {
|
|
||||||
entry.type = Config_String;
|
|
||||||
entry.value.string = g_strdup(cparsetext+1); /* drop the left quote */
|
|
||||||
if (entry.value.string[cparseleng-2] != '"')
|
|
||||||
g_warning("improperly terminated string on line %d",
|
|
||||||
lineno);
|
|
||||||
else
|
|
||||||
entry.value.string[cparseleng-2] = '\0';
|
|
||||||
} else
|
|
||||||
haserror = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void numbervalue()
|
|
||||||
{
|
|
||||||
if (!comment) {
|
|
||||||
if (!haserror && entry.name != NULL && (signed)entry.type < 0) {
|
|
||||||
entry.type = Config_Integer;
|
|
||||||
entry.value.integer = atoi(cparsetext);
|
|
||||||
} else
|
|
||||||
haserror = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void boolvalue()
|
|
||||||
{
|
|
||||||
if (!comment) {
|
|
||||||
if (!haserror && entry.name != NULL && (signed)entry.type < 0) {
|
|
||||||
entry.type = Config_Bool;
|
|
||||||
entry.value.bool = (!g_ascii_strcasecmp("true", cparsetext) ||
|
|
||||||
!g_ascii_strcasecmp("yes", cparsetext) ||
|
|
||||||
!g_ascii_strcasecmp("on", cparsetext));
|
|
||||||
} else
|
|
||||||
haserror = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void identifier()
|
|
||||||
{
|
|
||||||
if (!comment) {
|
|
||||||
entry.name = g_strdup(cparsetext);
|
|
||||||
entry.type = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void newline()
|
|
||||||
{
|
|
||||||
if (!comment) {
|
|
||||||
if (!haserror && entry.name != NULL && (signed)entry.type >= 0) {
|
|
||||||
if (!config_set(entry.name, entry.type, entry.value))
|
|
||||||
g_warning("Parser error in '%s' on line %d\n", filename,
|
|
||||||
lineno);
|
|
||||||
} else if (haserror || entry.name != NULL || (signed)entry.type >= 0) {
|
|
||||||
g_warning("Parser error in '%s' on line %d", filename, lineno);
|
|
||||||
}
|
|
||||||
g_free(entry.name);
|
|
||||||
entry.name = NULL;
|
|
||||||
if (entry.type == Config_String)
|
|
||||||
g_free(entry.value.string);
|
|
||||||
entry.type = -1;
|
|
||||||
|
|
||||||
haserror = FALSE;
|
|
||||||
}
|
|
||||||
comment = FALSE;
|
|
||||||
++lineno;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int cparsewrap()
|
|
||||||
{
|
|
||||||
g_free(entry.name);
|
|
||||||
entry.name = NULL;
|
|
||||||
if (entry.type == Config_String)
|
|
||||||
g_free(entry.value.string);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cparse_go(char *fname, FILE *file)
|
|
||||||
{
|
|
||||||
filename = fname;
|
|
||||||
cparsein = file;
|
|
||||||
cparselex();
|
|
||||||
}
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "extensions.h"
|
#include "extensions.h"
|
||||||
#include "gettext.h"
|
#include "gettext.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "parse.h"
|
||||||
#include "grab.h"
|
#include "grab.h"
|
||||||
#include "engine.h"
|
#include "engine.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
|
@ -153,10 +154,16 @@ int main(int argc, char **argv)
|
||||||
font_startup();
|
font_startup();
|
||||||
plugin_startup();
|
plugin_startup();
|
||||||
|
|
||||||
|
/* startup the parsing so plugins can register sections of the rc */
|
||||||
|
parse_startup();
|
||||||
|
|
||||||
/* load the plugins specified in the pluginrc */
|
/* load the plugins specified in the pluginrc */
|
||||||
plugin_loadall();
|
plugin_loadall();
|
||||||
/* parse/load user options */
|
/* parse/load user options */
|
||||||
config_parse();
|
parse_rc();
|
||||||
|
|
||||||
|
/* we're done with parsing now, kill it */
|
||||||
|
parse_shutdown();
|
||||||
|
|
||||||
engine_startup();
|
engine_startup();
|
||||||
event_startup();
|
event_startup();
|
||||||
|
|
137
openbox/parse.c
Normal file
137
openbox/parse.c
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
#include "parse.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
static GHashTable *reg = NULL;
|
||||||
|
static ParseFunc func = NULL;
|
||||||
|
|
||||||
|
/* parse tokens from the [openbox] section of the rc file */
|
||||||
|
static void parse_rc_token(ParseTokenType type, union ParseToken token);
|
||||||
|
|
||||||
|
void destkey(gpointer key) { g_free(key); }
|
||||||
|
|
||||||
|
void parse_startup()
|
||||||
|
{
|
||||||
|
reg = g_hash_table_new_full(g_str_hash, g_str_equal, destkey, NULL);
|
||||||
|
func = NULL;
|
||||||
|
|
||||||
|
parse_reg_section("openbox", parse_rc_token);
|
||||||
|
}
|
||||||
|
|
||||||
|
void parse_shutdown()
|
||||||
|
{
|
||||||
|
g_hash_table_destroy(reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void parse_reg_section(char *section, ParseFunc func)
|
||||||
|
{
|
||||||
|
if (g_hash_table_lookup(reg, section) != NULL)
|
||||||
|
g_warning("duplicate request for section '%s' in the rc file",
|
||||||
|
section);
|
||||||
|
else
|
||||||
|
g_hash_table_insert(reg, g_ascii_strdown(section, -1), (void*)func);
|
||||||
|
}
|
||||||
|
|
||||||
|
void parse_free_token(ParseTokenType type, union ParseToken token)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case TOKEN_STRING:
|
||||||
|
g_free(token.string);
|
||||||
|
break;
|
||||||
|
case TOKEN_IDENTIFIER:
|
||||||
|
g_free(token.identifier);
|
||||||
|
break;
|
||||||
|
case TOKEN_REAL:
|
||||||
|
case TOKEN_INTEGER:
|
||||||
|
case TOKEN_BOOL:
|
||||||
|
case TOKEN_LBRACKET:
|
||||||
|
case TOKEN_RBRACKET:
|
||||||
|
case TOKEN_LBRACE:
|
||||||
|
case TOKEN_RBRACE:
|
||||||
|
case TOKEN_EQUALS:
|
||||||
|
case TOKEN_COMMA:
|
||||||
|
case TOKEN_NEWLINE:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void parse_set_section(char *section)
|
||||||
|
{
|
||||||
|
func = (ParseFunc)g_hash_table_lookup(reg, section);
|
||||||
|
}
|
||||||
|
|
||||||
|
void parse_token(ParseTokenType type, union ParseToken token)
|
||||||
|
{
|
||||||
|
if (func != NULL)
|
||||||
|
func(type, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void parse_rc_token(ParseTokenType type, union ParseToken token)
|
||||||
|
{
|
||||||
|
static int got_eq = FALSE;
|
||||||
|
static ParseTokenType got_val = 0;
|
||||||
|
static char *id = NULL, *s = NULL;
|
||||||
|
static int i;
|
||||||
|
static gboolean b;
|
||||||
|
|
||||||
|
if (id == NULL) {
|
||||||
|
if (type == TOKEN_IDENTIFIER) {
|
||||||
|
id = token.identifier;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
yyerror("syntax error");
|
||||||
|
}
|
||||||
|
} else if (!got_eq) {
|
||||||
|
if (type == TOKEN_EQUALS) {
|
||||||
|
got_eq = TRUE;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
yyerror("syntax error");
|
||||||
|
}
|
||||||
|
} else if (!got_val) {
|
||||||
|
if (type == TOKEN_STRING) {
|
||||||
|
s = token.string;
|
||||||
|
got_val = type;
|
||||||
|
return;
|
||||||
|
} else if (type == TOKEN_BOOL) {
|
||||||
|
b = token.bool;
|
||||||
|
got_val = type;
|
||||||
|
return;
|
||||||
|
} else if (type == TOKEN_INTEGER) {
|
||||||
|
i = token.integer;
|
||||||
|
got_val = type;
|
||||||
|
return;
|
||||||
|
} else
|
||||||
|
yyerror("syntax error");
|
||||||
|
} else if (type != TOKEN_NEWLINE) {
|
||||||
|
yyerror("syntax error");
|
||||||
|
} else {
|
||||||
|
ConfigValue v;
|
||||||
|
|
||||||
|
switch (got_val) {
|
||||||
|
case TOKEN_STRING:
|
||||||
|
v.string = s;
|
||||||
|
if (!config_set(id, Config_String, v))
|
||||||
|
yyerror("invalid value type");
|
||||||
|
break;
|
||||||
|
case TOKEN_BOOL:
|
||||||
|
v.bool = b;
|
||||||
|
if (!config_set(id, Config_Bool, v))
|
||||||
|
yyerror("invalid value type");
|
||||||
|
break;
|
||||||
|
case TOKEN_INTEGER:
|
||||||
|
v.integer = i;
|
||||||
|
if (!config_set(id, Config_Integer, v))
|
||||||
|
yyerror("invalid value type");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached(); /* unhandled type got parsed */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free(id);
|
||||||
|
g_free(s);
|
||||||
|
id = s = NULL;
|
||||||
|
got_eq = FALSE;
|
||||||
|
got_val = 0;
|
||||||
|
parse_free_token(type, token);
|
||||||
|
}
|
42
openbox/parse.h
Normal file
42
openbox/parse.h
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
#ifndef __parse_h
|
||||||
|
#define __parse_h
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include "y.tab.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
TOKEN_REAL = REAL,
|
||||||
|
TOKEN_INTEGER = INTEGER,
|
||||||
|
TOKEN_STRING = STRING,
|
||||||
|
TOKEN_IDENTIFIER = IDENTIFIER,
|
||||||
|
TOKEN_BOOL = BOOL,
|
||||||
|
TOKEN_LBRACKET = '(',
|
||||||
|
TOKEN_RBRACKET = ')',
|
||||||
|
TOKEN_LBRACE = '{',
|
||||||
|
TOKEN_RBRACE = '}',
|
||||||
|
TOKEN_EQUALS = '=',
|
||||||
|
TOKEN_COMMA = ',',
|
||||||
|
TOKEN_NEWLINE = '\n'
|
||||||
|
} ParseTokenType;
|
||||||
|
|
||||||
|
typedef void (*ParseFunc)(ParseTokenType type, union ParseToken token);
|
||||||
|
|
||||||
|
void parse_startup();
|
||||||
|
void parse_shutdown();
|
||||||
|
|
||||||
|
/* Parse the RC file
|
||||||
|
found in parse.yacc
|
||||||
|
*/
|
||||||
|
void parse_rc();
|
||||||
|
|
||||||
|
void parse_reg_section(char *section, ParseFunc func);
|
||||||
|
|
||||||
|
|
||||||
|
/* Free a parsed token's allocated memory */
|
||||||
|
void parse_free_token(ParseTokenType type, union ParseToken token);
|
||||||
|
|
||||||
|
/* Display an error message while parsing.
|
||||||
|
found in parse.yacc */
|
||||||
|
void yyerror(char *err);
|
||||||
|
|
||||||
|
#endif
|
48
openbox/parse.l
Normal file
48
openbox/parse.l
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
%{
|
||||||
|
#include <glib.h>
|
||||||
|
#include "y.tab.h"
|
||||||
|
#ifdef HAVE_STDLIB_H
|
||||||
|
# include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern void yyerror(char *err);
|
||||||
|
|
||||||
|
int yylineno = 1;
|
||||||
|
%}
|
||||||
|
|
||||||
|
real [-0-9][0-9]*\.[0-9]+
|
||||||
|
integer [-0-9][0-9]*
|
||||||
|
string \"[^"\n]*\"
|
||||||
|
identifier [a-zA-Z][.a-zA-Z0-9]*
|
||||||
|
bool ([tT][rR][uU][eE]|[fF][aA][lL][sS][eE]|[yY][eE][sS]|[nN][oO]|[oO][nN]|[oO][fF][fF])
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
^[ \t]*#.*\n /* comment */ { ++yylineno; }
|
||||||
|
^[ \t]*#.* /* comment */
|
||||||
|
^[ \t]*\n /* empty lines */ { ++yylineno; }
|
||||||
|
[ \t] /* whitespace */
|
||||||
|
{real} { yylval.real = atof(yytext); return REAL; }
|
||||||
|
{integer} { yylval.integer = atoi(yytext); return INTEGER; }
|
||||||
|
{string} { yylval.string = g_strdup(yytext+1); /* drop the left quote */
|
||||||
|
if (yylval.string[yyleng-2] != '"')
|
||||||
|
yyerror("improperly terminated string on line %d");
|
||||||
|
else
|
||||||
|
yylval.string[yyleng-2] = '\0';
|
||||||
|
return STRING;
|
||||||
|
}
|
||||||
|
{bool} { yylval.bool = (!g_ascii_strcasecmp("true", yytext) ||
|
||||||
|
!g_ascii_strcasecmp("yes", yytext) ||
|
||||||
|
!g_ascii_strcasecmp("on", yytext));
|
||||||
|
return BOOL;
|
||||||
|
}
|
||||||
|
{identifier} { yylval.identifier = g_strdup(yytext); return IDENTIFIER; }
|
||||||
|
[{}()\[\]=,] { yylval.character = *yytext; return *yytext; }
|
||||||
|
\n { yylval.character = *yytext; ++yylineno; return *yytext; }
|
||||||
|
. { return INVALID; }
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
int yywrap() {
|
||||||
|
return 1;
|
||||||
|
}
|
98
openbox/parse.yacc
Normal file
98
openbox/parse.yacc
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
%{
|
||||||
|
#include "parse.h"
|
||||||
|
#ifdef HAVE_STDIO_H
|
||||||
|
# include <stdio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern int yylex();
|
||||||
|
|
||||||
|
extern int yylineno;
|
||||||
|
extern FILE *yyin;
|
||||||
|
|
||||||
|
static char *path;
|
||||||
|
static union ParseToken t;
|
||||||
|
|
||||||
|
/* in parse.c */
|
||||||
|
void parse_token(ParseTokenType type, union ParseToken token);
|
||||||
|
void parse_set_section(char *section);
|
||||||
|
%}
|
||||||
|
|
||||||
|
%union ParseToken {
|
||||||
|
float real;
|
||||||
|
int integer;
|
||||||
|
char *string;
|
||||||
|
char *identifier;
|
||||||
|
gboolean bool;
|
||||||
|
char character;
|
||||||
|
}
|
||||||
|
|
||||||
|
%token <real> REAL
|
||||||
|
%token <integer> INTEGER
|
||||||
|
%token <string> STRING
|
||||||
|
%token <identifier> IDENTIFIER
|
||||||
|
%token <bool> BOOL
|
||||||
|
%token <character> '('
|
||||||
|
%token <character> ')'
|
||||||
|
%token <character> '{'
|
||||||
|
%token <character> '}'
|
||||||
|
%token <character> '='
|
||||||
|
%token <character> ','
|
||||||
|
%token <character> '\n'
|
||||||
|
%token INVALID
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
sections:
|
||||||
|
| sections '[' IDENTIFIER ']' { parse_set_section($3); } '\n' lines
|
||||||
|
;
|
||||||
|
|
||||||
|
lines:
|
||||||
|
| lines tokens '\n' { t.character = $3; parse_token(TOKEN_NEWLINE, t); }
|
||||||
|
;
|
||||||
|
|
||||||
|
tokens:
|
||||||
|
tokens token
|
||||||
|
| token
|
||||||
|
;
|
||||||
|
|
||||||
|
token:
|
||||||
|
REAL { t.real = $1; parse_token(TOKEN_REAL, t); }
|
||||||
|
| INTEGER { t.integer = $1; parse_token(TOKEN_INTEGER, t); }
|
||||||
|
| STRING { t.string = $1; parse_token(TOKEN_STRING, t); }
|
||||||
|
| IDENTIFIER { t.identifier = $1; parse_token(TOKEN_IDENTIFIER, t); }
|
||||||
|
| BOOL { t.bool = $1; parse_token(TOKEN_BOOL, t); }
|
||||||
|
| '(' { t.character = $1; parse_token(TOKEN_LBRACKET, t); }
|
||||||
|
| ')' { t.character = $1; parse_token(TOKEN_RBRACKET, t); }
|
||||||
|
| '{' { t.character = $1; parse_token(TOKEN_LBRACE, t); }
|
||||||
|
| '}' { t.character = $1; parse_token(TOKEN_RBRACE, t); }
|
||||||
|
| '=' { t.character = $1; parse_token(TOKEN_EQUALS, t); }
|
||||||
|
| ',' { t.character = $1; parse_token(TOKEN_COMMA, t); }
|
||||||
|
;
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
void yyerror(char *err) {
|
||||||
|
g_message("%s:%d: %s", path, yylineno, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
void parse_rc()
|
||||||
|
{
|
||||||
|
/* try the user's rc */
|
||||||
|
path = g_build_filename(g_get_home_dir(), ".openbox", "rc3", NULL);
|
||||||
|
if ((yyin = fopen(path, "r")) == NULL) {
|
||||||
|
g_free(path);
|
||||||
|
/* try the system wide rc */
|
||||||
|
path = g_build_filename(RCDIR, "rc3", NULL);
|
||||||
|
if ((yyin = fopen(path, "r")) == NULL) {
|
||||||
|
g_warning("No rc2 file found!");
|
||||||
|
g_free(path);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
yylineno = 1;
|
||||||
|
|
||||||
|
yyparse();
|
||||||
|
|
||||||
|
g_free(path);
|
||||||
|
}
|
Loading…
Reference in a new issue