From 9eb9701c9490a5008b183db8558bd2fd12172fdf Mon Sep 17 00:00:00 2001
From: Christophe CURIS <[email protected]>
Date: Sun, 17 Jun 2012 23:20:33 +0200
Subject: [PATCH 1/7] Remove dependency to CPP: Moving parser functions to a
dedicated file
Due to the tasks to take in charge, the internal parser will grow, so
it is a good idea to start by moving the current functions into a
dedicated file.
The parser now uses a structure used to keep track of what's going on.
Took opportunity to de-CamelCase function 'parseCascade'
---
src/Makefile.am | 1 +
src/rootmenu.c | 152 +++++++-------------------------------------
src/rootmenu.h | 26 ++++++++
src/rootmenuparser.c | 173 ++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 223 insertions(+), 129 deletions(-)
create mode 100644 src/rootmenuparser.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 0521d11..7af56ec 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -59,6 +59,7 @@ wmaker_SOURCES = \
resources.h \
rootmenu.c \
rootmenu.h \
+ rootmenuparser.c \
screen.c \
screen.h \
session.h \
diff --git a/src/rootmenu.c b/src/rootmenu.c
index c32411d..5b384ad 100644
--- a/src/rootmenu.c
+++ b/src/rootmenu.c
@@ -50,6 +50,7 @@
#include "framewin.h"
#include "session.h"
#include "xmodifier.h"
+#include "rootmenu.h"
#include <WINGs/WUtil.h>
@@ -409,7 +410,7 @@ static void removeShortcutsForMenu(WMenu * menu)
menu->menu->screen_ptr->flags.root_menu_changed_shortcuts = 1;
}
-static Bool addShortcut(char *file, char *shortcutDefinition, WMenu * menu, WMenuEntry * entry)
+static Bool addShortcut(const char *file, char *shortcutDefinition, WMenu * menu, WMenuEntry * entry)
{
Shortcut *ptr;
KeySym ksym;
@@ -758,7 +759,7 @@ static WMenuEntry *addWindowsMenu(WScreen * scr, WMenu * menu, char *title)
}
static WMenuEntry *addMenuEntry(WMenu * menu, char *title, char *shortcut, char *command,
- char *params, char *file_name)
+ char *params, const char *file_name)
{
WScreen *scr;
WMenuEntry *entry = NULL;
@@ -890,113 +891,15 @@ static void freeline(char *title, char *command, char *parameter, char *shortcut
wfree(shortcut);
}
-static void separateline(char *line, char **title, char **command, char **parameter, char **shortcut)
+static WMenu *menu_parse_cascade(WScreen * scr, WMenu * menu, WMenuParser parser)
{
- char *suffix, *next = line;
-
- *title = NULL;
- *command = NULL;
- *parameter = NULL;
- *shortcut = NULL;
-
- /* get the title */
- *title = wtokennext(line, &next);
- if (next == NULL)
- return;
- line = next;
-
- /* get the command or shortcut keyword */
- *command = wtokennext(line, &next);
- if (next == NULL)
- return;
- line = next;
-
- if (*command != NULL && strcmp(*command, "SHORTCUT") == 0) {
- /* get the shortcut */
- *shortcut = wtokennext(line, &next);
- if (next == NULL)
- return;
- line = next;
-
- /* get the command */
- *command = wtokennext(line, &next);
- if (next == NULL)
- return;
- line = next;
- }
-
- /* get the parameters */
- suffix = wtrimspace(line);
-
- /* should we keep this weird old behavior? */
- if (suffix[0] == '"') {
- *parameter = wtokennext(suffix, &next);
- wfree(suffix);
- } else {
- *parameter = suffix;
- }
-}
-
-static char *getLine(FILE * file, const char *file_name)
-{
- char linebuf[MAXLINE];
- char *line = NULL, *result = NULL;
- size_t len;
- int done;
-
-again:
- done = 0;
- while (!done && fgets(linebuf, sizeof(linebuf), file) != NULL) {
- line = wtrimspace(linebuf);
- len = strlen(line);
-
- /* allow line wrapping */
- if (len > 0 && line[len - 1] == '\\') {
- line[len - 1] = '\0';
- } else {
- done = 1;
- }
-
- if (result == NULL) {
- result = line;
- } else {
- if (strlen(result) < MAXLINE) {
- result = wstrappend(result, line);
- }
- wfree(line);
- }
- }
- if (!done || ferror(file)) {
- wfree(result);
- result = NULL;
- } else if (result != NULL && (result[0] == 0 || result[0] == '#' ||
- (result[0] == '/' && result[1] == '/'))) {
- wfree(result);
- result = NULL;
- goto again;
- } else if (result != NULL && strlen(result) >= MAXLINE) {
- wwarning(_("%s:maximal line size exceeded in menu config: %s"),
- file_name, line);
- wfree(result);
- result = NULL;
- goto again;
- }
-
- return result;
-}
-
-static WMenu *parseCascade(WScreen * scr, WMenu * menu, FILE * file, char *file_name)
-{
- char *line;
char *command, *params, *shortcut, *title;
- while ((line = getLine(file, file_name)) != NULL) {
- separateline(line, &title, &command, ¶ms, &shortcut);
+ while (menu_parser_get_line(parser, &title, &command, ¶ms, &shortcut)) {
if (command == NULL || !command[0]) {
- wwarning(_("%s:missing command in menu config: %s"), file_name, line);
+ menu_parser_warning(parser, _("missing command in menu config") );
freeline(title, command, params, shortcut);
- wfree(line);
goto error;
}
@@ -1007,7 +910,7 @@ static WMenu *parseCascade(WScreen * scr, WMenu * menu, FILE * file, char *file_
cascade = wMenuCreate(scr, M_(title), False);
cascade->on_destroy = removeShortcutsForMenu;
- if (!parseCascade(scr, cascade, file, file_name)) {
+ if (!menu_parse_cascade(scr, cascade, parser)) {
wMenuDestroy(cascade, True);
} else {
wMenuEntrySetCascade(menu, wMenuAddCallback(menu, M_(title), NULL, NULL), cascade);
@@ -1015,17 +918,15 @@ static WMenu *parseCascade(WScreen * scr, WMenu * menu, FILE * file, char *file_
} else if (strcasecmp(command, "END") == 0) {
/* end of menu */
freeline(title, command, params, shortcut);
- wfree(line);
return menu;
} else {
/* normal items */
- addMenuEntry(menu, M_(title), shortcut, command, params, file_name);
+ addMenuEntry(menu, M_(title), shortcut, command, params, menu_parser_get_filename(parser));
}
freeline(title, command, params, shortcut);
- wfree(line);
}
- wwarning(_("%s:syntax error in menu file:END declaration missing"), file_name);
+ menu_parser_warning(parser, _("syntax error in menu file:END declaration missing") );
error:
return NULL;
@@ -1035,7 +936,7 @@ static WMenu *readMenuFile(WScreen * scr, char *file_name)
{
WMenu *menu = NULL;
FILE *file = NULL;
- char *line;
+ WMenuParser parser;
char *command, *params, *shortcut, *title;
char cmd[MAXLINE];
#ifdef USECPP
@@ -1068,36 +969,33 @@ static WMenu *readMenuFile(WScreen * scr, char *file_name)
return NULL;
}
}
+ parser = menu_parser_create(file_name, file);
- while ((line = getLine(file, file_name)) != NULL) {
- separateline(line, &title, &command, ¶ms, &shortcut);
+ while (menu_parser_get_line(parser, &title, &command, ¶ms, &shortcut)) {
if (command == NULL || !command[0]) {
- wwarning(_("%s:missing command in menu config: %s"), file_name, line);
+ menu_parser_warning(parser, _("missing command in menu config") );
freeline(title, command, params, shortcut);
- wfree(line);
break;
}
if (strcasecmp(command, "MENU") == 0) {
menu = wMenuCreate(scr, M_(title), True);
menu->on_destroy = removeShortcutsForMenu;
- if (!parseCascade(scr, menu, file, file_name)) {
+ if (!menu_parse_cascade(scr, menu, parser)) {
wMenuDestroy(menu, True);
menu = NULL;
}
freeline(title, command, params, shortcut);
- wfree(line);
break;
} else {
- wwarning(_("%s:invalid menu file. MENU command is missing"), file_name);
+ menu_parser_warning(parser, _("invalid menu file. MENU command is missing") );
freeline(title, command, params, shortcut);
- wfree(line);
break;
}
freeline(title, command, params, shortcut);
- wfree(line);
}
+ menu_parser_delete(parser);
#ifdef USECPP
if (cpp) {
if (pclose(file) == -1) {
@@ -1119,8 +1017,8 @@ static WMenu *readMenuPipe(WScreen * scr, char **file_name)
{
WMenu *menu = NULL;
FILE *file = NULL;
+ WMenuParser parser;
char *command, *params, *shortcut, *title;
- char *line;
char *filename;
char flat_file[MAXLINE];
char cmd[MAXLINE];
@@ -1156,43 +1054,39 @@ static WMenu *readMenuPipe(WScreen * scr, char **file_name)
if (!file) {
file = popen(filename, "rb");
-
if (!file) {
werror(_("%s:could not open menu file"), filename);
return NULL;
}
}
+ parser = menu_parser_create(flat_file, file);
- while ((line = getLine(file, filename)) != NULL) {
- separateline(line, &title, &command, ¶ms, &shortcut);
+ while (menu_parser_get_line(parser, &title, &command, ¶ms, &shortcut)) {
if (command == NULL || !command[0]) {
- wwarning(_("%s:missing command in menu config: %s"), filename, line);
+ menu_parser_warning(parser, _("missing command in menu config") );
freeline(title, command, params, shortcut);
- wfree(line);
break;
}
if (strcasecmp(command, "MENU") == 0) {
menu = wMenuCreate(scr, M_(title), True);
menu->on_destroy = removeShortcutsForMenu;
- if (!parseCascade(scr, menu, file, filename)) {
+ if (!menu_parse_cascade(scr, menu, parser)) {
wMenuDestroy(menu, True);
menu = NULL;
}
freeline(title, command, params, shortcut);
- wfree(line);
break;
} else {
- wwarning(_("%s:no title given for the root menu"), filename);
+ menu_parser_warning(parser, _("no title given for the root menu") );
freeline(title, command, params, shortcut);
- wfree(line);
break;
}
freeline(title, command, params, shortcut);
- wfree(line);
}
+ menu_parser_delete(parser);
pclose(file);
return menu;
diff --git a/src/rootmenu.h b/src/rootmenu.h
index e7ed855..0b4a5b3 100644
--- a/src/rootmenu.h
+++ b/src/rootmenu.h
@@ -41,4 +41,30 @@ typedef struct _WRootMenuReader {
void (*closeMenuFile)(WRootMenuData *data);
} WRootMenuReader;
+/****** Parsing of menu files ******/
+typedef struct menu_parser *WMenuParser;
+
+WMenuParser menu_parser_create(const char *file_name, FILE *file);
+Bool menu_parser_get_line(WMenuParser parser, char **title, char **command, char **parameter, char **shortcut);
+const char * menu_parser_get_filename(WMenuParser parser);
+void menu_parser_delete(WMenuParser parser);
+
+#define menu_parser_warning(parser, fmt, args...) \
+ __menu_parser_warning( parser, __func__, __FILE__, __LINE__, fmt, ## args)
+
+void __menu_parser_warning(WMenuParser parser, const char *src_func, const char *src_file, int src_line, const char *msg, ...)
+ __attribute__((__format__(printf,5,6)));
+
+#ifdef MENU_PARSER_INTERNALS
+
+struct menu_parser {
+ const char *file_name;
+ FILE *file_handle;
+ int num_line;
+ char *rd;
+ char line_buffer[MAXLINE];
+};
+
+#endif /* MENU_PARSER_INTERNALS */
+
#endif /* WMROOTMENU_H */
diff --git a/src/rootmenuparser.c b/src/rootmenuparser.c
new file mode 100644
index 0000000..32ff514
--- /dev/null
+++ b/src/rootmenuparser.c
@@ -0,0 +1,173 @@
+/*
+ * Window Maker window manager
+ *
+ * Copyright (c) 1997-2003 Alfredo K. Kojima
+ *
+ * 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 2 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#include "wconfig.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+
+#define MENU_PARSER_INTERNALS
+#include "WindowMaker.h"
+#include "rootmenu.h"
+
+
+/***** Root parser functions *****/
+WMenuParser menu_parser_create(const char *file_name, FILE *file)
+{
+ WMenuParser parser;
+
+ parser = wmalloc(sizeof(*parser));
+ parser->file_name = file_name;
+ parser->file_handle = file;
+ parser->rd = parser->line_buffer;
+
+ return parser;
+}
+
+void menu_parser_delete(WMenuParser parser)
+{
+ wfree(parser);
+}
+
+/***** Reporting problems to user *****/
+const char * menu_parser_get_filename(WMenuParser parser)
+{
+ return parser->file_name;
+}
+
+void __menu_parser_warning(WMenuParser parser, const char *src_func, const char *src_file, int src_line, const char *msg, ...)
+{
+ char buf[256];
+ int pos;
+ va_list args;
+
+ va_start(args, msg);
+ snprintf(buf, sizeof(buf), "%s:%d: ", parser->file_name, parser->num_line);
+ for (pos=0; buf[pos] != '\0'; pos++) ;
+ vsnprintf(buf+pos, sizeof(buf)-pos, msg, args);
+ va_end(args);
+ __wmessage(src_func, src_file, src_line, WMESSAGE_TYPE_WARNING, buf);
+}
+
+/***** Reading from the file *****/
+static void separateline(char *line, char **title, char **command, char **parameter, char **shortcut);
+
+/***** Main parsing from the file *****/
+Bool menu_parser_get_line(WMenuParser top_parser, char **title, char **command, char **parameter, char **shortcut)
+{
+ WMenuParser cur_parser;
+ char *line = NULL, *result = NULL;
+ size_t len;
+ int done;
+
+ *title = NULL;
+ *command = NULL;
+ *parameter = NULL;
+ *shortcut = NULL;
+
+ cur_parser = top_parser;
+
+again:
+ done = 0;
+ while (!done && fgets(cur_parser->line_buffer, sizeof(cur_parser->line_buffer), cur_parser->file_handle) != NULL) {
+ line = wtrimspace(cur_parser->line_buffer);
+ len = strlen(line);
+ cur_parser->num_line++;
+
+ /* allow line wrapping */
+ if (len > 0 && line[len - 1] == '\\') {
+ line[len - 1] = '\0';
+ } else {
+ done = 1;
+ }
+
+ if (result == NULL) {
+ result = line;
+ } else {
+ if (strlen(result) < MAXLINE) {
+ result = wstrappend(result, line);
+ }
+ wfree(line);
+ }
+ }
+ if (!done || ferror(cur_parser->file_handle)) {
+ wfree(result);
+ result = NULL;
+ } else if (result != NULL && (result[0] == 0 || result[0] == '#' ||
+ (result[0] == '/' && result[1] == '/'))) {
+ wfree(result);
+ result = NULL;
+ goto again;
+ } else if (result != NULL && strlen(result) >= MAXLINE) {
+ menu_parser_warning(cur_parser, _("maximal line size exceeded in menu config") );
+ wfree(result);
+ result = NULL;
+ goto again;
+ }
+
+ if (result == NULL)
+ return False;
+
+ separateline(line, title, command, parameter, shortcut);
+ wfree(line);
+ return True;
+}
+
+static void separateline(char *line, char **title, char **command, char **parameter, char **shortcut)
+{
+ char *suffix, *next = line;
+
+ /* get the title */
+ *title = wtokennext(line, &next);
+ if (next == NULL)
+ return;
+ line = next;
+
+ /* get the command or shortcut keyword */
+ *command = wtokennext(line, &next);
+ if (next == NULL)
+ return;
+ line = next;
+
+ if (*command != NULL && strcmp(*command, "SHORTCUT") == 0) {
+ /* get the shortcut */
+ *shortcut = wtokennext(line, &next);
+ if (next == NULL)
+ return;
+ line = next;
+
+ /* get the command */
+ *command = wtokennext(line, &next);
+ if (next == NULL)
+ return;
+ line = next;
+ }
+
+ /* get the parameters */
+ suffix = wtrimspace(line);
+
+ /* should we keep this weird old behavior? */
+ if (suffix[0] == '"') {
+ *parameter = wtokennext(suffix, &next);
+ wfree(suffix);
+ } else {
+ *parameter = suffix;
+ }
+}
--
1.7.10