www.pudn.com > xvoice-0.8.1.rar > ParseEventStream.cc
/** * ParseEventStream.cc * * Description: parse an event stream XML, and create an EventStream object * * Copyright (c) 1999, David Z. Creemer. * See the LICENSE file. All rights not granted therein are reserved. * * @author David Z. Creemer * @author Tom Doris * @version 1.0 * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include#include #include #include #include #include #include #include "expat/xmlparse.h" #include "EventStream.h" #include "ParseEventStream.h" #include "Error.h" #include "Voice.h" enum appType { APPAPP, APPDEF, APPVOC }; struct configCtx { application* app; appType type; applicationList* applist; bool inCdata; const char *gDir; int gFd; }; typedef struct configCtx configCtx; /* userData is the EventStream object created in ParseFile */ static void startElement( void *userData, const char *name, const char **attrs ) { configCtx *ctx = (configCtx *)userData; const char *aname = NULL, *expr = NULL; if (strcasecmp(name, "xvoice") == 0) return; dbgprintf(("name %s\n", name)); while (*attrs != NULL) { dbgprintf(("attribute %s\n", *attrs)); if (strcasecmp(*attrs, "name") == 0) aname = *++attrs; else if (strcasecmp(*attrs, "expr") == 0) expr = *++attrs; else attrs++; attrs++; } if (aname == NULL) LogMessage(E_FATAL, "No application name given!"); if (strcasecmp(name, "application") == 0) { if (expr == NULL) expr = aname; ctx->app = new application(aname,expr); ctx->type = APPAPP; } else if (strcasecmp(name, "vocab") == 0) { ctx->app = new application(aname,""); ctx->type = APPVOC; } else if (strcasecmp(name, "define") == 0) { ctx->app = new application(aname,""); ctx->type = APPDEF; } } static void endElement(void *userData, const char *name) { configCtx *ctx = (configCtx *)userData; if(strcasecmp(name, "application") == 0 ) { ctx->applist->push_back(*ctx->app); } else if (strcasecmp(name, "vocab") == 0 ) { delete ctx->app; } else if (strcasecmp(name, "define") == 0 ) { delete ctx->app; } } static void endCdataSection(void *userData) { configCtx *ctx = (configCtx *)userData; char *name = ctx->app->name; close(ctx->gFd); dbgprintf(("wrote bnf\n")); if (ctx->type != APPDEF) { compileGrammar(name); } ctx->inCdata = false; } static void startCdataSection(void *userData) { configCtx *ctx = (configCtx *)userData; close(ctx->gFd); fstring buff; buff.appendf("%s/%s.bnf", ctx->gDir, ctx->app->name); dbgprintf(("opening bnf %s\n",buff.c_str())); ctx->gFd = open( buff.c_str(), O_WRONLY | O_TRUNC | O_CREAT, 0644); if ( ctx->gFd == -1 ) { LogMessage(E_FATAL, "Could not open bnf file %s", buff.c_str()); } ctx->inCdata = true; } static void handleCharData(void *userData, const XML_Char *s, int len) { configCtx *ctx = (configCtx *)userData; if (ctx->inCdata == true) { dbgprintf(("writing %d chars\n",len)); if (write(ctx->gFd, s, len) < 0) LogMessage(E_FATAL, "Error writing to bnf"); } } applicationList* parseFile( const char* filename, const char* gdir) { applicationList* es = new applicationList(); configCtx ctx; ctx.gDir = gdir; ctx.gFd = -1; ctx.applist = es; ctx.inCdata = false; int fd = open(filename, O_RDONLY); if (fd == -1) { delete es; return NULL; } off_t fsize = lseek(fd, 0, SEEK_END); char* bytes = (char*) mmap(NULL, fsize, PROT_READ, MAP_SHARED, fd, 0); if (bytes != MAP_FAILED) { int done; XML_Parser parser = XML_ParserCreate(NULL); //es becomes the "userData" arg to the handlers: XML_SetUserData(parser, &ctx); XML_SetElementHandler(parser, startElement, endElement); XML_SetCharacterDataHandler(parser, handleCharData); XML_SetCdataSectionHandler(parser, startCdataSection, endCdataSection); do { if (!XML_Parse(parser, bytes, fsize, done)) { LogMessage(E_CONFIG, "%s at line %d\n", XML_ErrorString(XML_GetErrorCode(parser)), XML_GetCurrentLineNumber(parser)); delete es; return NULL; } } while (!done); XML_ParserFree(parser); munmap(bytes, fsize); } else { LogMessage(E_FATAL, "MMAP error"); delete es; return NULL; } close(fd); return es; } static void startElementB(void *userData, const char *name, const char **attrs) { dbgprintf(("name %s attr %s\n", name, attrs[0])); EventStream *es = (EventStream*) userData; if (strcasecmp(name, "key") == 0) { es->parseKeyEvent(attrs); } else if (strcasecmp(name, "mouse") == 0) { es->parseMouseEvent(attrs); } else if (strcasecmp(name, "grammar") == 0) { es->parseGrammarEvent(attrs); } } static void endElementB(void *userData, const char *name) { dbgprintf(("name %s\n", name)); } EventStream* parseBuff(const char* bytes) { EventStream* es = new EventStream(); off_t fsize = strlen(bytes); XML_Parser parser = XML_ParserCreate(NULL); //es becomes the "userData" arg to the handlers: XML_SetUserData(parser, es); XML_SetElementHandler(parser, startElementB, endElementB); XML_Parse( parser, " ", 3, 0); /* keeps the parser happy */ if (!XML_Parse(parser, bytes, fsize, 0)) { LogMessage(E_CONFIG, "%s at line %d\n", XML_ErrorString(XML_GetErrorCode(parser)), XML_GetCurrentLineNumber(parser)); delete es; return NULL; } XML_Parse(parser, "", 3, 1); /* keeps the parser happy */ XML_ParserFree(parser); return es; }