#include #include #include #include #include #include #include "honeysuckle.h" #include "md4c-html.h" #include "bindings.h" #include "logging.h" struct concat_buffer { char *buf; size_t size; int index; bool ok; }; static void md_callback(const MD_CHAR *html, MD_SIZE size, void *data) { argent_log(TRACE, "begin md_callback()"); struct concat_buffer *d = data; if (!d->ok) return; if (d->index + size >= d->size) { char *new_buf = realloc(d->buf, d->size * 2); if (new_buf == NULL) { // failed to allocate memory, abort! argent_log(WARN, "failed to properly allocate memory for html buffer!"); d->ok = false; return; } d->buf = new_buf; d->size *= 2; } memcpy((d->buf) + d->index, html, size); d->index += size; argent_log(TRACE, "finish md_callback()"); } int markdown(lua_State *L) { argent_log(DEBUG, "begin markdown parsing"); char *markdown_buffer; hs_parse_args(L, hs_str(markdown_buffer)); size_t len = strlen(markdown_buffer); argent_log(TRACE, "markdown input (%ld bytes): %s", len, markdown_buffer); unsigned int md_flags = MD_FLAG_TABLES | MD_FLAG_STRIKETHROUGH | MD_FLAG_UNDERLINE; struct concat_buffer data; data.buf = malloc(128 * sizeof(char)); data.size = 128 * sizeof(char); data.index = 0; data.ok = true; argent_log(TRACE, "call md_html()"); // fill out the buffer int error = md_html(markdown_buffer, len, md_callback, &data, md_flags, 0); if (error) hs_throw_error(L, "markdown parsing failed!"); if (data.ok == false) hs_throw_error(L, "encountered error (re)allocating html buffer memory!"); data.buf[data.index] = 0; argent_log(TRACE, "finished HTML buffer (%d bytes, %d chars): %s", data.size, data.index, data.buf); lua_pushstring(L, data.buf); free(data.buf); argent_log(DEBUG, "finish markdown parsing"); return 1; } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ static void throw_directory_error(lua_State *L, char *dir_name); static struct dirent *read_dir(lua_State *L, DIR *directory); int scan_directory(lua_State *L) { argent_log(DEBUG, "begin scan_directory()"); char *dir_name; hs_parse_args(L, hs_str(dir_name)); DIR *directory = opendir(dir_name); if (directory == NULL) throw_directory_error(L, dir_name); lua_newtable(L); int directory_table = lua_gettop(L); int directory_index = 1; lua_newtable(L); int file_table = lua_gettop(L); int file_index = 1; struct dirent *entry; while ((entry = read_dir(L, directory)) != NULL) { lua_pushstring(L, entry->d_name); if (entry->d_type == DT_DIR) { lua_rawseti(L, directory_table, directory_index); directory_index += 1; } else { lua_rawseti(L, file_table, file_index); file_index += 1; } } closedir(directory); argent_log(DEBUG, "end scan_directory()"); return 2; } static void throw_directory_error(lua_State *L, char *dir_name) { argent_log(ERROR, "failed to open directory: %d\n", errno); switch(errno) { case EACCES: hs_throw_error(L, "read %s: permission denied", dir_name); break; case EMFILE: hs_throw_error(L, "read %s: this process has too many open files", dir_name); break; case ENFILE: hs_throw_error(L, "read %s: this file system cannot support any more open files", dir_name); break; case ENOMEM: hs_throw_error(L, "read %s: Not enough memory", dir_name); break; default: hs_throw_error(L, "read %s: unknown error", dir_name); break; } } static struct dirent *read_dir(lua_State *L, DIR *directory) { // can't tell if a NULL was EOF or error without this errno = 0; struct dirent *entry = readdir(directory); if (entry == NULL && errno != 0) { argent_log(ERROR, "attempted to read invalid dirstream"); closedir(directory); hs_throw_error(L, "attempted to read invalid dirstream"); } return entry; }