summaryrefslogtreecommitdiff
path: root/server/src/macroparser.cc
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/macroparser.cc')
-rw-r--r--server/src/macroparser.cc327
1 files changed, 327 insertions, 0 deletions
diff --git a/server/src/macroparser.cc b/server/src/macroparser.cc
new file mode 100644
index 0000000..6f4798e
--- /dev/null
+++ b/server/src/macroparser.cc
@@ -0,0 +1,327 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * macroparser.cc
+ *
+ * Wed Jun 4 11:57:38 CEST 2008
+ * Copyright 2008 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of Pracro.
+ *
+ * Pracro 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.
+ *
+ * Pracro 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 Pracro; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include "macroparser.h"
+
+// For assert
+#include <assert.h>
+
+// For open and friends
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+// For vprintf and friends
+#include <stdarg.h>
+
+#ifndef XML
+// For XML
+#include <config.h>
+#endif/*XML*/
+
+#include <errno.h>
+
+#include "exception.h"
+
+void MacroParser::error(const char* fmt, ...)
+{
+ // TODO: Throw exception here.
+
+ fprintf(stderr, "Error in MacroParser: ");
+
+ va_list argp;
+ va_start(argp, fmt);
+ vfprintf(stderr, fmt, argp);
+ va_end(argp);
+
+ fprintf(stderr, "\n");
+
+ throw Exception("Error in MacroParser");
+}
+
+MacroParser::MacroParser(std::string macro)
+{
+ state = UNDEFINED;
+ m = NULL;
+ current_map = NULL;
+ current_luaprogram = NULL;
+
+ file = XML"/macros/" + macro + ".xml";
+
+ printf("Using macro file: %s\n", file.c_str());
+
+ fd = open(file.c_str(), O_RDONLY);
+ if(fd == -1) error("Could not open file %s", file.c_str());
+}
+
+MacroParser::~MacroParser()
+{
+ if(fd != -1) close(fd);
+ if(m) delete m;
+}
+
+void MacroParser::characterData(std::string &data)
+{
+ if(state == MAP) {
+ assert(current_map); // No map present!
+ current_map->attributes["lua"].append(data);
+ }
+
+ if(state == LUAPROGRAM) {
+ assert(current_luaprogram); // No lua program present!
+ current_luaprogram->attributes["lua"].append(data);
+ }
+}
+
+void MacroParser::startTag(std::string name, std::map< std::string, std::string> attributes)
+{
+ // Create macro and enable parsing of queries, maps and window
+ if(name == "macro") {
+ if(state != UNDEFINED) error("macro found not root tag.");
+ state = MACRO;
+
+ assert(!m); // A Macro has already been allocated, cannot create macro!
+
+ m = new Macro();
+ m->attributes = attributes;
+
+ return;
+ }
+
+ // Enable Query parsing
+ if(name == "queries") {
+ if(state != MACRO) error("queries found outside macro.");
+ state = QUERIES;
+
+ assert(m); // No macro is currently available, cannot create queries!
+
+ return;
+ }
+
+ // Create Query
+ if(name == "query") {
+ if(state != QUERIES) error("query found outside queries.");
+ state = QUERY;
+
+ assert(m); // No macro is currently available, cannot create query!
+
+ Query q;
+ q.attributes = attributes;
+ m->queries.push_back(q);
+
+ return;
+ }
+
+ // Enable Map parsing
+ if(name == "maps") {
+ if(state != MACRO) error("maps found outside macro.");
+ state = MAPS;
+
+ assert(m); // No macro is currently available, cannot create maps!
+
+ return;
+ }
+
+ // Create Query
+ if(name == "map") {
+ if(state != MAPS) error("map found outside maps.");
+ state = MAP;
+
+ assert(m); // No macro is currently available, cannot create map!
+
+ Map map;
+ map.attributes = attributes;
+ m->maps.push_back(map);
+ current_map = &(m->maps.back());
+
+ return;
+ }
+
+ // Enable LUA Program parsing
+ if(name == "luaprograms") {
+ if(state != MACRO) error("luaprograms found outside macro.");
+ state = LUAPROGRAMS;
+
+ assert(m); // No macro is currently available, cannot create maps!
+
+ return;
+ }
+
+ // Create Query
+ if(name == "luaprogram") {
+ if(state != LUAPROGRAMS) error("lua program found outside maps.");
+ state = LUAPROGRAM;
+
+ assert(m); // No macro is currently available, cannot create map!
+
+ LUAProgram l;
+ l.attributes = attributes;
+ m->luaprograms.push_back(l);
+ current_luaprogram = &(m->luaprograms.back());
+
+ return;
+ }
+
+ // Enable widget parsing
+ if(name == "window") {
+
+ if(state != MACRO) error("window found outside macro.");
+ state = WINDOW;
+
+ assert(m); // No macro is currently available, cannot create window!
+
+ m->window.attributes = attributes;
+ m->window.attributes["type"] = name;
+
+ Widget *current = &(m->window);
+ widgetstack.push_back(current);
+
+ return;
+ }
+
+ // TODO: We need to parse some (maybe even all) widgets in order to
+ // make db lookup of the previous values.
+ if(state == WINDOW) {
+
+ assert(widgetstack.size()); // Widget stack is empty, cannot create!
+
+ Widget w;
+ w.attributes = attributes;
+ w.attributes["type"] = name;
+
+ Widget *parent = widgetstack.back();
+ parent->widgets.push_back(w);
+
+ Widget *current = &(parent->widgets.back());
+ widgetstack.push_back(current);
+
+ return;
+ }
+
+
+ // Handle include
+ if(name == "include") {
+ return;
+ }
+
+ error("Unknown/illegal tag: %s", name.c_str());
+}
+
+void MacroParser::endTag(std::string name)
+{
+ if(name == "macro") {
+ state = UNDEFINED;
+ }
+ if(name == "queries") state = MACRO;
+ if(name == "query") state = QUERIES;
+ if(name == "maps") state = MACRO;
+ if(name == "map") {
+ current_map = NULL;
+ state = MAPS;
+ }
+ if(name == "luaprograms") state = MACRO;
+ if(name == "luaprogram") {
+ current_luaprogram = NULL;
+ state = LUAPROGRAMS;
+ }
+ if(name == "window") state = MACRO;
+
+ if(state == WINDOW) {
+ assert(widgetstack.size()); // Widget stack is empty, cannot pop!
+ widgetstack.pop_back();
+ if(widgetstack.size() == 0) state = MACRO;
+ }
+}
+
+int MacroParser::readData(char *data, size_t size)
+{
+ if(fd == -1) {
+ fprintf(stderr, "Invalid file descriptor.\n"); fflush(stderr);
+ return 0;
+ }
+ ssize_t r = read(fd, data, size);
+ if(r == -1) {
+ printf("Could not read...%s\n", strerror(errno)); fflush(stdout);
+ return 0;
+ }
+ return r;
+}
+
+void MacroParser::parseError(char *buf, size_t len, std::string error, int lineno)
+{
+ fprintf(stderr, "MacroParser[%s] error at line %d: %s\n", file.c_str(), lineno, error.c_str());
+ fprintf(stderr, "\tBuffer %u bytes: [", len);
+ if(fwrite(buf, len, 1, stderr) != len) {}
+ fprintf(stderr, "]\n");
+ fflush(stderr);
+}
+
+Macro *MacroParser::getMacro()
+{
+ return m;
+}
+
+#ifdef TEST_MACROPARSER
+
+void print_attributes(std::string prefix,
+ std::map< std::string, std::string > &att)
+{
+ std::map< std::string, std::string >::iterator i = att.begin();
+ while(i != att.end()) {
+ printf("%s %s = \"%s\"\n", prefix.c_str(), (*i).first.c_str(), (*i).second.c_str());
+ i++;
+ }
+}
+
+int main()
+{
+ MacroParser parser("example");
+ parser.parse();
+
+ Macro *m = parser.getMacro();
+
+ printf("\t\t\t[Macro]:\n");
+ print_attributes("\t\t\t\t-", m->attributes);
+
+ std::vector< Query >::iterator qi = m->queries.begin();
+ while(qi != m->queries.end()) {
+ printf("\t\t\t\t[Query]:\n");
+ print_attributes("\t\t\t\t\t-", (*qi).attributes);
+ qi++;
+ }
+
+ std::vector< Map >::iterator mi = m->maps.begin();
+ while(mi != m->maps.end()) {
+ printf("\t\t\t\t[Map]:\n");
+ print_attributes("\t\t\t\t\t-", (*mi).attributes);
+ mi++;
+ }
+
+ return 0;
+}
+
+#endif/*TEST_MACROPARSER*/