From dad77becc53e2f2c3b0880ee4fddd97d69099f94 Mon Sep 17 00:00:00 2001 From: deva Date: Wed, 4 Jun 2008 11:41:46 +0000 Subject: Modulized the template/course/macro system. --- server/src/macroparser.cc | 327 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 327 insertions(+) create mode 100644 server/src/macroparser.cc (limited to 'server/src/macroparser.cc') 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 + +// For open and friends +#include +#include +#include +#include + +// For vprintf and friends +#include + +#ifndef XML +// For XML +#include +#endif/*XML*/ + +#include + +#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*/ -- cgit v1.2.3