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