gtkradiant/tools/quake2/qdata_heretic2/common/token.c
TTimo ab3a99dbbe eol style
git-svn-id: svn://svn.icculus.org/gtkradiant/GtkRadiant/branches/ZeroRadiant.ab@184 8a3a26a2-13c4-0310-b231-cf6edde360e5
2007-11-04 03:47:06 +00:00

550 lines
11 KiB
C

/*
Copyright (C) 1999-2007 id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant 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.
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
//**************************************************************************
//**
//** token.c
//**
//**************************************************************************
// HEADER FILES ------------------------------------------------------------
#include "token.h"
#include "inout.h"
// MACROS ------------------------------------------------------------------
// TYPES -------------------------------------------------------------------
typedef enum
{
CHR_EOF,
CHR_LETTER,
CHR_NUMBER,
CHR_QUOTE,
CHR_SPECIAL
} chr_t;
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
static void ProcessLetterToken(void);
static void ProcessNumberToken(void);
static void ProcessQuoteToken(void);
static void ProcessSpecialToken(void);
static qboolean CheckForKeyword(void);
static void NextChr(void);
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
// PUBLIC DATA DEFINITIONS -------------------------------------------------
tokenType_t tk_Token;
int tk_Line;
int tk_IntNumber;
float tk_FloatNumber;
char *tk_String;
char tk_SourceName[MAX_FILE_NAME_LENGTH];
// PRIVATE DATA DEFINITIONS ------------------------------------------------
static char Chr;
static char *FileStart;
static char *FilePtr;
static char *FileEnd;
static qboolean SourceOpen;
static char ASCIIToChrCode[256];
static char TokenStringBuffer[MAX_QUOTED_LENGTH];
static qboolean IncLineNumber;
static char TempBuffer[2048];
static struct
{
char *name;
tokenType_t token;
} Keywords[] =
{
"model", TK_MODEL,
"mesh", TK_MESH,
"vertices", TK_VERTICES,
"edges", TK_EDGES,
"position", TK_POSITION,
"polygons", TK_POLYGONS,
"nodes", TK_NODES,
"rotation", TK_ROTATION,
"scaling", TK_SCALING,
"translation", TK_TRANSLATION,
"vertex", TK_VERTEX,
"HRCH", TK_HRCH,
"Softimage", TK_SOFTIMAGE,
"material", TK_MATERIAL,
"spline", TK_SPLINE,
"Named", TK_C_NAMED,
"object", TK_OBJECT,
"Tri", TK_C_TRI,
"Vertices", TK_C_VERTICES,
"Faces", TK_C_FACES,
"Vertex", TK_C_VERTEX,
"list", TK_LIST,
"Face", TK_C_FACE,
"Hexen", TK_C_HEXEN,
"Triangles", TK_C_TRIANGLES,
"Version", TK_C_VERSION,
"faces", TK_FACES,
"face", TK_FACE,
"origin", TK_ORIGIN,
"DK_clusters", TK_CLUSTERS,
"DK_cluster_ncvs", TK_NUM_CLUSTER_VERTICES,
"name", TK_NAME,
"DK_cluster_name", TK_CLUSTER_NAME,
"DK_cluster_state", TK_CLUSTER_STATE,
"actor_data", TK_ACTOR_DATA,
"uvTexture", TK_UVTEXTURE,
NULL, -1
};
static char *TokenNames[] =
{
"<nothing>",
"<unknown_char>",
"<EOF>",
"<identifier>",
"<string>",
"<int_number>",
"<float_number>",
"(",
")",
"{",
"}",
"[",
"]",
":",
"mesh",
"model",
"nodes",
"rotation",
"scaling",
"translation",
"polygons",
"position",
"vertex",
"vertices",
"HRCH",
"Softimage"
};
// CODE --------------------------------------------------------------------
//==========================================================================
//
// TK_Init
//
//==========================================================================
void TK_Init(void)
{
int i;
for(i = 0; i < 256; i++)
{
ASCIIToChrCode[i] = CHR_SPECIAL;
}
for(i = '0'; i <= '9'; i++)
{
ASCIIToChrCode[i] = CHR_NUMBER;
}
for(i = 'A'; i <= 'Z'; i++)
{
ASCIIToChrCode[i] = CHR_LETTER;
}
for(i = 'a'; i <= 'z'; i++)
{
ASCIIToChrCode[i] = CHR_LETTER;
}
ASCIIToChrCode[ASCII_QUOTE] = CHR_QUOTE;
ASCIIToChrCode[ASCII_UNDERSCORE] = CHR_LETTER;
ASCIIToChrCode[EOF_CHARACTER] = CHR_EOF;
tk_String = TokenStringBuffer;
IncLineNumber = FALSE;
SourceOpen = FALSE;
}
//==========================================================================
//
// TK_OpenSource
//
//==========================================================================
void TK_OpenSource(char *fileName)
{
int size;
TK_CloseSource();
size = LoadFile(fileName, (void **)&FileStart);
strcpy(tk_SourceName, fileName);
SourceOpen = TRUE;
FileEnd = FileStart+size;
FilePtr = FileStart;
tk_Line = 1;
tk_Token = TK_NONE;
NextChr();
}
//==========================================================================
//
// TK_CloseSource
//
//==========================================================================
void TK_CloseSource(void)
{
if(SourceOpen)
{
free(FileStart);
SourceOpen = FALSE;
}
}
//==========================================================================
//
// TK_Fetch
//
//==========================================================================
tokenType_t TK_Fetch(void)
{
while(Chr == ASCII_SPACE)
{
NextChr();
}
if(Chr == '-')
{
ProcessNumberToken();
}
else switch(ASCIIToChrCode[(byte)Chr])
{
case CHR_EOF:
tk_Token = TK_EOF;
break;
case CHR_LETTER:
ProcessLetterToken();
break;
case CHR_NUMBER:
ProcessNumberToken();
break;
case CHR_QUOTE:
ProcessQuoteToken();
break;
default:
ProcessSpecialToken();
break;
}
return tk_Token;
}
//==========================================================================
//
// TK_Require
//
//==========================================================================
void TK_Require(tokenType_t tokType)
{
if(tokType == TK_FLOATNUMBER && tk_Token == TK_INTNUMBER)
{
tk_FloatNumber = (float)tk_IntNumber;
tk_Token = TK_FLOATNUMBER;
return;
}
if(tk_Token != tokType)
{
Error("File '%s', line %d:\nExpected '%s', found '%s'.\n",
tk_SourceName, tk_Line, TokenNames[tokType],
TokenNames[tk_Token]);
}
}
void TK_FetchRequire(tokenType_t tokType)
{
TK_Fetch();
TK_Require(tokType);
}
tokenType_t TK_RequireFetch(tokenType_t tokType)
{
TK_Require(tokType);
return TK_Fetch();
}
tokenType_t TK_FetchRequireFetch(tokenType_t tokType)
{
TK_Fetch();
TK_Require(tokType);
return TK_Fetch();
}
tokenType_t TK_Beyond(tokenType_t tokType)
{
while(tk_Token != tokType)
{
if(TK_Fetch() == TK_EOF)
{
Error("File '%s':\nCould not find token '%s'.\n", // FIXME: TokenNames table not big enuff
tk_SourceName, TokenNames[tokType]);
}
}
return TK_Fetch();
}
void TK_BeyondRequire(tokenType_t bTok, tokenType_t rTok)
{
TK_Beyond(bTok);
TK_Require(rTok);
}
tokenType_t TK_Search(tokenType_t tokType)
{
while(tk_Token != tokType)
{
if(TK_Fetch() == TK_EOF)
{
return TK_EOF;
}
}
return TK_Fetch();
}
tokenType_t TK_Get(tokenType_t tokType)
{
while(tk_Token != tokType)
{
if(TK_Fetch() == TK_EOF)
{
Error("File '%s':\nCould not find token '%s'.\n",
tk_SourceName, TokenNames[tokType]);
}
}
return tk_Token;
}
//==========================================================================
//
// ProcessLetterToken
//
//==========================================================================
static void ProcessLetterToken(void)
{
int i;
char *text;
i = 0;
text = TokenStringBuffer;
while(ASCIIToChrCode[(byte)Chr] == CHR_LETTER
|| ASCIIToChrCode[(byte)Chr] == CHR_NUMBER)
{
if(++i == MAX_IDENTIFIER_LENGTH)
{
Error("File '%s', line %d:\nIdentifier too long.\n",
tk_SourceName, tk_Line);
}
*text++ = Chr;
NextChr();
}
*text = 0;
if(CheckForKeyword() == FALSE)
{
tk_Token = TK_IDENTIFIER;
}
}
//==========================================================================
//
// CheckForKeyword
//
//==========================================================================
static qboolean CheckForKeyword(void)
{
int i;
for(i = 0; Keywords[i].name != NULL; i++)
{
if(strcmp(tk_String, Keywords[i].name) == 0)
{
tk_Token = Keywords[i].token;
return TRUE;
}
}
return FALSE;
}
//==========================================================================
//
// ProcessNumberToken
//
//==========================================================================
static void ProcessNumberToken(void)
{
char *buffer;
buffer = TempBuffer;
*buffer++ = Chr;
NextChr();
while(ASCIIToChrCode[(byte)Chr] == CHR_NUMBER)
{
*buffer++ = Chr;
NextChr();
}
if(Chr == '.')
{ // Float
*buffer++ = Chr;
NextChr(); // Skip period
while(ASCIIToChrCode[(byte)Chr] == CHR_NUMBER)
{
*buffer++ = Chr;
NextChr();
}
*buffer = 0;
tk_FloatNumber = (float)atof(TempBuffer);
tk_Token = TK_FLOATNUMBER;
return;
}
// Integer
*buffer = 0;
tk_IntNumber = atoi(TempBuffer);
tk_Token = TK_INTNUMBER;
}
//==========================================================================
//
// ProcessQuoteToken
//
//==========================================================================
static void ProcessQuoteToken(void)
{
int i;
char *text;
i = 0;
text = TokenStringBuffer;
NextChr();
while(Chr != ASCII_QUOTE)
{
if(Chr == EOF_CHARACTER)
{
Error("File '%s', line %d:\n<EOF> inside string.\n",
tk_SourceName, tk_Line);
}
if(++i > MAX_QUOTED_LENGTH-1)
{
Error("File '%s', line %d:\nString literal too long.\n",
tk_SourceName, tk_Line);
}
*text++ = Chr;
NextChr();
}
*text = 0;
NextChr();
tk_Token = TK_STRING;
}
//==========================================================================
//
// ProcessSpecialToken
//
//==========================================================================
static void ProcessSpecialToken(void)
{
char c;
c = Chr;
NextChr();
switch(c)
{
case '(':
tk_Token = TK_LPAREN;
break;
case ')':
tk_Token = TK_RPAREN;
break;
case '{':
tk_Token = TK_LBRACE;
break;
case '}':
tk_Token = TK_RBRACE;
break;
case '[':
tk_Token = TK_LBRACKET;
break;
case ']':
tk_Token = TK_RBRACKET;
break;
case ':':
tk_Token = TK_COLON;
break;
default:
tk_Token = TK_UNKNOWNCHAR;
break;
}
}
//==========================================================================
//
// NextChr
//
//==========================================================================
static void NextChr(void)
{
if(FilePtr >= FileEnd)
{
Chr = EOF_CHARACTER;
return;
}
if(IncLineNumber == TRUE)
{
tk_Line++;
IncLineNumber = FALSE;
}
Chr = *FilePtr++;
if(Chr < ASCII_SPACE)
{
if(Chr == '\n')
{
IncLineNumber = TRUE;
}
Chr = ASCII_SPACE;
}
}