| rev | 
   line source | 
| 
jbe/bsw@0
 | 
     1 #include <lua.h>
 | 
| 
jbe/bsw@0
 | 
     2 #include <lauxlib.h>
 | 
| 
jbe/bsw@0
 | 
     3 #include <stdlib.h>
 | 
| 
jbe/bsw@0
 | 
     4 #include <string.h>
 | 
| 
jbe/bsw@0
 | 
     5 
 | 
| 
jbe/bsw@0
 | 
     6 static int webmcp_encode_html(lua_State *L) {
 | 
| 
jbe/bsw@0
 | 
     7   const char *input;
 | 
| 
jbe/bsw@0
 | 
     8   size_t input_len;
 | 
| 
jbe/bsw@0
 | 
     9   size_t i;
 | 
| 
jbe/bsw@0
 | 
    10   luaL_Buffer buf;
 | 
| 
jbe/bsw@0
 | 
    11   input = luaL_checklstring(L, 1, &input_len);
 | 
| 
jbe/bsw@0
 | 
    12   for (i=0; i<input_len; i++) {
 | 
| 
jbe/bsw@0
 | 
    13     char c = input[i];
 | 
| 
jbe/bsw@0
 | 
    14     if ((c == '<') || (c == '>') || (c == '&') || (c == '"')) break;
 | 
| 
jbe/bsw@0
 | 
    15   }
 | 
| 
jbe/bsw@0
 | 
    16   if (i == input_len) {
 | 
| 
jbe/bsw@0
 | 
    17     lua_settop(L, 1);
 | 
| 
jbe/bsw@0
 | 
    18     return 1;
 | 
| 
jbe/bsw@0
 | 
    19   }
 | 
| 
jbe/bsw@0
 | 
    20   luaL_buffinit(L, &buf);
 | 
| 
jbe/bsw@0
 | 
    21   for (i=0; i<input_len; i++) {
 | 
| 
jbe/bsw@0
 | 
    22     char c;
 | 
| 
jbe/bsw@0
 | 
    23     size_t j = i;
 | 
| 
jbe/bsw@0
 | 
    24     do {
 | 
| 
jbe/bsw@0
 | 
    25       c = input[j];
 | 
| 
jbe/bsw@0
 | 
    26       if ((c == '<') || (c == '>') || (c == '&') || (c == '"')) break;
 | 
| 
jbe/bsw@0
 | 
    27       else j++;
 | 
| 
jbe/bsw@0
 | 
    28     } while (j<input_len);
 | 
| 
jbe/bsw@0
 | 
    29     if (j != i) {
 | 
| 
jbe/bsw@0
 | 
    30       luaL_addlstring(&buf, input+i, j-i);
 | 
| 
jbe/bsw@0
 | 
    31       i = j;
 | 
| 
jbe/bsw@0
 | 
    32     }
 | 
| 
jbe/bsw@0
 | 
    33     if (i<input_len) {
 | 
| 
jbe/bsw@0
 | 
    34       if      (c == '<') luaL_addstring(&buf, "<");
 | 
| 
jbe/bsw@0
 | 
    35       else if (c == '>') luaL_addstring(&buf, ">");
 | 
| 
jbe/bsw@0
 | 
    36       else if (c == '&') luaL_addstring(&buf, "&");
 | 
| 
jbe/bsw@0
 | 
    37       else if (c == '"') luaL_addstring(&buf, """);
 | 
| 
jbe/bsw@0
 | 
    38       else abort();  // should not happen
 | 
| 
jbe/bsw@0
 | 
    39     }
 | 
| 
jbe/bsw@0
 | 
    40   }
 | 
| 
jbe/bsw@0
 | 
    41   luaL_pushresult(&buf);
 | 
| 
jbe/bsw@0
 | 
    42   return 1;
 | 
| 
jbe/bsw@0
 | 
    43 }
 | 
| 
jbe/bsw@0
 | 
    44 
 | 
| 
jbe/bsw@0
 | 
    45 static int webmcp_slot_put_into(lua_State *L) {
 | 
| 
jbe/bsw@0
 | 
    46   int argc;
 | 
| 
jbe/bsw@0
 | 
    47   int i;
 | 
| 
jbe/bsw@0
 | 
    48   int j;
 | 
| 
jbe/bsw@0
 | 
    49   luaL_checkany(L, 1);
 | 
| 
jbe/bsw@0
 | 
    50   argc = lua_gettop(L);
 | 
| 
jbe/bsw@0
 | 
    51   lua_getglobal(L, "slot");
 | 
| 
jbe/bsw@0
 | 
    52   lua_getfield(L, -1, "_data");
 | 
| 
jbe/bsw@0
 | 
    53   lua_pushvalue(L, 1);
 | 
| 
jbe/bsw@0
 | 
    54   lua_gettable(L, -2);  // get table by reference passed as 1st argument
 | 
| 
jbe/bsw@0
 | 
    55   lua_getfield(L, -1, "string_fragments");
 | 
| 
jbe@64
 | 
    56   j = lua_rawlen(L, -1);
 | 
| 
jbe/bsw@0
 | 
    57   for (i=2; i<=argc; i++) {
 | 
| 
jbe/bsw@0
 | 
    58     lua_pushvalue(L, i);
 | 
| 
jbe/bsw@0
 | 
    59     lua_rawseti(L, -2, ++j);
 | 
| 
jbe/bsw@0
 | 
    60   }
 | 
| 
jbe/bsw@0
 | 
    61   return 0;
 | 
| 
jbe/bsw@0
 | 
    62 }
 | 
| 
jbe/bsw@0
 | 
    63 
 | 
| 
jbe/bsw@0
 | 
    64 static int webmcp_slot_put(lua_State *L) {
 | 
| 
jbe/bsw@0
 | 
    65   int argc;
 | 
| 
jbe/bsw@0
 | 
    66   int i;
 | 
| 
jbe/bsw@0
 | 
    67   int j;
 | 
| 
jbe/bsw@0
 | 
    68   argc = lua_gettop(L);
 | 
| 
jbe/bsw@0
 | 
    69   lua_getglobal(L, "slot");
 | 
| 
jbe/bsw@0
 | 
    70   lua_getfield(L, -1, "_data");
 | 
| 
jbe/bsw@0
 | 
    71   lua_getfield(L, -2, "_active_slot");
 | 
| 
jbe/bsw@0
 | 
    72   lua_gettable(L, -2);
 | 
| 
jbe/bsw@0
 | 
    73   lua_getfield(L, -1, "string_fragments");
 | 
| 
jbe@64
 | 
    74   j = lua_rawlen(L, -1);
 | 
| 
jbe/bsw@0
 | 
    75   for (i=1; i<=argc; i++) {
 | 
| 
jbe/bsw@0
 | 
    76     lua_pushvalue(L, i);
 | 
| 
jbe/bsw@0
 | 
    77     lua_rawseti(L, -2, ++j);
 | 
| 
jbe/bsw@0
 | 
    78   }
 | 
| 
jbe/bsw@0
 | 
    79   return 0;
 | 
| 
jbe/bsw@0
 | 
    80 }
 | 
| 
jbe/bsw@0
 | 
    81 
 | 
| 
jbe/bsw@0
 | 
    82 static int webmcp_ui_tag(lua_State *L) {
 | 
| 
jbe/bsw@0
 | 
    83   int tag_given = 0;
 | 
| 
jbe/bsw@0
 | 
    84   int j;
 | 
| 
jbe/bsw@0
 | 
    85   lua_settop(L, 1);
 | 
| 
jbe/bsw@0
 | 
    86   luaL_checktype(L, 1, LUA_TTABLE);
 | 
| 
jbe/bsw@0
 | 
    87   lua_getglobal(L, "slot");       // 2
 | 
| 
jbe/bsw@0
 | 
    88   lua_getfield(L, 2, "_data");    // 3
 | 
| 
jbe/bsw@0
 | 
    89   lua_getfield(L, 2, "_active_slot");
 | 
| 
jbe/bsw@0
 | 
    90   lua_gettable(L, 3);             // 4
 | 
| 
jbe/bsw@0
 | 
    91   lua_getfield(L, 4, "string_fragments");  // 5
 | 
| 
jbe/bsw@0
 | 
    92   lua_getfield(L, 1, "tag");      // 6
 | 
| 
jbe/bsw@0
 | 
    93   lua_getfield(L, 1, "attr");     // 7
 | 
| 
jbe/bsw@0
 | 
    94   lua_getfield(L, 1, "content");  // 8
 | 
| 
jbe/bsw@0
 | 
    95   if (lua_toboolean(L, 7) && !lua_istable(L, 7)) {
 | 
| 
jbe/bsw@0
 | 
    96     return luaL_error(L,
 | 
| 
jbe/bsw@0
 | 
    97       "\"attr\" argument for ui.tag{...} must be nil or a table."
 | 
| 
jbe/bsw@0
 | 
    98     );
 | 
| 
jbe/bsw@0
 | 
    99   }
 | 
| 
jbe/bsw@0
 | 
   100   if (lua_toboolean(L, 6)) {
 | 
| 
jbe/bsw@0
 | 
   101     tag_given = 1;
 | 
| 
jbe/bsw@0
 | 
   102   } else if (lua_toboolean(L, 7)) {
 | 
| 
jbe/bsw@0
 | 
   103     lua_pushnil(L);
 | 
| 
jbe/bsw@0
 | 
   104     if (lua_next(L, 7)) {
 | 
| 
jbe/bsw@0
 | 
   105       lua_pop(L, 2);
 | 
| 
jbe/bsw@0
 | 
   106       lua_pushliteral(L, "span");
 | 
| 
jbe/bsw@0
 | 
   107       lua_replace(L, 6);
 | 
| 
jbe/bsw@0
 | 
   108       tag_given = 1;
 | 
| 
jbe/bsw@0
 | 
   109     }
 | 
| 
jbe/bsw@0
 | 
   110   }
 | 
| 
jbe@64
 | 
   111   j = lua_rawlen(L, 5);
 | 
| 
jbe/bsw@0
 | 
   112   if (tag_given) {
 | 
| 
jbe/bsw@0
 | 
   113     lua_pushliteral(L, "<");
 | 
| 
jbe/bsw@0
 | 
   114     lua_rawseti(L, 5, ++j);
 | 
| 
jbe/bsw@0
 | 
   115     lua_pushvalue(L, 6);
 | 
| 
jbe/bsw@0
 | 
   116     lua_rawseti(L, 5, ++j);
 | 
| 
jbe/bsw@0
 | 
   117     if (lua_toboolean(L, 7)) {
 | 
| 
jbe/bsw@0
 | 
   118       for (lua_pushnil(L); lua_next(L, 7); lua_pop(L, 1)) {
 | 
| 
jbe/bsw@0
 | 
   119         // key at position 9
 | 
| 
jbe/bsw@0
 | 
   120         // value at position 10
 | 
| 
jbe/bsw@0
 | 
   121         lua_pushliteral(L, " ");
 | 
| 
jbe/bsw@0
 | 
   122         lua_rawseti(L, 5, ++j);
 | 
| 
jbe/bsw@0
 | 
   123         lua_pushvalue(L, 9);
 | 
| 
jbe/bsw@0
 | 
   124         lua_rawseti(L, 5, ++j);
 | 
| 
jbe/bsw@0
 | 
   125         lua_pushliteral(L, "=\"");
 | 
| 
jbe/bsw@0
 | 
   126         lua_rawseti(L, 5, ++j);
 | 
| 
jbe/bsw@0
 | 
   127         if (!strcmp(lua_tostring(L, 9), "class") && lua_istable(L, 10)) {  // NOTE: lua_tostring(...) is destructive, will cause errors for numeric keys
 | 
| 
jbe/bsw@0
 | 
   128           lua_getglobal(L, "table");  // 11
 | 
| 
jbe/bsw@0
 | 
   129           lua_getfield(L, 11, "concat");  // 12
 | 
| 
jbe/bsw@0
 | 
   130           lua_replace(L, 11);  // 11
 | 
| 
jbe/bsw@0
 | 
   131           lua_pushvalue(L, 10);  // 12
 | 
| 
jbe/bsw@0
 | 
   132           lua_pushliteral(L, " ");  // 13
 | 
| 
jbe/bsw@0
 | 
   133           lua_call(L, 2, 1);  // 11
 | 
| 
jbe/bsw@0
 | 
   134           lua_rawseti(L, 5, ++j);
 | 
| 
jbe/bsw@0
 | 
   135         } else {
 | 
| 
jbe/bsw@0
 | 
   136           lua_pushcfunction(L, webmcp_encode_html);
 | 
| 
jbe/bsw@0
 | 
   137           lua_pushvalue(L, 10);
 | 
| 
jbe/bsw@0
 | 
   138           lua_call(L, 1, 1);
 | 
| 
jbe/bsw@0
 | 
   139           lua_rawseti(L, 5, ++j);
 | 
| 
jbe/bsw@0
 | 
   140         }
 | 
| 
jbe/bsw@0
 | 
   141         lua_pushliteral(L, "\"");
 | 
| 
jbe/bsw@0
 | 
   142         lua_rawseti(L, 5, ++j);
 | 
| 
jbe/bsw@0
 | 
   143       }
 | 
| 
jbe/bsw@0
 | 
   144     }
 | 
| 
jbe/bsw@0
 | 
   145   }
 | 
| 
jbe/bsw@0
 | 
   146   if (lua_toboolean(L, 8)) {
 | 
| 
jbe/bsw@0
 | 
   147     if (tag_given) {
 | 
| 
jbe/bsw@0
 | 
   148       lua_pushliteral(L, ">");
 | 
| 
jbe/bsw@0
 | 
   149       lua_rawseti(L, 5, ++j);
 | 
| 
jbe/bsw@0
 | 
   150     }
 | 
| 
jbe/bsw@0
 | 
   151     if (lua_isfunction(L, 8)) {
 | 
| 
jbe/bsw@0
 | 
   152       // content function should be on last stack position 8
 | 
| 
jbe/bsw@0
 | 
   153       lua_call(L, 0, 0);
 | 
| 
jbe/bsw@0
 | 
   154       // stack is now at position 7, but we don't care
 | 
| 
jbe/bsw@0
 | 
   155       // we assume that the active slot hasn't been exchanged or resetted
 | 
| 
jbe@64
 | 
   156       j = lua_rawlen(L, 5);  // but it may include more elements now
 | 
| 
jbe/bsw@0
 | 
   157     } else {
 | 
| 
jbe/bsw@0
 | 
   158       lua_pushcfunction(L, webmcp_encode_html);  // 9
 | 
| 
jbe/bsw@0
 | 
   159       lua_pushvalue(L, 8);  // 10
 | 
| 
jbe/bsw@0
 | 
   160       lua_call(L, 1, 1);  // 9
 | 
| 
jbe/bsw@0
 | 
   161       lua_rawseti(L, 5, ++j);
 | 
| 
jbe/bsw@0
 | 
   162     }
 | 
| 
jbe/bsw@0
 | 
   163     if (tag_given) {
 | 
| 
jbe/bsw@0
 | 
   164       lua_pushliteral(L, "</");
 | 
| 
jbe/bsw@0
 | 
   165       lua_rawseti(L, 5, ++j);
 | 
| 
jbe/bsw@0
 | 
   166       lua_pushvalue(L, 6);
 | 
| 
jbe/bsw@0
 | 
   167       lua_rawseti(L, 5, ++j);
 | 
| 
jbe/bsw@0
 | 
   168       lua_pushliteral(L, ">");
 | 
| 
jbe/bsw@0
 | 
   169       lua_rawseti(L, 5, ++j);
 | 
| 
jbe/bsw@0
 | 
   170     }
 | 
| 
jbe/bsw@0
 | 
   171   } else {
 | 
| 
jbe/bsw@0
 | 
   172     if (tag_given) {
 | 
| 
jbe/bsw@0
 | 
   173       lua_pushliteral(L, " />");
 | 
| 
jbe/bsw@0
 | 
   174       lua_rawseti(L, 5, ++j);
 | 
| 
jbe/bsw@0
 | 
   175     }
 | 
| 
jbe/bsw@0
 | 
   176   }
 | 
| 
jbe/bsw@0
 | 
   177   return 0;
 | 
| 
jbe/bsw@0
 | 
   178 }
 | 
| 
jbe/bsw@0
 | 
   179 
 | 
| 
jbe/bsw@0
 | 
   180 int luaopen_webmcp_accelerator(lua_State *L) {
 | 
| 
jbe/bsw@0
 | 
   181   lua_settop(L, 0);
 | 
| 
jbe/bsw@0
 | 
   182   lua_getglobal(L, "encode");  // 1
 | 
| 
jbe/bsw@0
 | 
   183   lua_pushcfunction(L, webmcp_encode_html);
 | 
| 
jbe/bsw@0
 | 
   184   lua_setfield(L, 1, "html");
 | 
| 
jbe/bsw@0
 | 
   185   lua_settop(L, 0);
 | 
| 
jbe/bsw@0
 | 
   186   lua_getglobal(L, "slot");  // 1
 | 
| 
jbe/bsw@0
 | 
   187   lua_pushcfunction(L, webmcp_slot_put_into);
 | 
| 
jbe/bsw@0
 | 
   188   lua_setfield(L, 1, "put_into");
 | 
| 
jbe/bsw@0
 | 
   189   lua_pushcfunction(L, webmcp_slot_put);
 | 
| 
jbe/bsw@0
 | 
   190   lua_setfield(L, 1, "put");
 | 
| 
jbe/bsw@0
 | 
   191   lua_settop(L, 0);
 | 
| 
jbe/bsw@0
 | 
   192   lua_getglobal(L, "ui");  // 1
 | 
| 
jbe/bsw@0
 | 
   193   lua_pushcfunction(L, webmcp_ui_tag);
 | 
| 
jbe/bsw@0
 | 
   194   lua_setfield(L, 1, "tag");
 | 
| 
jbe/bsw@0
 | 
   195   return 0;
 | 
| 
jbe/bsw@0
 | 
   196 }
 |