1
0
Fork 0
LithOS3 is a development library for ZDoom designed to provide an in-game graphical user interface and OS-like capabilities.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

223 lines
4.7 KiB

//-----------------------------------------------------------------------------
//
// Copyright © 2016-2017 Project Golan, David Hill
//
// Code by David Hill has been relicensed with consent.
//
// See "LICENSE.lithos3" for more information.
//
//-----------------------------------------------------------------------------
//
// Token stream.
//
//-----------------------------------------------------------------------------
#include "Lth_libinfo.h"
#if !LITHOS3_NO_TOKENSTREAM
#define _GNU_SOURCE
#include "Lth.h"
// Static Functions ----------------------------------------------------------|
static int Lth_TokenFileStream_getc(struct Lth_TokenStreamBuf *cookie);
static int Lth_TokenFileStream_bumpc(struct Lth_TokenStreamBuf *cookie);
// Type Definitions ----------------------------------------------------------|
//
// Lth_TokenStreamBuf
//
typedef struct Lth_TokenStreamBuf
{
char *beg, *itr, *end;
size_t len;
__prop getc {call: Lth_TokenFileStream_getc(this)}
__prop bumpc {call: Lth_TokenFileStream_bumpc(this)}
} Lth_TokenStreamBuf;
// Static Functions ----------------------------------------------------------|
//
// Lth_TokenFileStream_getc
//
static int Lth_TokenFileStream_getc(Lth_TokenStreamBuf *cookie)
{
if(cookie->itr == cookie->end) return EOF;
return *cookie->itr;
}
//
// Lth_TokenFileStream_bumpc
//
static int Lth_TokenFileStream_bumpc(Lth_TokenStreamBuf *cookie)
{
if(cookie->itr == cookie->end) return EOF;
return *cookie->itr++;
}
//
// Lth_TokenFileStream_read
//
static ssize_t Lth_TokenFileStream_read(void *cookie_, char *buf, size_t size)
{
Lth_TokenStreamBuf *cookie = cookie_;
size_t avail = cookie->end - cookie->itr;
if(size > avail)
size = avail;
if(size == 0) return 0;
for(ssize_t i = 0; i < size;)
{
if(cookie->getc() == '/')
{
cookie->bumpc();
if(cookie->getc() == '*')
{
for(cookie->bumpc(); !(cookie->bumpc() == '*' && cookie->bumpc() == '/');)
if(cookie->getc() == EOF)
return i;
buf[i++] = ' ';
}
else if(cookie->getc() == '/')
{
do if(cookie->bumpc() == EOF) return i;
while(cookie->getc() != '\n');
buf[i++] = ' ';
}
else
buf[i++] = '/';
}
else if(cookie->getc() == EOF)
return i;
else
buf[i++] = cookie->bumpc();
}
return size;
}
//
// Lth_TokenFileStream_close
//
static int Lth_TokenFileStream_close(void *cookie)
{
free(cookie);
return 0;
}
//
// Lth_TokenFileStreamOpen
//
static FILE *Lth_TokenFileStreamOpen(void *data, size_t size)
{
cookie_io_functions_t io_funcs = {
.read = Lth_TokenFileStream_read,
.write = NULL,
.seek = NULL,
.close = Lth_TokenFileStream_close
};
Lth_TokenStreamBuf *cookie = calloc(1, sizeof(Lth_TokenStreamBuf));
cookie->beg = data;
cookie->itr = data;
cookie->end = cookie->beg + size;
return fopencookie(cookie, "r", io_funcs);
}
//
// Lth_TokenStreamGrab
//
static void Lth_TokenStreamGrab(Lth_TokenStream *stream)
{
if(feof(stream->fp)) return;
do Lth_TokenGet(stream->fp, &stream->tokbuf);
while((stream->skipspc && stream->tokbuf.type == Lth_TOK_Space) ||
(stream->skipeol && stream->tokbuf.type == Lth_TOK_LnEnd));
stream->filled = true;
}
// Extern Functions ----------------------------------------------------------|
//
// Lth_TokenStreamOpen
//
Lth_TokenStream *Lth_TokenStreamOpen(void *data, size_t size)
{
Lth_TokenStream *stream = calloc(1, sizeof(Lth_TokenStream));
stream->fp = Lth_TokenFileStreamOpen(data, size);
if(stream->fp == NULL)
{
free(stream);
return NULL;
}
stream->skipeol = stream->skipspc = true;
return stream;
}
//
// Lth_TokenStreamClose
//
void Lth_TokenStreamClose(Lth_TokenStream *stream)
{
if(stream == NULL) return;
Lth_TokenCleanup(stream->tokbuf);
fclose(stream->fp);
free(stream);
}
//
// Lth_TokenStreamBump
//
Lth_Token const *Lth_TokenStreamBump(Lth_TokenStream *stream)
{
Lth_Token const *tok = Lth_TokenStreamPeek(stream);
return stream->filled = false, tok;
}
//
// Lth_TokenStreamPeek
//
Lth_Token const *Lth_TokenStreamPeek(Lth_TokenStream *stream)
{
static Lth_Token const eof = { .type = Lth_TOK_EOF };
if(!stream->filled && (Lth_TokenStreamGrab(stream), !stream->filled))
return &eof;
return &stream->tokbuf;
}
//
// Lth_TokenStreamDrop
//
bool Lth_TokenStreamDrop(Lth_TokenStream *stream, Lth_TokenType tt)
{
Lth_Token const *tok = Lth_TokenStreamPeek(stream);
if(tok->type == tt)
return Lth_TokenStreamBump(stream), true;
return false;
}
#endif//LITHOS3_NO_TOKENSTREAM