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.
222 lines
4.7 KiB
222 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
|
|
|