/************************************************************************ * * Copyright 2020 by Sean Conner. All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * Comments, questions and criticisms can be sent to: sean@conman.org * *************************************************************************/ #include #include #include #include #include #include #include #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 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) { 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) { 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_mod_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; }