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 <unistd.h>
#include <sys/mman.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#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, &amt;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, "<s>", 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, "</s>", 3, 1); /* keeps the parser happy */
XML_ParserFree(parser);
return es;
}