qbsp: make parser state non-global

Signed-off-by: Kevin Shanahan <kmshanah@disenchant.net>
This commit is contained in:
Kevin Shanahan 2013-02-17 11:49:00 +10:30
parent bbe203629a
commit d1839943c9
3 changed files with 104 additions and 105 deletions

View File

@ -100,7 +100,7 @@ FindTexinfo(texinfo_t *t)
static void
ParseEpair(mapentity_t *ent)
ParseEpair(parser_t *parser, mapentity_t *ent)
{
epair_t *epair;
@ -108,13 +108,13 @@ ParseEpair(mapentity_t *ent)
epair->next = ent->epairs;
ent->epairs = epair;
if (strlen(token) >= MAX_KEY - 1)
Error(errEpairTooLong, linenum);
epair->key = copystring(token);
ParseToken(PARSE_SAMELINE);
if (strlen(token) >= MAX_VALUE - 1)
Error(errEpairTooLong, linenum);
epair->value = copystring(token);
if (strlen(parser->token) >= MAX_KEY - 1)
Error(errEpairTooLong, parser->linenum);
epair->key = copystring(parser->token);
ParseToken(parser, PARSE_SAMELINE);
if (strlen(parser->token) >= MAX_VALUE - 1)
Error(errEpairTooLong, parser->linenum);
epair->value = copystring(parser->token);
if (!strcasecmp(epair->key, "origin")) {
GetVectorForKey(ent, epair->key, ent->origin);
@ -171,15 +171,15 @@ typedef enum {
} texcoord_style_t;
static texcoord_style_t
ParseExtendedTX(void)
ParseExtendedTX(parser_t *parser)
{
texcoord_style_t style = TX_ORIGINAL;
if (ParseToken(PARSE_COMMENT)) {
if (!strncmp(token, "//TX", 4)) {
if (token[4] == '1')
if (ParseToken(parser, PARSE_COMMENT)) {
if (!strncmp(parser->token, "//TX", 4)) {
if (parser->token[4] == '1')
style = TX_QUARK_TYPE1;
else if (token[4] == '2')
else if (parser->token[4] == '2')
style = TX_QUARK_TYPE2;
}
}
@ -259,7 +259,8 @@ SetTexinfo_QuakeEd(const plane_t *plane, const int shift[2], int rotate,
}
static void
SetTexinfo_QuArK(vec3_t planepts[3], texcoord_style_t style, texinfo_t *out)
SetTexinfo_QuArK(parser_t *parser, vec3_t planepts[3], texcoord_style_t style,
texinfo_t *out)
{
int i;
vec3_t vecs[2];
@ -302,7 +303,7 @@ SetTexinfo_QuArK(vec3_t planepts[3], texcoord_style_t style, texinfo_t *out)
*/
determinant = a * d - b * c;
if (fabs(determinant) < ZERO_EPSILON) {
Message(msgWarning, warnDegenerateQuArKTX, linenum);
Message(msgWarning, warnDegenerateQuArKTX, parser->linenum);
for (i = 0; i < 3; i++)
out->vecs[0][i] = out->vecs[1][i] = 0;
} else {
@ -323,7 +324,7 @@ SetTexinfo_QuArK(vec3_t planepts[3], texcoord_style_t style, texinfo_t *out)
static void
ParseBrush(mapbrush_t *brush)
ParseBrush(parser_t *parser, mapbrush_t *brush)
{
vec3_t planepts[3];
vec3_t t1, t2, t3;
@ -337,41 +338,41 @@ ParseBrush(mapbrush_t *brush)
mapface_t *face, *checkface;
brush->faces = face = map.faces + map.numfaces;
while (ParseToken(PARSE_NORMAL)) {
if (!strcmp(token, "}"))
while (ParseToken(parser, PARSE_NORMAL)) {
if (!strcmp(parser->token, "}"))
break;
// read the three point plane definition
for (i = 0; i < 3; i++) {
if (i != 0)
ParseToken(PARSE_NORMAL);
if (strcmp(token, "("))
Error(errInvalidMapPlane, linenum);
ParseToken(parser, PARSE_NORMAL);
if (strcmp(parser->token, "("))
Error(errInvalidMapPlane, parser->linenum);
for (j = 0; j < 3; j++) {
ParseToken(PARSE_SAMELINE);
planepts[i][j] = atof(token);
ParseToken(parser, PARSE_SAMELINE);
planepts[i][j] = atof(parser->token);
}
ParseToken(PARSE_SAMELINE);
if (strcmp(token, ")"))
Error(errInvalidMapPlane, linenum);
ParseToken(parser, PARSE_SAMELINE);
if (strcmp(parser->token, ")"))
Error(errInvalidMapPlane, parser->linenum);
}
// read the texturedef
memset(&tx, 0, sizeof(tx));
ParseToken(PARSE_SAMELINE);
tx.miptex = FindMiptex(token);
ParseToken(PARSE_SAMELINE);
shift[0] = atoi(token);
ParseToken(PARSE_SAMELINE);
shift[1] = atoi(token);
ParseToken(PARSE_SAMELINE);
rotate = atoi(token);
ParseToken(PARSE_SAMELINE);
scale[0] = atof(token);
ParseToken(PARSE_SAMELINE);
scale[1] = atof(token);
ParseToken(parser, PARSE_SAMELINE);
tx.miptex = FindMiptex(parser->token);
ParseToken(parser, PARSE_SAMELINE);
shift[0] = atoi(parser->token);
ParseToken(parser, PARSE_SAMELINE);
shift[1] = atoi(parser->token);
ParseToken(parser, PARSE_SAMELINE);
rotate = atoi(parser->token);
ParseToken(parser, PARSE_SAMELINE);
scale[0] = atof(parser->token);
ParseToken(parser, PARSE_SAMELINE);
scale[1] = atof(parser->token);
// if the three points are all on a previous plane, it is a
// duplicate plane
@ -386,7 +387,7 @@ ParseBrush(mapbrush_t *brush)
break;
}
if (checkface < face) {
Message(msgWarning, warnBrushDuplicatePlane, linenum);
Message(msgWarning, warnBrushDuplicatePlane, parser->linenum);
continue;
}
@ -403,17 +404,17 @@ ParseBrush(mapbrush_t *brush)
plane = &face->plane;
CrossProduct(t1, t2, plane->normal);
if (VectorCompare(plane->normal, vec3_origin)) {
Message(msgWarning, warnNoPlaneNormal, linenum);
Message(msgWarning, warnNoPlaneNormal, parser->linenum);
continue;
}
VectorNormalize(plane->normal);
plane->dist = DotProduct(t3, plane->normal);
tx_type = ParseExtendedTX();
tx_type = ParseExtendedTX(parser);
switch (tx_type) {
case TX_QUARK_TYPE1:
case TX_QUARK_TYPE2:
SetTexinfo_QuArK(&planepts[0], tx_type, &tx);
SetTexinfo_QuArK(parser, &planepts[0], tx_type, &tx);
break;
default:
SetTexinfo_QuakeEd(plane, shift, rotate, scale, &tx);
@ -432,32 +433,32 @@ ParseBrush(mapbrush_t *brush)
}
static bool
ParseEntity(mapentity_t *ent)
ParseEntity(parser_t *parser, mapentity_t *ent)
{
mapbrush_t *brush;
if (!ParseToken(PARSE_NORMAL))
if (!ParseToken(parser, PARSE_NORMAL))
return false;
if (strcmp(token, "{"))
Error(errParseEntity, linenum);
if (strcmp(parser->token, "{"))
Error(errParseEntity, parser->linenum);
if (map.numentities == map.maxentities)
Error(errLowEntCount);
ent->mapbrushes = brush = map.brushes + map.numbrushes;
do {
if (!ParseToken(PARSE_NORMAL))
if (!ParseToken(parser, PARSE_NORMAL))
Error(errUnexpectedEOF);
if (!strcmp(token, "}"))
if (!strcmp(parser->token, "}"))
break;
else if (!strcmp(token, "{")) {
else if (!strcmp(parser->token, "{")) {
if (map.numbrushes == map.maxbrushes)
Error(errLowMapbrushCount);
ParseBrush(brush++);
ParseBrush(parser, brush++);
map.numbrushes++;
} else
ParseEpair(ent);
ParseEpair(parser, ent);
} while (1);
ent->nummapbrushes = brush - ent->mapbrushes;
@ -469,7 +470,7 @@ ParseEntity(mapentity_t *ent)
static void
PreParseFile(char *buf)
PreParseFile(const char *buf)
{
int braces = 0;
struct lumpdata *texinfo;
@ -528,6 +529,7 @@ PreParseFile(char *buf)
void
LoadMapFile(void)
{
parser_t parser;
char *buf;
int i, j, length, cAxis;
void *pTemp;
@ -540,11 +542,11 @@ LoadMapFile(void)
length = LoadFile(options.szMapName, &buf, true);
PreParseFile(buf);
ParserInit(buf);
ParserInit(&parser, buf);
map.numfaces = map.numbrushes = map.numentities = 0;
ent = map.entities;
while (ParseEntity(ent)) {
while (ParseEntity(&parser, ent)) {
if (ent->nummapbrushes) {
ent->lumps[BSPMODEL].data = AllocMem(BSPMODEL, 1, true);
ent->lumps[BSPMODEL].count = 1;

View File

@ -22,65 +22,58 @@
#include "qbsp.h"
#include "parser.h"
int linenum;
char token[MAXTOKEN];
static bool unget;
static char *script;
void
ParserInit(char *data)
ParserInit(parser_t *p, const char *data)
{
linenum = 1;
script = data;
unget = false;
p->linenum = 1;
p->pos = data;
p->unget = false;
}
bool
ParseToken(int flags)
ParseToken(parser_t *p, parseflags_t flags)
{
char *token_p;
/* is a token already waiting? */
if (unget) {
unget = false;
if (p->unget) {
p->unget = false;
return true;
}
skipspace:
/* skip space */
while (*script <= 32) {
if (!*script) {
while (*p->pos <= 32) {
if (!*p->pos) {
if (flags & PARSE_SAMELINE)
Error(errLineIncomplete, linenum);
Error(errLineIncomplete, p->linenum);
return false;
}
if (*script++ == '\n') {
if (*p->pos++ == '\n') {
if (flags & PARSE_SAMELINE)
Error(errLineIncomplete, linenum);
linenum++;
Error(errLineIncomplete, p->linenum);
p->linenum++;
}
}
/* comment field */
if (script[0] == '/' && script[1] == '/') {
if (p->pos[0] == '/' && p->pos[1] == '/') {
if (flags & PARSE_COMMENT) {
token_p = token;
while (*script && *script != '\n') {
*token_p++ = *script++;
if (token_p > &token[MAXTOKEN - 1])
Error(errTokenTooLarge, linenum);
token_p = p->token;
while (*p->pos && *p->pos != '\n') {
*token_p++ = *p->pos++;
if (token_p > &p->token[MAXTOKEN - 1])
Error(errTokenTooLarge, p->linenum);
}
goto out;
}
if (flags & PARSE_SAMELINE)
Error(errLineIncomplete, linenum);
while (*script++ != '\n')
if (!*script) {
Error(errLineIncomplete, p->linenum);
while (*p->pos++ != '\n')
if (!*p->pos) {
if (flags & PARSE_SAMELINE)
Error(errLineIncomplete, linenum);
Error(errLineIncomplete, p->linenum);
return false;
}
goto skipspace;
@ -89,23 +82,23 @@ ParseToken(int flags)
return false;
/* copy token */
token_p = token;
token_p = p->token;
if (*script == '"') {
script++;
while (*script != '"') {
if (!*script)
Error(errEOFInQuotes, linenum);
*token_p++ = *script++;
if (token_p > &token[MAXTOKEN - 1])
Error(errTokenTooLarge, linenum);
if (*p->pos == '"') {
p->pos++;
while (*p->pos != '"') {
if (!*p->pos)
Error(errEOFInQuotes, p->linenum);
*token_p++ = *p->pos++;
if (token_p > &p->token[MAXTOKEN - 1])
Error(errTokenTooLarge, p->linenum);
}
script++;
p->pos++;
} else
while (*script > 32) {
*token_p++ = *script++;
if (token_p > &token[MAXTOKEN - 1])
Error(errTokenTooLarge, linenum);
while (*p->pos > 32) {
*token_p++ = *p->pos++;
if (token_p > &p->token[MAXTOKEN - 1])
Error(errTokenTooLarge, p->linenum);
}
out:
*token_p = 0;

View File

@ -26,16 +26,20 @@
#define MAXTOKEN 256
extern int linenum;
extern char token[MAXTOKEN];
enum parseflags {
typedef enum parseflags {
PARSE_NORMAL = 0,
PARSE_SAMELINE = 1, /* The next token must be on the current line */
PARSE_COMMENT = 2 /* Return a // comment as the next token */
};
} parseflags_t;
bool ParseToken(int flags);
void ParserInit(char *data);
typedef struct parser {
bool unget;
const char *pos;
int linenum;
char token[MAXTOKEN];
} parser_t;
bool ParseToken(parser_t *p, parseflags_t flags);
void ParserInit(parser_t *p, const char *data);
#endif /* PARSER_H */