💾 Archived View for gemini.conman.org › extensions › port70 › handlers › blog › html.c captured on 2021-12-03 at 14:04:38.

View Raw

More Information

⬅️ Previous capture (2020-11-01)

➡️ Next capture (2021-12-17)

🚧 View Differences

-=-=-=-=-=-=-

/************************************************************************


#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <ctype.h>
#include <limits.h>

#include <lua.h>
#include <lauxlib.h>

#if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 503
#  error You need to compile against Lua 5.3 or higher
#endif

/**************************************************************************/

enum
{
  UPV_ENTITY = 1,
  UPV_UTF8   = 2,
};

struct _yycontext;

static int  readchars   (struct _yycontext *,char *,size_t);
static void push_string (struct _yycontext *,char const *,size_t);
static void tagi        (struct _yycontext *,char const *);
static void tagb        (struct _yycontext *,char const *);
static void endtag      (struct _yycontext *);
static void setfield    (struct _yycontext *,char const *);
static void deentifyn   (struct _yycontext *,char const *,int);
static void deentify    (struct _yycontext *,char const *);

#define YY_CTX_LOCAL
#define YY_PARSE(T) static T
#define YY_CTX_MEMBERS  \
  size_t       len;     \
  char const  *buffer;  \
  lua_State   *L;       \
  luaL_Buffer  buf;     \
  bool         pre;
#define YY_INPUT(yy,buf,result,max) result = readchars(yy,buf,max)

#include "html.i"

/**************************************************************************/

static int readchars(yycontext *yy,char *dest,size_t dlen)
{
  size_t xfer;
  
  if (dlen > INT_MAX)
    dlen = INT_MAX;
    
  xfer = dlen < yy->len ? dlen : yy->len;
  
  memcpy(dest,yy->buffer,xfer);
  yy->len    -= xfer;
  yy->buffer += xfer;
  
  return (int)xfer;  
}

/**************************************************************************/

static void tagi(yycontext *yy,char const *tag)
{
  lua_createtable(yy->L,0,0);
  lua_pushstring(yy->L,tag);
  lua_setfield(yy->L,-2,"tag");
  lua_pushboolean(yy->L,true);
  lua_setfield(yy->L,-2,"inline");
  lua_createtable(yy->L,0,0);
  lua_setfield(yy->L,-2,"attributes");
}

/**************************************************************************/

static void tagb(yycontext *yy,char const *tag)
{
  lua_createtable(yy->L,0,0);
  lua_pushstring(yy->L,tag);
  lua_setfield(yy->L,-2,"tag");
  lua_pushboolean(yy->L,true);
  lua_setfield(yy->L,-2,"block");
  lua_createtable(yy->L,0,0);
  lua_setfield(yy->L,-2,"attributes");
}

/**************************************************************************/

static void endtag(yycontext *yy)
{
  lua_pushinteger(yy->L,luaL_len(yy->L,-2) + 1);
  lua_insert(yy->L,-2);
  lua_settable(yy->L,-3);
}

/**************************************************************************/

static void setfield(yycontext *yy,char const *name)
{
  lua_pushstring(yy->L,name);
  lua_insert(yy->L,-2);
  lua_getfield(yy->L,-3,"attributes");
  lua_insert(yy->L,-3);
  lua_settable(yy->L,-3);
  lua_pop(yy->L,1);
}

/**************************************************************************/

static void deentifyn(yycontext *yy,char const *num,int base)
{
  size_t       len;
  char const  *s;
  lua_Integer  v = strtoul(num,NULL,base);
  
  lua_getfield(yy->L,lua_upvalueindex(UPV_UTF8),"char");
  lua_pushinteger(yy->L,v);
  lua_call(yy->L,1,1);
  luaL_addvalue(&yy->buf);
}

/**************************************************************************/

static void deentify(yycontext *yy,char const *label)
{
  char const *entity;
  size_t      len;
  
  lua_getfield(yy->L,lua_upvalueindex(UPV_ENTITY),label);
  luaL_addvalue(&yy->buf);
}

/**************************************************************************/

static int parse(lua_State *L)
{
  yycontext yyctx;
  int       rc;
  
  lua_settop(L,1);
  lua_createtable(L,0,0);
  
  memset(&yyctx,0,sizeof(yyctx));
  yyctx.buffer = luaL_checklstring(L,1,&yyctx.len);
  yyctx.L      = L;
  rc           = yyparse(&yyctx);
  yyrelease(&yyctx);
  
  if (rc == 0)
    lua_pushnil(L);
  return 1;
}

/**************************************************************************/

int luaopen_org_conman_app_port70_handlers_blog_html(lua_State *L)
{
  lua_getglobal(L,"require");
  lua_pushliteral(L,"org.conman.const.entity");
  lua_call(L,1,1);
  
  lua_getglobal(L,"require");
  lua_pushliteral(L,"utf8");
  lua_call(L,1,1);
  
  lua_pushcclosure(L,parse,2);
  return 1;
}