1
0
Fork 0
LithOS3/lithos_c/src/tokenstream.c

233 lines
5.0 KiB
C
Raw Normal View History

//-----------------------------------------------------------------------------
//
// Copyright © 2016 David P. Hill & Project Golan
//
// This file contains material copyrighted by David P. Hill, licensed under
// the same GPLv2 license as Project Golan's code.
//
// See "LICENSE" for more information.
//
// This file also contains material copyrighted by David P. Hill licensed
// under the Lesser GPL license.
//
// See "COPYLIB" for more information.
//
//-----------------------------------------------------------------------------
//
// Token stream.
//
//-----------------------------------------------------------------------------
#define _GNU_SOURCE
#include "Lth.h"
// Type Definitions ----------------------------------------------------------|
//
// Lth_TokenStreamBuf
//
typedef struct Lth_TokenStreamBuf
{
char *beg, *itr, *end;
size_t len;
int (*getc)(struct Lth_TokenStreamBuf *);
int (*bumpc)(struct Lth_TokenStreamBuf *);
} 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) == '/')
{
cookie->bumpc(cookie);
if(cookie->getc(cookie) == '*')
{
for(cookie->bumpc(cookie); !(cookie->bumpc(cookie) == '*' && cookie->getc(cookie) == '/');)
if(cookie->getc(cookie) == EOF)
return i;
buf[i++] = ' ';
continue;
}
else if(cookie->getc(cookie) == '/')
{
do if(cookie->bumpc(cookie) == EOF) return i;
while(cookie->getc(cookie) != '\n');
buf[i++] = ' ';
continue;
}
}
else if(cookie->getc(cookie) == EOF)
return i;
else
buf[i++] = cookie->bumpc(cookie);
}
return size;
}
//
// Lth_TokenFileStream_close
//
static int Lth_TokenFileStream_close(void *cookie_)
{
Lth_TokenStreamBuf *cookie = 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;
cookie->getc = Lth_TokenFileStream_getc;
cookie->bumpc = Lth_TokenFileStream_bumpc;
return fopencookie(cookie, "r", io_funcs);
}
//
// Lth_TokenGet_Script
//
Lth_ScriptCall static void Lth_TokenGet_Script(FILE *fp, Lth_Token *out)
{
Lth_TokenGet(fp, out);
}
//
// Lth_TokenStreamGrab
//
static void Lth_TokenStreamGrab(Lth_TokenStream *stream)
{
if(feof(stream->fp)) return;
bool scriptcall = stream->scriptcall;
do
if(!scriptcall) Lth_TokenGet(stream->fp, &stream->tokbuf);
else Lth_TokenGet_Script(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;
}
// EOF