2015-06-05 04:09:08 -07:00
|
|
|
/*
|
2015-06-05 21:47:23 -07:00
|
|
|
Copyright (c) 2015 Benjamin Moir <bennyboy.private@hotmail.com.au>
|
2015-06-05 04:09:08 -07:00
|
|
|
Copyright (c) 2015 Marrub <marrub@greyserv.net>
|
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
|
|
in the Software without restriction, including without limitation the rights
|
|
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
|
|
all copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
THE SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "lt.h"
|
|
|
|
|
2015-06-05 15:09:04 -07:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <stdlib.h>
|
2015-06-07 01:04:23 -07:00
|
|
|
#include <stdarg.h>
|
2015-06-05 15:09:04 -07:00
|
|
|
|
2015-06-11 06:42:36 -07:00
|
|
|
#ifdef __GDCC__
|
|
|
|
#include <ACS_Zandronum.h>
|
|
|
|
#else
|
2015-07-26 02:36:36 -07:00
|
|
|
#ifndef LT_NO_ICONV
|
2015-06-11 06:42:36 -07:00
|
|
|
#include <iconv.h>
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef __GDCC__
|
2015-07-26 02:36:36 -07:00
|
|
|
|
|
|
|
// TODO: replace these with GDCC's new file function tables or whatever they're called
|
|
|
|
|
2015-06-11 06:42:36 -07:00
|
|
|
#define fopen LT_FOpen
|
|
|
|
#define ftell LT_FTell
|
|
|
|
#define fgetc LT_FGetC
|
|
|
|
#define ungetc LT_UnGetC
|
|
|
|
#define fseek LT_FSeek
|
|
|
|
#define fclose LT_FClose
|
|
|
|
#define FILE LT_File
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
__str langId;
|
|
|
|
__str data;
|
|
|
|
int pos;
|
|
|
|
} LT_File;
|
|
|
|
#endif
|
|
|
|
|
2015-06-05 10:38:34 -07:00
|
|
|
/*
|
|
|
|
* Variables
|
|
|
|
*/
|
2015-06-05 04:09:08 -07:00
|
|
|
|
2015-06-05 10:38:34 -07:00
|
|
|
static LT_GarbageList *gbHead, *gbRover;
|
2015-06-05 09:44:24 -07:00
|
|
|
static FILE *parseFile;
|
2015-06-07 00:46:36 -07:00
|
|
|
static LT_Config cfg;
|
2015-06-11 06:42:36 -07:00
|
|
|
|
2015-07-26 02:36:36 -07:00
|
|
|
#ifndef LT_NO_ICONV
|
2015-06-05 08:14:35 -07:00
|
|
|
static iconv_t icDesc;
|
2015-06-11 06:42:36 -07:00
|
|
|
#endif
|
|
|
|
|
2015-07-29 04:59:25 -07:00
|
|
|
static LT_BOOL assertError = LT_FALSE;
|
2015-06-06 18:53:22 -07:00
|
|
|
static char *assertString;
|
2015-06-11 06:42:36 -07:00
|
|
|
static char *stringChars = (char *)"\"", *charChars = (char *)"'";
|
2015-06-06 06:28:04 -07:00
|
|
|
|
|
|
|
static const char *errors[] = {
|
|
|
|
"LT_Error: Syntax error",
|
2015-06-06 18:53:22 -07:00
|
|
|
"LT_Error: Unknown operation",
|
|
|
|
"LT_Error: Out of memory"
|
2015-06-06 06:28:04 -07:00
|
|
|
};
|
2015-06-05 04:09:08 -07:00
|
|
|
|
2015-06-11 06:05:23 -07:00
|
|
|
const char *LT_TkNames[] = {
|
2015-06-05 04:09:08 -07:00
|
|
|
// [marrub] So, this was an interesting bug. This was completely misordered from the enum.
|
|
|
|
// As can be guessed, this caused many issues. Seriously, all of them.
|
2015-06-07 05:02:33 -07:00
|
|
|
"TOK_Colon", "TOK_Comma", "TOK_Div", "TOK_Mod", "TOK_Mul", "TOK_Query",
|
|
|
|
"TOK_BraceO", "TOK_BraceC","TOK_BrackO", "TOK_BrackC", "TOK_ParenO", "TOK_ParenC",
|
|
|
|
"TOK_LnEnd", "TOK_Add2", "TOK_Add", "TOK_And2", "TOK_And", "TOK_CmpGE",
|
|
|
|
"TOK_ShR", "TOK_CmpGT", "TOK_CmpLE", "TOK_ShL", "TOK_CmpNE", "TOK_CmpLT",
|
|
|
|
"TOK_CmpEQ", "TOK_Equal", "TOK_Not", "TOK_OrI2", "TOK_OrI", "TOK_OrX2",
|
|
|
|
"TOK_OrX", "TOK_Sub2", "TOK_Sub", "TOK_String", "TOK_Charac", "TOK_Number",
|
|
|
|
"TOK_Identi", "TOK_EOF", "TOK_ChrSeq", "TOK_Comment","TOK_Period", "TOK_Arrow",
|
|
|
|
"TOK_Sigil", "TOK_Hash", "TOK_BlkCmtO","TOK_BlkCmtC","TOK_Exp", "TOK_NstCmtO",
|
|
|
|
"TOK_NstCmtC", "TOK_Semicl"
|
2015-06-05 04:09:08 -07:00
|
|
|
};
|
|
|
|
|
2015-06-05 10:38:34 -07:00
|
|
|
/*
|
|
|
|
* Functions
|
|
|
|
*/
|
|
|
|
|
2015-07-26 02:36:36 -07:00
|
|
|
#ifndef LT_NO_ICONV
|
2015-06-05 08:14:35 -07:00
|
|
|
static void LT_DoConvert(char **str)
|
|
|
|
{
|
|
|
|
size_t i = strlen(*str);
|
|
|
|
char *strbuf = calloc((i * 6) + 1, 1);
|
|
|
|
char *strbufOrig = strbuf, *strOrig = *str;
|
|
|
|
size_t in = i, out = i * 6;
|
|
|
|
|
|
|
|
iconv(icDesc, str, &in, &strbuf, &out);
|
|
|
|
|
|
|
|
*str = strOrig, strbuf = strbufOrig;
|
|
|
|
|
|
|
|
free(*str);
|
|
|
|
*str = strbuf;
|
|
|
|
}
|
2015-06-11 06:42:36 -07:00
|
|
|
#endif
|
2015-06-05 08:14:35 -07:00
|
|
|
|
2015-06-06 09:47:13 -07:00
|
|
|
static void *LT_Alloc(size_t size)
|
|
|
|
{
|
|
|
|
void *p = malloc(size);
|
2015-06-06 18:53:22 -07:00
|
|
|
|
|
|
|
if(p == NULL)
|
|
|
|
{ // [marrub] if we don't error it will try to allocate an assertion, thus breaking horribly
|
|
|
|
LT_Error(LTERR_NOMEMORY);
|
|
|
|
}
|
|
|
|
|
2015-06-06 09:47:13 -07:00
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *LT_ReAlloc(void *ptr, size_t newSize)
|
|
|
|
{
|
|
|
|
void *p = realloc(ptr, newSize);
|
2015-06-06 18:53:22 -07:00
|
|
|
|
|
|
|
if(p == NULL)
|
|
|
|
{
|
|
|
|
LT_Error(LTERR_NOMEMORY);
|
|
|
|
}
|
|
|
|
|
2015-06-06 09:47:13 -07:00
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
2015-06-06 18:53:22 -07:00
|
|
|
static void *LT_SetGarbage(void *p)
|
|
|
|
{
|
2015-06-11 06:42:36 -07:00
|
|
|
#ifndef __GDCC__
|
2015-06-06 18:53:22 -07:00
|
|
|
gbRover->next = LT_Alloc(sizeof(LT_GarbageList));
|
|
|
|
gbRover = gbRover->next;
|
|
|
|
gbRover->ptr = p;
|
|
|
|
gbRover->next = NULL;
|
|
|
|
|
|
|
|
return gbRover->ptr;
|
2015-06-11 06:42:36 -07:00
|
|
|
#else
|
|
|
|
return p;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef __GDCC__
|
|
|
|
#define StrParam(...) \
|
2015-07-26 02:36:36 -07:00
|
|
|
( \
|
|
|
|
ACS_BeginStrParam(), \
|
|
|
|
__nprintf(__VA_ARGS__), \
|
|
|
|
ACS_EndStrParam() \
|
|
|
|
)
|
2015-06-11 06:42:36 -07:00
|
|
|
#define StrParamL(...) (StrParam("%LS", StrParam(__VA_ARGS__)))
|
|
|
|
|
|
|
|
LT_File *LT_FOpen(__str languageId, const char *mode)
|
|
|
|
{
|
|
|
|
LT_File *file = LT_Alloc(sizeof(LT_File));
|
|
|
|
|
|
|
|
file->langId = languageId;
|
|
|
|
file->data = StrParamL("%S", languageId);
|
|
|
|
file->pos = 0;
|
|
|
|
|
|
|
|
return file;
|
|
|
|
}
|
|
|
|
|
|
|
|
int LT_FTell(LT_File *file)
|
|
|
|
{
|
|
|
|
return file->pos;
|
|
|
|
}
|
|
|
|
|
|
|
|
int LT_FGetC(LT_File *file)
|
|
|
|
{
|
|
|
|
int c = ACS_GetChar(file->data, file->pos++);
|
|
|
|
return c < 1 ? EOF : c;
|
|
|
|
}
|
|
|
|
|
|
|
|
int LT_UnGetC(int ch, LT_File *file)
|
|
|
|
{
|
|
|
|
int c = ACS_GetChar(file->data, file->pos--);
|
|
|
|
return c < 1 ? EOF : c;
|
|
|
|
}
|
|
|
|
|
|
|
|
int LT_FSeek(LT_File *file, long int offset, int whence)
|
|
|
|
{
|
|
|
|
switch(whence)
|
|
|
|
{
|
|
|
|
case SEEK_SET:
|
|
|
|
file->pos = offset;
|
|
|
|
return 0;
|
|
|
|
case SEEK_CUR:
|
|
|
|
file->pos += offset;
|
|
|
|
return 0;
|
|
|
|
case SEEK_END:
|
|
|
|
file->pos = ACS_StrLen(file->data) + offset;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int LT_FClose(LT_File *file)
|
|
|
|
{
|
|
|
|
free(file);
|
|
|
|
return 0;
|
2015-06-06 18:53:22 -07:00
|
|
|
}
|
2015-06-11 06:42:36 -07:00
|
|
|
#endif
|
2015-06-06 18:53:22 -07:00
|
|
|
|
2015-06-07 00:46:36 -07:00
|
|
|
void LT_Init(LT_Config initCfg)
|
2015-06-05 04:09:08 -07:00
|
|
|
{
|
2015-06-11 06:42:36 -07:00
|
|
|
#ifndef __GDCC__
|
2015-07-26 02:36:36 -07:00
|
|
|
// [marrub] we don't need a garbage collector in GDCC
|
2015-06-06 09:47:13 -07:00
|
|
|
gbHead = LT_Alloc(sizeof(LT_GarbageList));
|
2015-06-06 07:08:55 -07:00
|
|
|
gbHead->next = NULL;
|
|
|
|
gbHead->ptr = NULL;
|
|
|
|
|
|
|
|
gbRover = gbHead;
|
2015-06-11 06:42:36 -07:00
|
|
|
#endif
|
2015-06-06 07:08:55 -07:00
|
|
|
|
2015-06-07 00:46:36 -07:00
|
|
|
cfg = initCfg;
|
2015-06-05 04:09:08 -07:00
|
|
|
|
2015-07-26 02:36:36 -07:00
|
|
|
#ifndef LT_NO_ICONV
|
2015-06-07 00:46:36 -07:00
|
|
|
if(cfg.doConvert && cfg.fromCode != NULL && cfg.toCode != NULL)
|
2015-06-05 08:14:35 -07:00
|
|
|
{
|
2015-06-07 00:46:36 -07:00
|
|
|
icDesc = iconv_open(cfg.toCode, cfg.fromCode);
|
2015-06-05 08:14:35 -07:00
|
|
|
|
|
|
|
if(icDesc == (iconv_t) -1)
|
|
|
|
{
|
2015-07-29 04:59:25 -07:00
|
|
|
LT_Assert(LT_TRUE, "LT_Init: Failure opening iconv");
|
2015-06-05 08:14:35 -07:00
|
|
|
}
|
|
|
|
}
|
2015-06-06 05:42:29 -07:00
|
|
|
else
|
|
|
|
{
|
2015-07-29 04:59:25 -07:00
|
|
|
cfg.doConvert = LT_FALSE;
|
2015-06-06 05:42:29 -07:00
|
|
|
}
|
|
|
|
|
2015-06-07 00:46:36 -07:00
|
|
|
if(cfg.stripInvalid && cfg.doConvert)
|
2015-06-06 05:42:29 -07:00
|
|
|
{
|
2015-07-29 04:59:25 -07:00
|
|
|
cfg.stripInvalid = LT_FALSE;
|
2015-06-06 05:42:29 -07:00
|
|
|
}
|
2015-06-11 06:42:36 -07:00
|
|
|
#endif
|
2015-06-06 07:13:54 -07:00
|
|
|
|
2015-06-07 00:46:36 -07:00
|
|
|
if(cfg.stringChars != NULL)
|
2015-06-06 07:13:54 -07:00
|
|
|
{
|
2015-07-29 05:30:16 -07:00
|
|
|
unsigned i;
|
2015-06-06 07:13:54 -07:00
|
|
|
|
2015-06-06 09:47:13 -07:00
|
|
|
stringChars = LT_Alloc(6);
|
2015-06-06 07:13:54 -07:00
|
|
|
|
|
|
|
for(i = 0; i < 6; i++)
|
|
|
|
{
|
2015-06-07 00:46:36 -07:00
|
|
|
int c = cfg.stringChars[i];
|
2015-06-06 07:13:54 -07:00
|
|
|
|
|
|
|
if(c != '\0')
|
|
|
|
{
|
|
|
|
stringChars[i] = c;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
stringChars[i] = '\0';
|
|
|
|
|
2015-06-06 18:53:22 -07:00
|
|
|
LT_SetGarbage(stringChars);
|
2015-06-06 07:13:54 -07:00
|
|
|
}
|
|
|
|
|
2015-06-07 00:46:36 -07:00
|
|
|
if(cfg.charChars != NULL)
|
2015-06-06 07:13:54 -07:00
|
|
|
{
|
2015-07-29 05:30:16 -07:00
|
|
|
unsigned i;
|
2015-06-06 07:13:54 -07:00
|
|
|
|
2015-06-06 09:47:13 -07:00
|
|
|
charChars = LT_Alloc(6);
|
2015-06-06 07:13:54 -07:00
|
|
|
|
|
|
|
for(i = 0; i < 6; i++)
|
|
|
|
{
|
2015-06-07 00:46:36 -07:00
|
|
|
int c = cfg.charChars[i];
|
|
|
|
|
|
|
|
if(c != '\0')
|
|
|
|
{
|
|
|
|
charChars[i] = c;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
charChars[i] = '\0';
|
|
|
|
|
|
|
|
LT_SetGarbage(charChars);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void LT_SetConfig(LT_Config newCfg)
|
|
|
|
{
|
|
|
|
cfg = newCfg;
|
|
|
|
|
2015-07-26 02:36:36 -07:00
|
|
|
#ifndef LT_NO_ICONV
|
2015-06-07 00:46:36 -07:00
|
|
|
if(cfg.doConvert && cfg.fromCode != NULL && cfg.toCode != NULL)
|
|
|
|
{
|
|
|
|
if(icDesc != NULL)
|
|
|
|
{
|
|
|
|
iconv_close(icDesc);
|
|
|
|
}
|
|
|
|
|
|
|
|
icDesc = iconv_open(cfg.toCode, cfg.fromCode);
|
|
|
|
|
|
|
|
if(icDesc == (iconv_t) -1)
|
|
|
|
{
|
2015-07-29 04:59:25 -07:00
|
|
|
LT_Assert(LT_TRUE, "LT_Init: Failure opening iconv");
|
2015-06-07 00:46:36 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if(icDesc != NULL)
|
|
|
|
{
|
|
|
|
iconv_close(icDesc);
|
|
|
|
icDesc = NULL;
|
|
|
|
}
|
|
|
|
|
2015-07-29 04:59:25 -07:00
|
|
|
cfg.doConvert = LT_FALSE;
|
2015-06-07 00:46:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if(cfg.stripInvalid && cfg.doConvert)
|
|
|
|
{
|
2015-07-29 04:59:25 -07:00
|
|
|
cfg.stripInvalid = LT_FALSE;
|
2015-06-07 00:46:36 -07:00
|
|
|
}
|
2015-06-11 06:42:36 -07:00
|
|
|
#endif
|
2015-06-07 00:46:36 -07:00
|
|
|
|
|
|
|
if(cfg.stringChars != NULL)
|
|
|
|
{
|
2015-07-29 05:30:16 -07:00
|
|
|
unsigned i;
|
2015-06-07 00:46:36 -07:00
|
|
|
|
|
|
|
stringChars = LT_Alloc(6);
|
|
|
|
|
|
|
|
for(i = 0; i < 6; i++)
|
|
|
|
{
|
|
|
|
int c = cfg.stringChars[i];
|
|
|
|
|
|
|
|
if(c != '\0')
|
|
|
|
{
|
|
|
|
stringChars[i] = c;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
stringChars[i] = '\0';
|
|
|
|
|
|
|
|
LT_SetGarbage(stringChars);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(cfg.charChars != NULL)
|
|
|
|
{
|
2015-07-29 05:30:16 -07:00
|
|
|
unsigned i;
|
2015-06-07 00:46:36 -07:00
|
|
|
|
|
|
|
charChars = LT_Alloc(6);
|
|
|
|
|
|
|
|
for(i = 0; i < 6; i++)
|
|
|
|
{
|
|
|
|
int c = cfg.charChars[i];
|
2015-06-06 07:13:54 -07:00
|
|
|
|
|
|
|
if(c != '\0')
|
|
|
|
{
|
|
|
|
charChars[i] = c;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
charChars[i] = '\0';
|
|
|
|
|
2015-06-06 18:53:22 -07:00
|
|
|
LT_SetGarbage(charChars);
|
2015-06-06 07:13:54 -07:00
|
|
|
}
|
2015-06-05 04:09:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void LT_Quit()
|
|
|
|
{
|
2015-07-26 02:36:36 -07:00
|
|
|
#ifndef LT_NO_ICONV
|
2015-06-07 00:46:36 -07:00
|
|
|
if(cfg.doConvert)
|
2015-06-05 08:14:35 -07:00
|
|
|
{
|
|
|
|
iconv_close(icDesc);
|
|
|
|
}
|
2015-06-11 06:42:36 -07:00
|
|
|
#endif
|
2015-06-05 08:14:35 -07:00
|
|
|
|
2015-06-11 06:42:36 -07:00
|
|
|
#ifndef __GDCC__
|
2015-06-05 04:09:08 -07:00
|
|
|
gbRover = gbHead;
|
|
|
|
|
|
|
|
while(gbRover != NULL)
|
|
|
|
{
|
|
|
|
LT_GarbageList *next = gbRover->next;
|
|
|
|
|
|
|
|
if(gbRover->ptr != NULL)
|
|
|
|
{
|
|
|
|
free(gbRover->ptr);
|
|
|
|
gbRover->ptr = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
free(gbRover);
|
|
|
|
|
|
|
|
gbRover = next;
|
|
|
|
}
|
|
|
|
|
|
|
|
gbRover = NULL;
|
|
|
|
gbHead = NULL;
|
2015-06-11 06:42:36 -07:00
|
|
|
#endif
|
2015-06-05 04:09:08 -07:00
|
|
|
}
|
|
|
|
|
2015-07-29 04:59:25 -07:00
|
|
|
LT_BOOL LT_Assert(LT_BOOL assertion, const char *fmt, ...)
|
2015-06-05 04:09:08 -07:00
|
|
|
{
|
|
|
|
if(assertion)
|
|
|
|
{
|
2015-06-07 01:04:23 -07:00
|
|
|
char ftString[16];
|
|
|
|
char asBuffer[512];
|
|
|
|
|
|
|
|
va_list va;
|
2015-07-29 04:59:25 -07:00
|
|
|
assertError = LT_TRUE;
|
2015-06-06 18:53:22 -07:00
|
|
|
assertString = malloc(512);
|
|
|
|
|
2015-07-29 05:30:16 -07:00
|
|
|
sprintf(ftString, ":%ld:", ftell(parseFile));
|
2015-06-07 01:04:23 -07:00
|
|
|
|
|
|
|
va_start(va, fmt);
|
2015-07-29 05:30:16 -07:00
|
|
|
vsprintf(asBuffer, fmt, va);
|
2015-06-07 01:04:23 -07:00
|
|
|
va_end(va);
|
|
|
|
|
2015-07-29 05:30:16 -07:00
|
|
|
sprintf(assertString, "%s%s", ftString, asBuffer);
|
2015-06-05 10:38:34 -07:00
|
|
|
|
2015-07-26 02:40:32 -07:00
|
|
|
LT_SetGarbage(assertString);
|
2015-06-05 04:09:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return assertion;
|
|
|
|
}
|
|
|
|
|
2015-06-06 05:12:58 -07:00
|
|
|
void LT_Error(int type)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "%s", errors[type]);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2015-06-05 08:14:35 -07:00
|
|
|
LT_AssertInfo LT_CheckAssert()
|
|
|
|
{
|
|
|
|
LT_AssertInfo ltAssertion;
|
2015-06-05 09:44:24 -07:00
|
|
|
ltAssertion.failure = assertError;
|
|
|
|
ltAssertion.str = assertString;
|
2015-06-05 08:14:35 -07:00
|
|
|
return ltAssertion;
|
|
|
|
}
|
|
|
|
|
2015-06-11 06:42:36 -07:00
|
|
|
#ifndef __GDCC__
|
2015-07-29 04:59:25 -07:00
|
|
|
LT_BOOL LT_OpenFile(const char *filePath)
|
2015-06-11 06:42:36 -07:00
|
|
|
#else
|
2015-07-29 04:59:25 -07:00
|
|
|
LT_BOOL LT_OpenFile(__str filePath)
|
2015-06-11 06:42:36 -07:00
|
|
|
#endif
|
2015-06-05 04:09:08 -07:00
|
|
|
{
|
2015-06-05 09:44:24 -07:00
|
|
|
parseFile = fopen(filePath, "r");
|
2015-06-05 04:09:08 -07:00
|
|
|
|
2015-06-05 09:44:24 -07:00
|
|
|
if(parseFile == NULL)
|
2015-06-05 04:09:08 -07:00
|
|
|
{
|
2015-07-29 04:59:25 -07:00
|
|
|
LT_Assert(LT_TRUE, "LT_OpenFile: %s", strerror(errno));
|
|
|
|
return LT_FALSE;
|
2015-06-05 04:09:08 -07:00
|
|
|
}
|
|
|
|
|
2015-07-29 04:59:25 -07:00
|
|
|
return LT_TRUE;
|
2015-06-05 04:09:08 -07:00
|
|
|
}
|
|
|
|
|
2015-06-07 00:46:36 -07:00
|
|
|
void LT_SetPos(int newPos)
|
|
|
|
{
|
2015-06-11 06:42:36 -07:00
|
|
|
#ifndef __GDCC__
|
2015-06-07 00:46:36 -07:00
|
|
|
if(fseek(parseFile, newPos, SEEK_SET) != 0)
|
|
|
|
{
|
2015-06-07 01:04:23 -07:00
|
|
|
LT_Assert(ferror(parseFile), "LT_SetPos: %s", strerror(errno));
|
2015-06-07 00:46:36 -07:00
|
|
|
}
|
2015-06-11 06:42:36 -07:00
|
|
|
#else
|
|
|
|
fseek(parseFile, newPos, SEEK_SET);
|
|
|
|
#endif
|
2015-06-07 00:46:36 -07:00
|
|
|
}
|
|
|
|
|
2015-06-05 04:09:08 -07:00
|
|
|
void LT_CloseFile()
|
|
|
|
{
|
2015-06-05 09:44:24 -07:00
|
|
|
if(parseFile != NULL)
|
2015-06-05 04:09:08 -07:00
|
|
|
{
|
2015-06-05 09:44:24 -07:00
|
|
|
fclose(parseFile);
|
2015-06-05 04:09:08 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
char *LT_ReadNumber()
|
|
|
|
{
|
2015-06-06 09:47:13 -07:00
|
|
|
size_t i = 0, strBlocks = 1;
|
|
|
|
char *str = LT_Alloc(TOKEN_STR_BLOCK_LENGTH);
|
|
|
|
int c = '\0';
|
2015-06-05 04:09:08 -07:00
|
|
|
|
2015-06-06 09:47:13 -07:00
|
|
|
while(c != EOF)
|
2015-06-05 04:09:08 -07:00
|
|
|
{
|
2015-06-06 09:47:13 -07:00
|
|
|
c = fgetc(parseFile);
|
2015-06-05 04:09:08 -07:00
|
|
|
|
|
|
|
if(!isalnum(c))
|
|
|
|
{
|
2015-06-06 09:47:13 -07:00
|
|
|
ungetc(c, parseFile);
|
2015-06-05 04:09:08 -07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-06-06 09:47:13 -07:00
|
|
|
if(i > (TOKEN_STR_BLOCK_LENGTH * strBlocks))
|
2015-06-05 04:09:08 -07:00
|
|
|
{
|
2015-06-06 09:47:13 -07:00
|
|
|
str = LT_ReAlloc(str, TOKEN_STR_BLOCK_LENGTH * ++strBlocks);
|
2015-06-05 04:09:08 -07:00
|
|
|
}
|
|
|
|
|
2015-06-05 08:14:35 -07:00
|
|
|
str[i++] = c;
|
|
|
|
|
2015-06-07 00:46:36 -07:00
|
|
|
if(cfg.stripInvalid)
|
2015-06-05 08:14:35 -07:00
|
|
|
{
|
|
|
|
str[i++] = (isspace(c) || isprint(c)) ? c : ' ';
|
|
|
|
}
|
2015-06-05 04:09:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
str[i++] = '\0';
|
|
|
|
|
2015-07-26 02:36:36 -07:00
|
|
|
#ifndef LT_NO_ICONV
|
2015-06-07 00:46:36 -07:00
|
|
|
if(cfg.doConvert)
|
2015-06-05 08:14:35 -07:00
|
|
|
{
|
|
|
|
LT_DoConvert(&str);
|
|
|
|
}
|
2015-06-11 06:42:36 -07:00
|
|
|
#endif
|
2015-06-05 08:14:35 -07:00
|
|
|
|
2015-06-06 18:53:22 -07:00
|
|
|
return LT_SetGarbage(LT_ReAlloc(str, i));
|
2015-06-05 04:09:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
char *LT_ReadString(char term)
|
|
|
|
{
|
2015-06-06 09:47:13 -07:00
|
|
|
size_t i = 0, strBlocks = 1;
|
|
|
|
char *str = LT_Alloc(TOKEN_STR_BLOCK_LENGTH);
|
|
|
|
int c;
|
2015-06-05 04:09:08 -07:00
|
|
|
|
2015-07-29 04:59:25 -07:00
|
|
|
while(LT_TRUE)
|
2015-06-05 04:09:08 -07:00
|
|
|
{
|
2015-06-06 09:47:13 -07:00
|
|
|
c = fgetc(parseFile);
|
2015-06-05 04:09:08 -07:00
|
|
|
|
|
|
|
if(c == term)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-06-06 09:47:13 -07:00
|
|
|
if(LT_Assert(c == EOF || c == '\n', "LT_ReadString: Unterminated string literal"))
|
2015-06-05 04:09:08 -07:00
|
|
|
{
|
2015-06-06 10:07:07 -07:00
|
|
|
char *emptyString = LT_Alloc(1);
|
|
|
|
emptyString[0] = '\0';
|
|
|
|
|
2015-06-06 18:53:22 -07:00
|
|
|
return LT_SetGarbage(emptyString);
|
2015-06-05 04:09:08 -07:00
|
|
|
}
|
|
|
|
|
2015-06-07 00:46:36 -07:00
|
|
|
if(c == '\\' && cfg.escapeChars)
|
2015-06-05 04:09:08 -07:00
|
|
|
{
|
2015-06-06 09:47:13 -07:00
|
|
|
c = fgetc(parseFile);
|
2015-06-05 04:09:08 -07:00
|
|
|
|
2015-06-06 09:47:13 -07:00
|
|
|
if(LT_Assert(c == EOF || c == '\n', "LT_ReadString: Unterminated string literal"))
|
2015-06-05 04:09:08 -07:00
|
|
|
{
|
|
|
|
str[i] = '\0';
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2015-06-06 09:47:13 -07:00
|
|
|
if(i > (TOKEN_STR_BLOCK_LENGTH * strBlocks))
|
2015-06-05 04:09:08 -07:00
|
|
|
{
|
2015-06-06 09:47:13 -07:00
|
|
|
str = LT_ReAlloc(str, TOKEN_STR_BLOCK_LENGTH * ++strBlocks);
|
2015-06-05 04:09:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
str = LT_Escaper(str, i++, c);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-06-06 09:47:13 -07:00
|
|
|
if(i > (TOKEN_STR_BLOCK_LENGTH * strBlocks))
|
2015-06-05 04:09:08 -07:00
|
|
|
{
|
2015-06-06 09:47:13 -07:00
|
|
|
str = LT_ReAlloc(str, TOKEN_STR_BLOCK_LENGTH * ++strBlocks);
|
2015-06-05 04:09:08 -07:00
|
|
|
}
|
|
|
|
|
2015-06-05 08:14:35 -07:00
|
|
|
str[i++] = c;
|
|
|
|
|
2015-06-07 00:46:36 -07:00
|
|
|
if(cfg.stripInvalid)
|
2015-06-05 08:14:35 -07:00
|
|
|
{
|
|
|
|
str[i++] = (isspace(c) || isprint(c)) ? c : ' ';
|
|
|
|
}
|
2015-06-05 04:09:08 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
str[i++] = '\0';
|
|
|
|
|
2015-07-26 02:36:36 -07:00
|
|
|
#ifndef LT_NO_ICONV
|
2015-06-07 00:46:36 -07:00
|
|
|
if(cfg.doConvert)
|
2015-06-05 08:14:35 -07:00
|
|
|
{
|
|
|
|
LT_DoConvert(&str);
|
|
|
|
}
|
2015-06-11 06:42:36 -07:00
|
|
|
#endif
|
2015-06-05 08:14:35 -07:00
|
|
|
|
2015-06-06 18:53:22 -07:00
|
|
|
return LT_SetGarbage(LT_ReAlloc(str, i));
|
2015-06-05 04:09:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
char *LT_Escaper(char *str, size_t pos, char escape)
|
|
|
|
{
|
2015-07-29 05:30:16 -07:00
|
|
|
unsigned i;
|
|
|
|
|
2015-06-05 04:09:08 -07:00
|
|
|
switch(escape)
|
|
|
|
{
|
|
|
|
case '\\': case '\'': case '"': str[pos] = escape; break;
|
|
|
|
case 'a': str[pos] = '\a'; break;
|
|
|
|
case 'b': str[pos] = '\b'; break;
|
|
|
|
case 'f': str[pos] = '\f'; break;
|
|
|
|
case 'n': str[pos] = '\n'; break;
|
|
|
|
case 'r': str[pos] = '\r'; break;
|
|
|
|
case 't': str[pos] = '\t'; break;
|
|
|
|
case 'v': str[pos] = '\v'; break;
|
|
|
|
case 'x': // [marrub] THIS ONE IS FUN
|
2015-07-29 05:30:16 -07:00
|
|
|
for(i = 0;;)
|
2015-06-05 04:09:08 -07:00
|
|
|
{
|
2015-06-06 09:47:13 -07:00
|
|
|
int c = fgetc(parseFile);
|
2015-06-05 04:09:08 -07:00
|
|
|
|
|
|
|
switch(c)
|
|
|
|
{
|
|
|
|
case '0': i = i * 16 + 0x0; break;
|
|
|
|
case '1': i = i * 16 + 0x1; break;
|
|
|
|
case '2': i = i * 16 + 0x2; break;
|
|
|
|
case '3': i = i * 16 + 0x3; break;
|
|
|
|
case '4': i = i * 16 + 0x4; break;
|
|
|
|
case '5': i = i * 16 + 0x5; break;
|
|
|
|
case '6': i = i * 16 + 0x6; break;
|
|
|
|
case '7': i = i * 16 + 0x7; break;
|
|
|
|
case '8': i = i * 16 + 0x8; break;
|
|
|
|
case '9': i = i * 16 + 0x9; break;
|
|
|
|
case 'a': case 'A': i = i * 16 + 0xA; break;
|
|
|
|
case 'b': case 'B': i = i * 16 + 0xB; break;
|
|
|
|
case 'c': case 'C': i = i * 16 + 0xC; break;
|
|
|
|
case 'd': case 'D': i = i * 16 + 0xD; break;
|
|
|
|
case 'e': case 'E': i = i * 16 + 0xE; break;
|
|
|
|
case 'f': case 'F': i = i * 16 + 0xF; break;
|
|
|
|
|
|
|
|
default:
|
2015-06-06 09:47:13 -07:00
|
|
|
ungetc(c, parseFile);
|
2015-06-05 04:09:08 -07:00
|
|
|
str[pos] = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '0': case '1': case '2': case '3':
|
|
|
|
case '4': case '5': case '6': case '7':
|
|
|
|
{
|
2015-06-06 09:47:13 -07:00
|
|
|
int c = escape;
|
2015-07-29 05:30:16 -07:00
|
|
|
unsigned n;
|
|
|
|
|
|
|
|
i = 0;
|
2015-06-05 04:09:08 -07:00
|
|
|
|
2015-07-29 05:30:16 -07:00
|
|
|
for(n = 2; n != 0; n--)
|
2015-06-05 04:09:08 -07:00
|
|
|
{
|
|
|
|
switch(c)
|
|
|
|
{
|
|
|
|
case '0': i = i * 8 + 00; break;
|
|
|
|
case '1': i = i * 8 + 01; break;
|
|
|
|
case '2': i = i * 8 + 02; break;
|
|
|
|
case '3': i = i * 8 + 03; break;
|
|
|
|
case '4': i = i * 8 + 04; break;
|
|
|
|
case '5': i = i * 8 + 05; break;
|
|
|
|
case '6': i = i * 8 + 06; break;
|
|
|
|
case '7': i = i * 8 + 07; break;
|
|
|
|
default:
|
2015-06-06 09:47:13 -07:00
|
|
|
ungetc(c, parseFile);
|
2015-06-05 04:09:08 -07:00
|
|
|
str[pos] = i;
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2015-06-06 09:47:13 -07:00
|
|
|
c = fgetc(parseFile);
|
2015-06-05 04:09:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
str[pos] = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
2015-06-05 10:38:34 -07:00
|
|
|
default:
|
2015-07-29 04:59:25 -07:00
|
|
|
LT_Assert(LT_TRUE, "LT_Escaper: Unknown escape character '%c'", escape);
|
2015-06-05 10:38:34 -07:00
|
|
|
break;
|
2015-06-05 04:09:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
LT_Token LT_GetToken()
|
|
|
|
{
|
|
|
|
LT_Token tk = { 0 };
|
2015-06-06 09:47:13 -07:00
|
|
|
int c = fgetc(parseFile);
|
2015-06-05 04:09:08 -07:00
|
|
|
|
2015-06-06 09:47:13 -07:00
|
|
|
if(c == EOF)
|
2015-06-05 04:09:08 -07:00
|
|
|
{
|
2015-06-05 10:38:34 -07:00
|
|
|
tk.token = LT_TkNames[TOK_EOF];
|
2015-06-05 09:44:24 -07:00
|
|
|
tk.pos = ftell(parseFile);
|
2015-06-05 04:09:08 -07:00
|
|
|
return tk;
|
|
|
|
}
|
|
|
|
|
|
|
|
while(isspace(c) && c != '\n')
|
|
|
|
{
|
2015-06-06 09:47:13 -07:00
|
|
|
c = fgetc(parseFile);
|
2015-06-05 04:09:08 -07:00
|
|
|
|
2015-06-06 09:47:13 -07:00
|
|
|
if(c == EOF) // [marrub] This could have caused issues if there was whitespace before EOF.
|
2015-06-05 04:09:08 -07:00
|
|
|
{
|
2015-06-05 10:38:34 -07:00
|
|
|
tk.token = LT_TkNames[TOK_EOF];
|
2015-06-05 09:44:24 -07:00
|
|
|
tk.pos = ftell(parseFile);
|
2015-06-05 04:09:08 -07:00
|
|
|
return tk;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-05 09:44:24 -07:00
|
|
|
tk.pos = ftell(parseFile);
|
2015-06-05 04:09:08 -07:00
|
|
|
|
|
|
|
switch(c)
|
|
|
|
{
|
2015-06-06 07:42:26 -07:00
|
|
|
case '$': tk.token = LT_TkNames[TOK_Sigil]; return tk;
|
|
|
|
case '#': tk.token = LT_TkNames[TOK_Hash]; return tk;
|
|
|
|
case '.': tk.token = LT_TkNames[TOK_Period]; return tk;
|
2015-06-05 10:38:34 -07:00
|
|
|
case ':': tk.token = LT_TkNames[TOK_Colon]; return tk;
|
2015-06-07 05:02:33 -07:00
|
|
|
case ';': tk.token = LT_TkNames[TOK_Semicl]; return tk;
|
2015-06-05 10:38:34 -07:00
|
|
|
case ',': tk.token = LT_TkNames[TOK_Comma]; return tk;
|
|
|
|
case '%': tk.token = LT_TkNames[TOK_Mod]; return tk;
|
|
|
|
case '?': tk.token = LT_TkNames[TOK_Query]; return tk;
|
|
|
|
case '{': tk.token = LT_TkNames[TOK_BraceO]; return tk;
|
|
|
|
case '}': tk.token = LT_TkNames[TOK_BraceC]; return tk;
|
|
|
|
case '[': tk.token = LT_TkNames[TOK_BrackO]; return tk;
|
|
|
|
case ']': tk.token = LT_TkNames[TOK_BrackC]; return tk;
|
|
|
|
case '(': tk.token = LT_TkNames[TOK_ParenO]; return tk;
|
|
|
|
case ')': tk.token = LT_TkNames[TOK_ParenC]; return tk;
|
|
|
|
case '\n': tk.token = LT_TkNames[TOK_LnEnd]; return tk;
|
2015-06-05 04:09:08 -07:00
|
|
|
|
|
|
|
// [marrub] Sorry, I wouldn't normally do a quick and dirty hack like this,
|
|
|
|
// but sometimes I really do care about my sanity. And wrists.
|
|
|
|
#define DoubleTokDef(ch, t1, t2) \
|
|
|
|
case ch: \
|
2015-06-06 09:47:13 -07:00
|
|
|
c = fgetc(parseFile); \
|
2015-06-05 04:09:08 -07:00
|
|
|
\
|
|
|
|
if(c == ch) \
|
|
|
|
{ \
|
2015-06-05 10:38:34 -07:00
|
|
|
tk.token = LT_TkNames[t2]; \
|
2015-06-05 04:09:08 -07:00
|
|
|
} \
|
|
|
|
else \
|
|
|
|
{ \
|
2015-06-05 10:38:34 -07:00
|
|
|
tk.token = LT_TkNames[t1]; \
|
2015-06-06 09:47:13 -07:00
|
|
|
ungetc(c, parseFile); \
|
2015-06-05 04:09:08 -07:00
|
|
|
} \
|
|
|
|
\
|
|
|
|
return tk;
|
|
|
|
|
|
|
|
DoubleTokDef('&', TOK_And, TOK_And2);
|
|
|
|
DoubleTokDef('=', TOK_Equal, TOK_CmpEQ);
|
|
|
|
DoubleTokDef('^', TOK_OrX, TOK_OrX2);
|
|
|
|
DoubleTokDef('|', TOK_OrI, TOK_OrI2);
|
|
|
|
|
|
|
|
#undef DoubleTokDef
|
|
|
|
|
|
|
|
// [marrub] Special god damn snowflakes
|
|
|
|
case '>':
|
2015-06-06 09:47:13 -07:00
|
|
|
c = fgetc(parseFile);
|
2015-06-05 04:09:08 -07:00
|
|
|
|
|
|
|
if(c == '=')
|
|
|
|
{
|
2015-06-05 10:38:34 -07:00
|
|
|
tk.token = LT_TkNames[TOK_CmpGE];
|
2015-06-05 04:09:08 -07:00
|
|
|
}
|
|
|
|
else if(c == '>')
|
|
|
|
{
|
2015-06-05 10:38:34 -07:00
|
|
|
tk.token = LT_TkNames[TOK_ShR];
|
2015-06-05 04:09:08 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-06-05 10:38:34 -07:00
|
|
|
tk.token = LT_TkNames[TOK_CmpGT];
|
2015-06-06 09:47:13 -07:00
|
|
|
ungetc(c, parseFile);
|
2015-06-05 04:09:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return tk;
|
|
|
|
case '<':
|
2015-06-06 09:47:13 -07:00
|
|
|
c = fgetc(parseFile);
|
2015-06-05 04:09:08 -07:00
|
|
|
|
|
|
|
if(c == '=')
|
|
|
|
{
|
2015-06-05 10:38:34 -07:00
|
|
|
tk.token = LT_TkNames[TOK_CmpLE];
|
2015-06-05 04:09:08 -07:00
|
|
|
}
|
|
|
|
else if(c == '<')
|
|
|
|
{
|
2015-06-05 10:38:34 -07:00
|
|
|
tk.token = LT_TkNames[TOK_ShL];
|
2015-06-05 04:09:08 -07:00
|
|
|
}
|
|
|
|
else if(c == '>')
|
|
|
|
{
|
2015-06-05 10:38:34 -07:00
|
|
|
tk.token = LT_TkNames[TOK_CmpNE];
|
2015-06-05 04:09:08 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-06-05 10:38:34 -07:00
|
|
|
tk.token = LT_TkNames[TOK_CmpLT];
|
2015-06-06 09:47:13 -07:00
|
|
|
ungetc(c, parseFile);
|
2015-06-05 04:09:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return tk;
|
|
|
|
case '!':
|
2015-06-06 09:47:13 -07:00
|
|
|
c = fgetc(parseFile);
|
2015-06-05 04:09:08 -07:00
|
|
|
|
|
|
|
if(c == '=')
|
|
|
|
{
|
2015-06-05 10:38:34 -07:00
|
|
|
tk.token = LT_TkNames[TOK_CmpNE];
|
2015-06-05 04:09:08 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-06-05 10:38:34 -07:00
|
|
|
tk.token = LT_TkNames[TOK_Not];
|
2015-06-06 09:47:13 -07:00
|
|
|
ungetc(c, parseFile);
|
2015-06-05 04:09:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return tk;
|
|
|
|
case '~':
|
2015-06-06 09:47:13 -07:00
|
|
|
c = fgetc(parseFile);
|
2015-06-05 04:09:08 -07:00
|
|
|
|
|
|
|
if(c == '=')
|
|
|
|
{
|
2015-06-05 10:38:34 -07:00
|
|
|
tk.token = LT_TkNames[TOK_CmpNE];
|
2015-06-05 04:09:08 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-06-06 09:47:13 -07:00
|
|
|
ungetc(c, parseFile);
|
2015-06-06 18:53:22 -07:00
|
|
|
tk.token = LT_TkNames[TOK_ChrSeq];
|
|
|
|
tk.string = LT_Alloc(2);
|
|
|
|
tk.string[0] = c;
|
|
|
|
tk.string[1] = '\0';
|
|
|
|
|
|
|
|
LT_SetGarbage(tk.string);
|
2015-06-05 04:09:08 -07:00
|
|
|
}
|
|
|
|
|
2015-06-06 07:42:26 -07:00
|
|
|
return tk;
|
|
|
|
// [zombie] extra tokens
|
|
|
|
case '/':
|
2015-06-06 09:47:13 -07:00
|
|
|
c = fgetc(parseFile);
|
2015-06-06 07:42:26 -07:00
|
|
|
|
|
|
|
if(c == '/')
|
|
|
|
{
|
|
|
|
tk.token = LT_TkNames[TOK_Comment];
|
|
|
|
}
|
|
|
|
else if(c == '*')
|
|
|
|
{
|
|
|
|
tk.token = LT_TkNames[TOK_BlkCmtO];
|
|
|
|
}
|
|
|
|
else if(c == '+')
|
|
|
|
{
|
|
|
|
tk.token = LT_TkNames[TOK_NstCmtO];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tk.token = LT_TkNames[TOK_Div];
|
2015-06-06 09:47:13 -07:00
|
|
|
ungetc(c, parseFile);
|
2015-06-06 07:42:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return tk;
|
|
|
|
case '*':
|
2015-06-06 09:47:13 -07:00
|
|
|
c = fgetc(parseFile);
|
2015-06-06 07:42:26 -07:00
|
|
|
|
|
|
|
if(c == '/')
|
|
|
|
{
|
|
|
|
tk.token = LT_TkNames[TOK_BlkCmtC];
|
|
|
|
}
|
|
|
|
else if(c == '*')
|
|
|
|
{
|
|
|
|
tk.token = LT_TkNames[TOK_Exp];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tk.token = LT_TkNames[TOK_Mul];
|
2015-06-06 09:47:13 -07:00
|
|
|
ungetc(c, parseFile);
|
2015-06-06 07:42:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return tk;
|
|
|
|
case '-':
|
2015-06-06 09:47:13 -07:00
|
|
|
c = fgetc(parseFile);
|
2015-06-06 07:42:26 -07:00
|
|
|
|
|
|
|
if(c == '-')
|
|
|
|
{
|
|
|
|
tk.token = LT_TkNames[TOK_Sub2];
|
|
|
|
}
|
|
|
|
else if (c == '>')
|
|
|
|
{
|
|
|
|
tk.token = LT_TkNames[TOK_Arrow];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tk.token = LT_TkNames[TOK_Sub];
|
2015-06-06 09:47:13 -07:00
|
|
|
ungetc(c, parseFile);
|
2015-06-06 07:42:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return tk;
|
|
|
|
case '+':
|
2015-06-06 09:47:13 -07:00
|
|
|
c = fgetc(parseFile);
|
2015-06-06 07:42:26 -07:00
|
|
|
|
|
|
|
if (c == '/')
|
|
|
|
{
|
|
|
|
tk.token = LT_TkNames[TOK_NstCmtC];
|
|
|
|
}
|
|
|
|
else if (c == '+')
|
|
|
|
{
|
|
|
|
tk.token = LT_TkNames[TOK_Add2];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tk.token = LT_TkNames[TOK_Add];
|
2015-06-06 09:47:13 -07:00
|
|
|
ungetc(c, parseFile);
|
2015-06-06 07:42:26 -07:00
|
|
|
}
|
|
|
|
|
2015-06-05 04:09:08 -07:00
|
|
|
return tk;
|
2015-06-06 07:13:54 -07:00
|
|
|
}
|
|
|
|
|
2015-06-06 19:30:15 -07:00
|
|
|
|
|
|
|
if(stringChars[0] != '\0')
|
2015-06-06 07:13:54 -07:00
|
|
|
{
|
2015-07-29 05:30:16 -07:00
|
|
|
unsigned i;
|
|
|
|
|
|
|
|
for(i = 0; i < 6;)
|
2015-06-05 04:09:08 -07:00
|
|
|
{
|
2015-06-06 19:30:15 -07:00
|
|
|
char cc = stringChars[i++];
|
|
|
|
|
|
|
|
if(cc == '\0')
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if(c == cc)
|
|
|
|
{
|
|
|
|
tk.token = LT_TkNames[TOK_String];
|
|
|
|
tk.string = LT_ReadString(c);
|
|
|
|
return tk;
|
|
|
|
}
|
2015-06-06 06:28:04 -07:00
|
|
|
}
|
2015-06-06 07:13:54 -07:00
|
|
|
}
|
|
|
|
|
2015-06-06 19:30:15 -07:00
|
|
|
if(charChars[0] != '\0')
|
2015-06-06 07:13:54 -07:00
|
|
|
{
|
2015-07-29 05:30:16 -07:00
|
|
|
unsigned i;
|
|
|
|
|
|
|
|
for(i = 0; i < 6;)
|
2015-06-05 04:09:08 -07:00
|
|
|
{
|
2015-06-06 19:30:15 -07:00
|
|
|
char cc = charChars[i++];
|
|
|
|
|
|
|
|
if(cc == '\0')
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if(c == cc)
|
|
|
|
{
|
|
|
|
tk.token = LT_TkNames[TOK_Charac];
|
|
|
|
tk.string = LT_ReadString(c);
|
|
|
|
return tk;
|
|
|
|
}
|
2015-06-05 04:09:08 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(isdigit(c))
|
|
|
|
{
|
2015-06-06 09:47:13 -07:00
|
|
|
ungetc(c, parseFile);
|
2015-06-05 04:09:08 -07:00
|
|
|
|
2015-06-05 10:38:34 -07:00
|
|
|
tk.token = LT_TkNames[TOK_Number];
|
2015-06-06 19:30:15 -07:00
|
|
|
tk.string = LT_ReadNumber();
|
2015-06-05 04:09:08 -07:00
|
|
|
return tk;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(isalpha(c) || c == '_')
|
|
|
|
{
|
2015-06-06 09:47:13 -07:00
|
|
|
size_t i = 0, strBlocks = 1;
|
|
|
|
char *str = LT_Alloc(TOKEN_STR_BLOCK_LENGTH);
|
2015-06-05 04:09:08 -07:00
|
|
|
|
2015-06-06 09:47:13 -07:00
|
|
|
while(c != EOF && (isalnum(c) || c == '_'))
|
2015-06-05 04:09:08 -07:00
|
|
|
{
|
2015-06-06 09:47:13 -07:00
|
|
|
if(i > (TOKEN_STR_BLOCK_LENGTH * strBlocks))
|
2015-06-05 04:09:08 -07:00
|
|
|
{
|
2015-06-06 09:47:13 -07:00
|
|
|
str = LT_ReAlloc(str, TOKEN_STR_BLOCK_LENGTH * ++strBlocks);
|
2015-06-05 04:09:08 -07:00
|
|
|
}
|
|
|
|
|
2015-06-05 08:14:35 -07:00
|
|
|
str[i++] = c;
|
|
|
|
|
2015-06-06 09:47:13 -07:00
|
|
|
c = fgetc(parseFile);
|
2015-06-05 04:09:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
str[i++] = '\0'; // [marrub] Completely forgot this line earlier. Really screwed up everything.
|
|
|
|
|
2015-07-26 02:36:36 -07:00
|
|
|
#ifndef LT_NO_ICONV
|
2015-06-07 00:46:36 -07:00
|
|
|
if(cfg.doConvert)
|
2015-06-05 08:14:35 -07:00
|
|
|
{
|
|
|
|
LT_DoConvert(&str);
|
|
|
|
}
|
2015-06-11 06:42:36 -07:00
|
|
|
#endif
|
2015-06-05 08:14:35 -07:00
|
|
|
|
2015-06-06 09:47:13 -07:00
|
|
|
ungetc(c, parseFile);
|
2015-06-05 04:09:08 -07:00
|
|
|
|
2015-06-05 10:38:34 -07:00
|
|
|
tk.token = LT_TkNames[TOK_Identi];
|
2015-06-06 19:30:15 -07:00
|
|
|
tk.string = LT_SetGarbage(LT_ReAlloc(str, i));
|
2015-06-05 04:09:08 -07:00
|
|
|
return tk;
|
|
|
|
}
|
|
|
|
|
2015-06-06 19:30:15 -07:00
|
|
|
tk.token = LT_TkNames[TOK_ChrSeq];
|
2015-06-06 09:47:13 -07:00
|
|
|
tk.string = LT_Alloc(2);
|
2015-06-05 08:14:35 -07:00
|
|
|
tk.string[0] = c;
|
|
|
|
tk.string[1] = '\0';
|
|
|
|
|
2015-06-06 18:53:22 -07:00
|
|
|
LT_SetGarbage(tk.string);
|
2015-06-05 08:14:35 -07:00
|
|
|
|
2015-06-05 04:09:08 -07:00
|
|
|
return tk;
|
|
|
|
}
|
|
|
|
|
2015-06-09 15:43:36 -07:00
|
|
|
void LT_SkipWhite()
|
|
|
|
{
|
|
|
|
char c = fgetc(parseFile);
|
|
|
|
|
|
|
|
while(isspace(c) && c != EOF)
|
|
|
|
{
|
|
|
|
c = fgetc(parseFile);
|
|
|
|
}
|
|
|
|
|
|
|
|
ungetc(c, parseFile);
|
|
|
|
}
|