Mercurial > blahgd > fmt4
changeset 1157:3c363a43965a
Merge with v4.5
author | Josef 'Jeff' Sipek <jeffpc@josefsipek.net> |
---|---|
date | Sun, 30 Dec 2018 13:23:15 -0500 |
parents | c6906a7dbd8e (current diff) 9a70df4e78e9 (diff) |
children | 68a04057057e |
files | .gitmodules CMakeLists.txt ast.c daemon.c error.c iter.h parse.h pipeline.c post.c post_fmt3_cmds.c post_fmt4_ast.c ptree.c tag.c template.y utils.h |
diffstat | 46 files changed, 569 insertions(+), 634 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgsigs Sun Dec 30 13:23:15 2018 -0500 @@ -0,0 +1,5 @@ +9f2eb71d116d7b3accc7c87fea9b085b15aadde6 0 iQIcBAABCAAGBQJZlJQoAAoJEIPhJk8UI+I5UZAP/0DFwgQDPvM/Iw1lrhpaWyskb2uQ8x28AVGD2Mp0bdZgSs0s3FYR6h9g8cSUTJexlZyFo+sD97BwSbrg6x3wKuAVUR7RYOS0SA6nTuw1A8kQlThPEy5En1EnXPiBy9EfY6Y3UQmlJJhJ3OkaamQL0zWFpEZzviBnPYyb1VO1PmxwEkB60kdj+CBx5uOn65XREnFsDsEElmykI3U2+XwtK2/xqcRXubXmFk+JvaowdYseDy2lKpgdtEK7dGOZVWjAk7dk8EgSKwYUvGKoP/3vB7ZiBVGbfC0OsQfaghOIQT1IJvzPzMJIgHFrn+/LzKcRKd8u/gy8KXuEuX5XSs/z+I898phUn4u3EtIzI5+Azk3E7J8rUJYpFlHmbuelG0Ks7mkFak01+3Jfv7rvRpfzxVDsQqIFcriZzQdHaQJ+3cILic1Z1pwtryiGFwFCrZTz4Da3gOqhuKIpKZ5IWJKtzjZZtNPCptWA0fWhlDWQxJ/Lk2XCxcNwaBgJ141jcDZ/LGhnEuwZgi+AtJJqIMecDfWzpctk5x32n4zbncQVnPiS7ie94ZnmTvtgi9jRiOnFDCORv2WargMFwwYJddt99eawf8eWM3DF+yH8jVZyZnQ9N9VPWc6FIKvhqXFHZmJ0LIYPZXKCH8wEkDJps6WE+XY0arqQFFHJoMQNV3C2CmHy +d7ff619768d39bac25ff110ecf6224c2cdfd422a 0 iQIcBAABCAAGBQJZrYwwAAoJEIPhJk8UI+I5jDwP/0nxz1adoXvK5sHH1Xl8QyKculbipyf49mPMHNwMwot17ndARYrmYk135tkiUMv81nib5J/F5uvjR2GtNXTKeZLCDPW/hJDdK5TKLI+IKd2lPqG5/cCmO3d7c2OO9sqig6egMH2O/HU/ocg4Z+0/PbA2e0xR8KKY4i+MqmfU9xTeQq0J+jmTV61Uq+wesz9Bqn6aHr3iaDNi+qIz1AwQxG+D0GvNzKxBCncglA6M1ZQ1KGOWQlam8DUAUBK6YHqFxYXpEfpbDThEw8Et0MgAunomkcdDXHQl/PnVnyMkq9ug7ds/qzgCFb9pzimNLDjnLycuI0wCEe5CAFT8k4a33mbnvdYSmXgxHXXtUWjJawVY0cD6tInjtREqApISR43hodyh8KcFtrvj7M4A7npHTkHXXR0XIJYZmXEsFzH5EcIuSmdEcNvuNNc8KcJuWz9t3qbZZv7h+ZppXqPKwTa3QMCnCKayW1iPANXY4zBwI8GPllXmvBb9eJX7d3kUBUT8H2MALf2bGO842Ny/6CitzE3L4qFbmU53Fi1wXn7qtOX2G7iqn0Ly59hTz9zSGCkOZbWWIcYBAk5q1/bNfSKA7y8tejMeJDwle4Wk4hfbickmcHmYLnywe6/cxeXroBnhrsTpMLqRtpBv1NEfITT2mU+AIs7uH+lrTL8GdiE9FDFO +1dc65e2b39e75af9fc4f7a9c1e3517cff4666eea 0 iQIcBAABCAAGBQJaz35oAAoJEIPhJk8UI+I5v0wP/32WThLTsV6VwIeCwpirZmzGOHT4rKSxOjUh4meEKNQlT86EnvTZRkHlWe304ERRTvE6U58jnHweiK6c6XzbWndDGk2GfvFHUnO2PB+RGXXfNKnkgM2k1FtMcG/FHC51GcOQHCggsvT5LCMSMHu1BHxOvtUgs7GagPiJuK33AQl0GugAPWxH3PTQq2H2NpSWPEGIY1q355WYF0h7czTYULX4+JD3jf3gpJ//PTsr5NA/i7RdzM672RYSLi43gTj2/roY7KLOD9PfEb7QMrv9tz4juhjFewFEExyTC11STCy9ok+4HKGjwOO1dgkAqgJj2mM4dQfBUL+U7sHxenh25bpxCOXb2Ndr42t1hdIeZqB0ya8QHQcJZG9osFn7t/TV4bd6YTO5Km+HWE0GWBFzEcaiIoCTyxVto+c6Wo9zzIHA9yEkGCFdmNIENOtwbzpTSwuDXTct0EQMOELStF9IIGmc9G1NlGwWY0jxkrnk0kY8tjdbMSHFCXi5qj64s/Vv7pMfz2p4b1rXSHkcpsba6wJI3T8M8qHncje+whLLstm3ViCVkdCyVYtFEMxHoStcIVo1089SEtbfeEKiv2Lvlo4YmE+JhE3gxPZEcxrdR+Z3vo2WlAQ/gsjd6SPG7Vny1oK8GBUJo9sSxg4SRiySo6K88GNgS81qxA3r559PBfw4 +40e8a3bb0684652444e3090343af2a31ad98da63 0 iQIcBAABCAAGBQJbWMeLAAoJEIPhJk8UI+I51/AP/2fihCE0dV9UVmtHkoWHrYq+CWo/pvpNG8HI6vxLcEkuTtmKSsz9hHbdxsZG0VqnPPk//Mw4Yqo7nxWDpgbfTxexd4HggSmJgXjgNJgDj5VI2VV/6WhxRF1/B6U71+Ivo1raLCtVeb684Ol7upIQEDHx9voConUkIVn7UXAdB1U+Rsj9ZZ6N1ZiEzPcIP9JafSfR/csy29HQYL6z6oxPGZrsnPbm5C6AxsUSXEF/fE3PyAD1BCUsV31JhulPOwH3u5YLLXhrUzAu7gFiDOMJL/JfGPbO5YkbbGWMqQ3DGhdSmWrfncnrL+47M3rWC3kpWchC0atOvxGNYb5fIDb/aFO3CxYZlCS88NcJYNAzLLKBQuGEee8HTDQSYzyLTB1MJW/ip1vAm7wYY67nzUNusQbbbFYusm75pB20atsvWvT7U5vKihkFC78oeYsxVJuLIan/+7YD5Dgng3C+2XUqV07zov1riEgMl2rKdsU3HrTZWbCjBTn6WNKX9KysZqeeN/BK14HRwSdf4+wVR8Nm003WqkdDRBIPiasK9TNXlfz82u91nFdUwDQJNSOG5UA4MAghU9LhzNlEwXPHtNzKwB3nOf8wu1906Pc8txqcskO9P7EC8mpQoRQ9jxQiiPidLA65yqWQ08pgYof8T61DLGNbO83Q4skhW+NhjuHLdz5i +6435f2f8f9181c677db9fdfd42e60937b6966772 0 iQIzBAABCAAdFiEEZaFgAMhruIJk7gQkg+EmTxQj4jkFAlu5gaQACgkQg+EmTxQj4jm4BA//UYWxnyRf7mksZIuyOCosVYL2HC3NEUnbotN/5i6znjCwQbsQCfW/wiMyfXZ9oXJVZlhSH5mlwFVHLr5X49+7ajima26SubCowwN00+NVuduUQkQjV4g/AJxxOZXf6Nnj5zLkpBPk7XF2j9ZQRlYkwVhtz9vkQmamr3HYw6jHeCKwg6iokgxhvyNqjpjI1NM34PiN2vL732kbsnKxGI7+2VAhwE+BEKYTG5R0FDj96rstqYz9mcEGUtG4KQZblwndL3ZZS5VEX0xGm/NlOYvbiwIhBpNf9KhPS/eSGyBvk/vHb9LfG7B3tCt+oQ+wMErKhXHV73BgwxbCigHfKWoaTkMRJZ3sNWuMwSk4tgR2u/EW/LUOFTkZSxgOuXf8rJ1b1HcSppRRvNxJFle9dL7u2fUHZiO3YVh8bjFzr0WlQd0OZemLnYbnj2TJ3PBiWErSfbC3NbPcpWg6R+csPY3Tsnep5iDB2vZ7MXaMO/7zEsIo25QwOlZZYPIA/afKaLN1jAkg5YwyCuKaNhNLa5wP1nzEqEWlm/Y9epWAgqY3cOgYWlPo58zOrEw5xGtDgdZlGNvH5Lms+RVht+ZJ+61ARLLb4b2+rbnHFEpRokv7jCgh+WHL14isYBCEVo9EjducFB3NIsIbK3H26WY9BQ7XfM23RdYTu+g8ZqPr12tpTsg=
--- a/.hgtags Sun Aug 06 15:48:33 2017 +0300 +++ b/.hgtags Sun Dec 30 13:23:15 2018 -0500 @@ -8,3 +8,8 @@ 01e4e479754cd110c4944b374e45dab534678fc5 v4.2 fe6c3446b55db23a7343bc0ae5b7eeb4601fb24c v4.3 bd519cc8058c6c15ce882f5c265d55b474638964 v4.4-rc1 +9f2eb71d116d7b3accc7c87fea9b085b15aadde6 v4.4-rc2 +d7ff619768d39bac25ff110ecf6224c2cdfd422a v4.4 +1dc65e2b39e75af9fc4f7a9c1e3517cff4666eea v4.5-rc1 +40e8a3bb0684652444e3090343af2a31ad98da63 v4.5-rc2 +6435f2f8f9181c677db9fdfd42e60937b6966772 v4.5
--- a/CMakeLists.txt Sun Aug 06 15:48:33 2017 +0300 +++ b/CMakeLists.txt Sun Dec 30 13:23:15 2018 -0500 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011-2017 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> +# Copyright (c) 2011-2018 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -118,10 +118,8 @@ target_link_libraries(blahg md - avl m ${JEFFPC_LIBRARY} - ${JEFFPC_COMM_LIBRARY} ) add_executable(blahgd
--- a/README Sun Aug 06 15:48:33 2017 +0300 +++ b/README Sun Dec 30 13:23:15 2018 -0500 @@ -50,7 +50,6 @@ provided by illumos-based distros (e.g., OmniOS or OpenIndiana hipster). Specifically, blahgd requires: - - libavl.so (for AVL trees) - libmd.so (for SHA1) Other dependencies include:
--- a/ast.c Sun Aug 06 15:48:33 2017 +0300 +++ b/ast.c Sun Dec 30 13:23:15 2018 -0500 @@ -29,7 +29,6 @@ #include "ast.h" #include "utils.h" -#include "iter.h" static struct mem_cache *ast_cache; static struct mem_cache *astnode_cache; @@ -109,7 +108,7 @@ struct val *parts[6]; int nparts = 0; /* pacify gcc */ - parts[0] = VAL_ALLOC_SYM_CSTR(ast_typename(cur->type)); + parts[0] = VAL_ALLOC_STR_STATIC(ast_typename(cur->type)); switch (cur->type) { case AST_ENCAP: @@ -119,11 +118,11 @@ case AST_STR: case AST_VERB: case AST_LIST: - parts[1] = VAL_ALLOC_STR(cur->u.str); + parts[1] = str_getref_val(cur->u.str); nparts = 2; break; case AST_CMD: - parts[1] = VAL_DUP_CSTR(cur->u.cmd.info->name); + parts[1] = VAL_DUP_STR(cur->u.cmd.info->name); parts[2] = VAL_ALLOC_BOOL(cur->u.cmd.bad); parts[3] = VAL_ALLOC_INT(cur->u.cmd.capture_nmand); parts[4] = VAL_ALLOC_INT(cur->u.cmd.capture_nopt); @@ -141,7 +140,7 @@ break; case AST_ENV: if (cur->u.env.name) - parts[1] = VAL_ALLOC_STR(cur->u.env.name); + parts[1] = str_getref_val(cur->u.env.name); else parts[1] = VAL_ALLOC_CONS(NULL, NULL); parts[2] = __ast_dump_to_lisp(&cur->u.env.children); @@ -157,7 +156,7 @@ case AST_CHAR: char2str[0] = cur->u.ch.ch; char2str[1] = '\0'; - parts[1] = VAL_DUP_CSTR(char2str); + parts[1] = VAL_DUP_STR(char2str); parts[2] = VAL_ALLOC_INT(cur->u.ch.len); nparts = 3; break;
--- a/cmake/Modules/Findjeffpc.cmake Sun Aug 06 15:48:33 2017 +0300 +++ b/cmake/Modules/Findjeffpc.cmake Sun Dec 30 13:23:15 2018 -0500 @@ -1,5 +1,5 @@ # -# Copyright (c) 2016-2017 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> +# Copyright (c) 2016-2018 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -26,12 +26,10 @@ # This module defines: # JEFFPC_INCLUDE_DIR # JEFFPC_LIBRARY -# JEFFPC_COMM_LIBRARY # JEFFPC_FOUND # # Use the following variables to help locate the library and header files. # WITH_JEFFPC_LIB=x - directory containing libjeffpc.so -# WITH_JEFFPC_COMM_LIB=x - directory containing libjeffpc-comm.so # WITH_JEFFPC_INCLUDES=x - directory containing jeffpc/jeffpc.h # WITH_JEFFPC=x - same as setting WITH_JEFFPC_LIB=x/lib and # WITH_JEFFPC_INCLUDES=x/include @@ -41,9 +39,6 @@ if (NOT WITH_JEFFPC_LIB) set(WITH_JEFFPC_LIB "${WITH_JEFFPC}/lib") endif() - if (NOT WITH_JEFFPC_COMM_LIB) - set(WITH_JEFFPC_COMM_LIB "${WITH_JEFFPC}/lib") - endif() if (NOT WITH_JEFFPC_INCLUDES) set(WITH_JEFFPC_INCLUDES "${WITH_JEFFPC}/include") endif() @@ -54,9 +49,6 @@ find_library(JEFFPC_LIBRARY NAMES jeffpc PATHS ${WITH_JEFFPC_LIB} ) -find_library(JEFFPC_COMM_LIBRARY NAMES jeffpc-comm - PATHS ${WITH_JEFFPC_COMM_LIB} -) # # Handle the QUIETLY and REQUIRED arguments and set JEFFPC_FOUND to TRUE if @@ -65,5 +57,3 @@ include(FindPackageHandleStandardArgs) find_package_handle_standard_args(JEFFPC DEFAULT_MSG JEFFPC_LIBRARY JEFFPC_INCLUDE_DIR) -find_package_handle_standard_args(JEFFPC_COMM DEFAULT_MSG JEFFPC_COMM_LIBRARY - JEFFPC_INCLUDE_DIR)
--- a/comment.c Sun Aug 06 15:48:33 2017 +0300 +++ b/comment.c Sun Dec 30 13:23:15 2018 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2017 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * Copyright (c) 2009-2018 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -34,7 +34,6 @@ #include <jeffpc/error.h> #include <jeffpc/atomic.h> #include <jeffpc/sexpr.h> -#include <jeffpc/str.h> #include <jeffpc/io.h> #include <jeffpc/qstring.h> @@ -82,9 +81,9 @@ #define COMMENT_EMPTY "x" static const struct nvl_convert_info comment_convert[] = { - { .name = COMMENT_DATE, .tgt_type = NVT_INT, }, - { .name = COMMENT_ID, .tgt_type = NVT_INT, }, - { .name = COMMENT_CAPTCHA, .tgt_type = NVT_INT, }, + { .name = COMMENT_DATE, .tgt_type = VT_INT, }, + { .name = COMMENT_ID, .tgt_type = VT_INT, }, + { .name = COMMENT_CAPTCHA, .tgt_type = VT_INT, }, { .name = NULL, }, }; @@ -92,12 +91,9 @@ struct str *curdate, struct str *ip, struct str *url) { - struct val *url_val; struct val *lv; struct str *str; - url_val = url ? VAL_ALLOC_STR(url) : NULL; - /* * We're looking for a list looking something like: * @@ -110,12 +106,12 @@ */ lv = sexpr_args_to_list(6, - VAL_ALLOC_CONS(VAL_ALLOC_SYM_CSTR("author"), VAL_ALLOC_STR(author)), - VAL_ALLOC_CONS(VAL_ALLOC_SYM_CSTR("email"), VAL_ALLOC_STR(email)), - VAL_ALLOC_CONS(VAL_ALLOC_SYM_CSTR("time"), VAL_ALLOC_STR(curdate)), - VAL_ALLOC_CONS(VAL_ALLOC_SYM_CSTR("ip"), VAL_ALLOC_STR(ip)), - VAL_ALLOC_CONS(VAL_ALLOC_SYM_CSTR("url"), url_val), - VAL_ALLOC_CONS(VAL_ALLOC_SYM_CSTR("moderated"), VAL_ALLOC_BOOL(false))); + VAL_ALLOC_CONS(str_cast_to_val(STATIC_STR("author")), str_cast_to_val(author)), + VAL_ALLOC_CONS(str_cast_to_val(STATIC_STR("email")), str_cast_to_val(email)), + VAL_ALLOC_CONS(str_cast_to_val(STATIC_STR("time")), str_cast_to_val(curdate)), + VAL_ALLOC_CONS(str_cast_to_val(STATIC_STR("ip")), str_cast_to_val(ip)), + VAL_ALLOC_CONS(str_cast_to_val(STATIC_STR("url")), str_cast_to_val(url)), + VAL_ALLOC_CONS(str_cast_to_val(STATIC_STR("moderated")), VAL_ALLOC_BOOL(false))); str = sexpr_dump(lv, false); @@ -207,7 +203,7 @@ goto err; } - ret = write_file(lisppath, meta->str, str_len(meta)); + ret = write_file(lisppath, str_cstr(meta), str_len(meta)); str_putref(meta); @@ -420,13 +416,13 @@ int id; if (nvl_exists_type(req->scgi->request.headers, SCGI_HTTP_USER_AGENT, - NVT_STR)) { + VT_STR)) { DBG("Missing user agent..."); return USERAGENT_MISSING; } if (nvl_exists_type(req->scgi->request.headers, SCGI_REMOTE_ADDR, - NVT_STR)) { + VT_STR)) { DBG("Missing remote addr..."); return INTERNAL_ERR; } @@ -450,7 +446,7 @@ goto err; } - ret = nvl_convert(qs, comment_convert); + ret = nvl_convert(qs, comment_convert, false); if (ret) { DBG("Failed to convert nvlist types: %s", xstrerror(ret)); goto err;
--- a/config.cmake Sun Aug 06 15:48:33 2017 +0300 +++ b/config.cmake Sun Dec 30 13:23:15 2018 -0500 @@ -22,8 +22,6 @@ include(CheckFunctionExists) -check_function_exists(reallocarray HAVE_REALLOCARRAY) - set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules") find_package(jeffpc)
--- a/config.h.in Sun Aug 06 15:48:33 2017 +0300 +++ b/config.h.in Sun Dec 30 13:23:15 2018 -0500 @@ -23,8 +23,6 @@ #ifndef __CONFIG_H #define __CONFIG_H -#cmakedefine HAVE_REALLOCARRAY - /* settings */ #cmakedefine DEFAULT_SCGI_PORT ${DEFAULT_SCGI_PORT}
--- a/daemon.c Sun Aug 06 15:48:33 2017 +0300 +++ b/daemon.c Sun Dec 30 13:23:15 2018 -0500 @@ -28,7 +28,6 @@ #include <jeffpc/error.h> #include <jeffpc/atomic.h> #include <jeffpc/val.h> -#include <jeffpc/str.h> #include <jeffpc/types.h> #include <jeffpc/scgisvc.h> @@ -43,18 +42,31 @@ #include "version.h" #include "debug.h" -static void process_request(struct scgi *scgi, void *private) +static int init_request(struct scgi *scgi, void *private) { - struct req req; + struct req *req; - req_init(&req); + req = malloc(sizeof(struct req)); + if (!req) + return -ENOMEM; + + req_init(req, scgi); + + scgi->private = req; - req.scgi = scgi; + return 0; +} - req_dispatch(&req); +static void deinit_request(struct scgi *scgi) +{ + req_destroy(scgi->private); + free(scgi->private); +} - req_output(&req); - req_destroy(&req); +static void process_request(struct scgi *scgi) +{ + req_dispatch(scgi->private); + req_output(scgi->private); } static int drop_privs(void) @@ -106,6 +118,11 @@ /* the main daemon process */ static int main_blahgd(int argc, char **argv, int mathfd) { + static const struct scgiops ops = { + .init = init_request, + .process = process_request, + .deinit = deinit_request, + }; int ret; /* drop unneeded privs */ @@ -129,7 +146,7 @@ goto err; ret = scgisvc(NULL, config.scgi_port, config.scgi_threads, - process_request, NULL); + &ops, NULL); if (ret) goto err; @@ -158,11 +175,11 @@ ASSERT0(putenv("TZ=UTC")); + jeffpc_init(&init_ops); + cmn_err(CE_INFO, "blahgd version %s", version_string); cmn_err(CE_INFO, "libjeffpc version %s", jeffpc_version); - jeffpc_init(&init_ops); - ret = config_load((argc >= 2) ? argv[1] : NULL); if (ret) goto out;
--- a/debug.h Sun Aug 06 15:48:33 2017 +0300 +++ b/debug.h Sun Dec 30 13:23:15 2018 -0500 @@ -28,6 +28,8 @@ #define DBG(...) cmn_err(CE_DEBUG, __VA_ARGS__) +extern void set_session(uint32_t id); + extern struct jeffpc_ops init_ops; #endif
--- a/error.c Sun Aug 06 15:48:33 2017 +0300 +++ b/error.c Sun Dec 30 13:23:15 2018 -0500 @@ -26,6 +26,10 @@ #include <syslog.h> #include <stdarg.h> +/* session info */ +static __thread char session_str[64]; +static __thread uint32_t session_id; + static void mylog(int level, const char *fmt, va_list ap) { char msg[512]; @@ -38,6 +42,22 @@ syslog(LOG_LOCAL0 | level, "%s", msg); } +void set_session(uint32_t id) +{ + session_id = id; +} + +static const char *get_session(void) +{ + if (!session_id) + return ""; + + snprintf(session_str, sizeof(session_str), " {%u}", session_id); + + return session_str; +} + struct jeffpc_ops init_ops = { .log = mylog, + .get_session = get_session, };
--- a/file_cache.c Sun Aug 06 15:48:33 2017 +0300 +++ b/file_cache.c Sun Dec 30 13:23:15 2018 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2017 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * Copyright (c) 2014-2018 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -20,7 +20,6 @@ * SOFTWARE. */ -#include <sys/avl.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> @@ -28,22 +27,25 @@ #include <stdbool.h> #include <port.h> -#include <jeffpc/str.h> +#include <jeffpc/val.h> #include <jeffpc/synch.h> #include <jeffpc/thread.h> #include <jeffpc/refcnt.h> #include <jeffpc/io.h> #include <jeffpc/list.h> #include <jeffpc/mem.h> +#include <jeffpc/rbtree.h> #include "file_cache.h" #include "utils.h" -#include "iter.h" #include "debug.h" #define FILE_EVENTS (FILE_MODIFIED | FILE_ATTRIB) -static avl_tree_t file_cache; +static LOCK_CLASS(file_lock_lc); +static LOCK_CLASS(file_node_lc); + +static struct rb_tree file_cache; static struct lock file_lock; static int filemon_port; @@ -60,7 +62,7 @@ struct file_node { char *name; /* the filename */ - avl_node_t node; + struct rb_node node; refcnt_t refcnt; struct lock lock; @@ -159,7 +161,7 @@ * disk. */ MXLOCK(&file_lock); - avl_remove(&file_cache, node); + rb_remove(&file_cache, node); MXUNLOCK(&file_lock); MXUNLOCK(&node->lock); @@ -225,10 +227,10 @@ { int ret; - MXINIT(&file_lock); + MXINIT(&file_lock, &file_lock_lc); - avl_create(&file_cache, filename_cmp, sizeof(struct file_node), - offsetof(struct file_node, node)); + rb_create(&file_cache, filename_cmp, sizeof(struct file_node), + offsetof(struct file_node, node)); file_node_cache = mem_cache_create("file-node-cache", sizeof(struct file_node), 0); @@ -262,7 +264,7 @@ node->contents = NULL; node->needs_reload = true; - MXINIT(&node->lock); + MXINIT(&node->lock, &file_node_lc); refcnt_init(&node->refcnt, 1); list_create(&node->callbacks, sizeof(struct file_callback), offsetof(struct file_callback, list)); @@ -326,10 +328,14 @@ } node->contents = str_alloc(tmp); - if (!node->contents) { - DBG("file (%s) str_alloc error", node->name); + if (IS_ERR(node->contents)) { + int ret = PTR_ERR(node->contents); + + DBG("file (%s) str_alloc error: %s", node->name, xstrerror(ret)); free(tmp); - return -ENOMEM; + + node->contents = NULL; + return ret; } node->needs_reload = false; @@ -359,14 +365,14 @@ struct file_node *out, *tmp; struct file_node key; struct str *str; - avl_index_t where; + struct rb_cookie where; int ret; key.name = (char *) name; /* do we have it? */ MXLOCK(&file_lock); - out = avl_find(&file_cache, &key, NULL); + out = rb_find(&file_cache, &key, NULL); fn_getref(out); MXUNLOCK(&file_lock); @@ -391,7 +397,7 @@ /* ...and insert it into the cache */ MXLOCK(&file_lock); - tmp = avl_find(&file_cache, &key, &where); + tmp = rb_find(&file_cache, &key, &where); if (tmp) { /* * uh oh, someone beat us to it; free our copy & return @@ -412,7 +418,7 @@ /* get a ref for the cache */ fn_getref(out); - avl_insert(&file_cache, out, where); + rb_insert_here(&file_cache, out, &where); MXUNLOCK(&file_lock); MXUNLOCK(&out->lock); @@ -447,11 +453,11 @@ void uncache_all_files(void) { struct file_node *cur; - void *cookie; + struct rb_cookie cookie; MXLOCK(&file_lock); - cookie = NULL; - while ((cur = avl_destroy_nodes(&file_cache, &cookie))) + memset(&cookie, 0, sizeof(cookie)); + while ((cur = rb_destroy_nodes(&file_cache, &cookie))) fn_putref(cur); MXUNLOCK(&file_lock); }
--- a/index.c Sun Aug 06 15:48:33 2017 +0300 +++ b/index.c Sun Dec 30 13:23:15 2018 -0500 @@ -121,8 +121,6 @@ int blahg_index(struct req *req, int page) { - page = max(page, 0); - __store_title(&req->vars, "Blahg", false); __store_pages(&req->vars, page); @@ -136,15 +134,29 @@ return 0; } -static int validate_arch_id(int arch) +static bool valid_arch_id(uint64_t arch) { - int y = arch / 100; - int m = arch % 100; + uint64_t y = arch / 100; + uint64_t m = arch % 100; return (m >= 1) && (m <= 12) && (y >= 1970) && (y < 2100); } -int blahg_archive(struct req *req, int m, int page) +static int get_arch_id(struct req *req) +{ + const int default_arch_id = 197001; + uint64_t tmp; + + if (nvl_lookup_int(req->scgi->request.query, "m", &tmp)) + return default_arch_id; + + if (!valid_arch_id(tmp)) + return default_arch_id; + + return tmp; +} + +int blahg_archive(struct req *req, int page) { static const char *months[12] = { "January", "February", "March", "April", "May", "June", @@ -153,17 +165,15 @@ }; char nicetitle[32]; + int m; - if (!validate_arch_id(m)) - m = 197001; + m = get_arch_id(req); snprintf(nicetitle, sizeof(nicetitle), "%d » %s", m / 100, months[(m % 100) - 1]); req_head(req, "Content-Type", "text/html"); - page = max(page, 0); - __store_title(&req->vars, nicetitle, true); __store_pages(&req->vars, page); __store_archid(&req->vars, m);
--- a/iter.h Sun Aug 06 15:48:33 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2014-2017 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef __ITER_H -#define __ITER_H - -#include <stddef.h> - -#define avl_for_each(tree, pos) \ - for (pos = avl_first(tree); pos; pos = AVL_NEXT(tree, pos)) - -#endif
--- a/lisplint.c Sun Aug 06 15:48:33 2017 +0300 +++ b/lisplint.c Sun Dec 30 13:23:15 2018 -0500 @@ -25,7 +25,6 @@ #include <jeffpc/jeffpc.h> #include <jeffpc/error.h> #include <jeffpc/sexpr.h> -#include <jeffpc/str.h> #include <jeffpc/val.h> #include "utils.h"
--- a/listing.h Sun Aug 06 15:48:33 2017 +0300 +++ b/listing.h Sun Dec 30 13:23:15 2018 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2016 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * Copyright (c) 2011-2017 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -25,7 +25,7 @@ #include <stdlib.h> -#include <jeffpc/str.h> +#include <jeffpc/val.h> #include "post.h" #include "mangle.h"
--- a/math.c Sun Aug 06 15:48:33 2017 +0300 +++ b/math.c Sun Dec 30 13:23:15 2018 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2017 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * Copyright (c) 2014-2018 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -22,7 +22,7 @@ #include <sha1.h> -#include <jeffpc/str.h> +#include <jeffpc/val.h> #include <jeffpc/synch.h> #include <jeffpc/error.h> #include <jeffpc/atomic.h> @@ -47,6 +47,7 @@ * process doing its job; it can chdir as needed */ +static LOCK_CLASS(math_lc); static struct lock lock; static int pipefd = -1; @@ -369,5 +370,5 @@ pipefd = fd; - MXINIT(&lock); + MXINIT(&lock, &math_lc); }
--- a/math.h Sun Aug 06 15:48:33 2017 +0300 +++ b/math.h Sun Dec 30 13:23:15 2018 -0500 @@ -25,7 +25,7 @@ #include <stdbool.h> -#include <jeffpc/str.h> +#include <jeffpc/val.h> extern void init_math(int fd); extern int render_math_processor(int fd);
--- a/nvl.c Sun Aug 06 15:48:33 2017 +0300 +++ b/nvl.c Sun Dec 30 13:23:15 2018 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2017 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * Copyright (c) 2015-2018 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -34,15 +34,3 @@ return out; } - -const char *pair2str(const struct nvpair *pair) -{ - struct str *str; - - str = nvpair_value_str(pair); - ASSERT(!IS_ERR(str)); - - /* FIXME: we are leaking a refence */ - - return str_cstr(str); -}
--- a/nvl.h Sun Aug 06 15:48:33 2017 +0300 +++ b/nvl.h Sun Dec 30 13:23:15 2018 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2017 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * Copyright (c) 2015-2018 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,7 +26,6 @@ #include <stdbool.h> #include <jeffpc/nvl.h> -extern const char *pair2str(const struct nvpair *pair); extern uint64_t pair2int(const struct nvpair *pair); #endif
--- a/parse.h Sun Aug 06 15:48:33 2017 +0300 +++ b/parse.h Sun Dec 30 13:23:15 2018 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * Copyright (c) 2012-2017 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -24,7 +24,6 @@ #define __PARSE_H #include <jeffpc/error.h> -#include <jeffpc/str.h> #include <jeffpc/sexpr.h> #include "req.h"
--- a/pipeline.c Sun Aug 06 15:48:33 2017 +0300 +++ b/pipeline.c Sun Dec 30 13:23:15 2018 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2017 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * Copyright (c) 2013-2018 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -133,12 +133,18 @@ out = str_of_int(val->i); break; case VT_STR: - out = cvt(str_cstr(val->str)); + out = cvt(str_cstr(val_cast_to_str(val))); break; + case VT_NULL: + val_putref(val); + return str_cast_to_val(str_empty_string()); + case VT_BLOB: case VT_SYM: case VT_CONS: case VT_BOOL: case VT_CHAR: + case VT_ARRAY: + case VT_NVL: panic("%s called with value type %d", __func__, val->type); } @@ -147,7 +153,7 @@ ASSERT(out); - return VAL_ALLOC_CSTR(out); + return VAL_ALLOC_STR(out); } static struct val *urlescape_fxn(struct val *val) @@ -174,7 +180,7 @@ val_putref(val); - return VAL_DUP_CSTR(buf); + return VAL_DUP_STR(buf); } static struct val *time_fxn(struct val *val)
--- a/post.c Sun Aug 06 15:48:33 2017 +0300 +++ b/post.c Sun Dec 30 13:23:15 2018 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2017 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * Copyright (c) 2009-2018 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -38,7 +38,6 @@ #include <jeffpc/io.h> #include <jeffpc/mem.h> -#include "iter.h" #include "post.h" #include "vars.h" #include "req.h" @@ -52,7 +51,9 @@ static struct mem_cache *post_cache; static struct mem_cache *comment_cache; -static void post_remove_all_tags(avl_tree_t *taglist); +static LOCK_CLASS(post_lc); + +static void post_remove_all_tags(struct rb_tree *taglist); static void post_remove_all_comments(struct post *post); static int tag_cmp(const void *va, const void *vb) @@ -93,41 +94,31 @@ post_unlock(post); } -static void post_add_tags(avl_tree_t *taglist, struct val *list) +/* consumes the struct val reference */ +static void post_add_tags(struct rb_tree *taglist, struct val *list) { - struct post_tag *tag; + struct val *tagval; + struct val *tmp; - /* tags list not present in metadata */ - if (!list) - return; - - for (; list; list = sexpr_cdr(list)) { - struct val *tagval; - struct str *tagname; - - tagval = sexpr_car(val_getref(list)); + sexpr_for_each_noref(tagval, tmp, list) { + struct post_tag *tag; /* sanity check */ ASSERT3U(tagval->type, ==, VT_STR); - /* get the tag name */ - tagname = str_getref(tagval->str); - - /* release the tag value */ - val_putref(tagval); - tag = malloc(sizeof(struct post_tag)); ASSERT(tag); - tag->tag = tagname; - ASSERT(tag->tag); + tag->tag = val_getref_str(tagval); - if (safe_avl_add(taglist, tag)) { + if (rb_insert(taglist, tag)) { /* found a duplicate */ str_putref(tag->tag); free(tag); } } + + val_putref(list); } static void post_remove_all_comments(struct post *post) @@ -213,25 +204,21 @@ str_putref(meta); } +/* consumes the struct val reference */ static void post_add_comments(struct post *post, struct val *list) { - if (!list) - return; + struct val *val; + struct val *tmp; - for (; list; list = sexpr_cdr(list)) { - struct val *val; - - val = sexpr_car(val_getref(list)); - + sexpr_for_each_noref(val, tmp, list) { /* sanity check */ ASSERT3U(val->type, ==, VT_INT); /* add the comment */ post_add_comment(post, val->i); + } - /* release the value */ - val_putref(val); - } + val_putref(list); } static int __do_load_post_body_fmt3(struct post *post, const struct str *input) @@ -485,14 +472,14 @@ post->preview = preview; post->needs_refresh = true; - avl_create(&post->tags, tag_cmp, sizeof(struct post_tag), - offsetof(struct post_tag, node)); - avl_create(&post->cats, tag_cmp, sizeof(struct post_tag), - offsetof(struct post_tag, node)); + rb_create(&post->tags, tag_cmp, sizeof(struct post_tag), + offsetof(struct post_tag, node)); + rb_create(&post->cats, tag_cmp, sizeof(struct post_tag), + offsetof(struct post_tag, node)); list_create(&post->comments, sizeof(struct comment), offsetof(struct comment, list)); refcnt_init(&post->refcnt, 1); - MXINIT(&post->lock); + MXINIT(&post->lock, &post_lc); if ((err = __refresh(post))) goto err_free; @@ -510,19 +497,19 @@ return NULL; } -static void post_remove_all_tags(avl_tree_t *taglist) +static void post_remove_all_tags(struct rb_tree *taglist) { struct post_tag *tag; - void *cookie; + struct rb_cookie cookie; - cookie = NULL; - while ((tag = avl_destroy_nodes(taglist, &cookie))) { + memset(&cookie, 0, sizeof(cookie)); + while ((tag = rb_destroy_nodes(taglist, &cookie))) { str_putref(tag->tag); free(tag); } - avl_create(taglist, tag_cmp, sizeof(struct post_tag), - offsetof(struct post_tag, node)); + rb_create(taglist, tag_cmp, sizeof(struct post_tag), + offsetof(struct post_tag, node)); } void post_destroy(struct post *post)
--- a/post.h Sun Aug 06 15:48:33 2017 +0300 +++ b/post.h Sun Dec 30 13:23:15 2018 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2017 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * Copyright (c) 2009-2018 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -25,16 +25,16 @@ #include <time.h> #include <stdbool.h> -#include <sys/avl.h> #include <jeffpc/synch.h> #include <jeffpc/refcnt.h> #include <jeffpc/list.h> +#include <jeffpc/rbtree.h> #include "vars.h" struct post_tag { - avl_node_t node; + struct rb_node node; struct str *tag; }; @@ -66,8 +66,8 @@ unsigned int fmt; /* from 'post_tags' table */ - avl_tree_t tags; - avl_tree_t cats; + struct rb_tree tags; + struct rb_tree cats; /* from 'comments' table */ struct list comments;
--- a/post_fmt3.l Sun Aug 06 15:48:33 2017 +0300 +++ b/post_fmt3.l Sun Dec 30 13:23:15 2018 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2017 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * Copyright (c) 2011-2018 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -29,8 +29,6 @@ %{ #include <stdlib.h> -#include <jeffpc/str.h> - #include "parse.h" #include "post_fmt3.tab.h" @@ -73,23 +71,13 @@ "\\tag{" { BEGIN(SPECIALCMD); return TAGSTART; } "\\category{" { BEGIN(SPECIALCMD); return CATSTART; } "\\twitterimg{" { BEGIN(SPECIALCMD); return TWITTERIMGSTART; } +"\\twitterphoto{" { BEGIN(SPECIALCMD); return TWITTERPHOTOSTART; } <SPECIALCMD>"}" { BEGIN(INITIAL); return SPECIALCMDEND; } <SPECIALCMD>. { yylval->ptr = STR_DUP(yytext); return VERBTEXT; } "$" { BEGIN(MATH); return MATHSTART; } <MATH>"$" { BEGIN(INITIAL); return MATHEND; } -<MATH>"\\" { return BSLASH; } -<MATH>"_" { return USCORE; } -<MATH>"^" { return CARRET; } -<MATH>"+" { return PLUS; } -<MATH>"-" { return MINUS; } -<MATH>"*" { return ASTERISK; } -<MATH>"/" { return SLASH; } -<MATH>"{" { return OCURLY; } -<MATH>"}" { return CCURLY; } -<MATH>"(" { return OPAREN; } -<MATH>")" { return CPAREN; } -<MATH>"~" { return TILDE; } +<MATH>[\\{}()*/~^_+-] { return *yytext; } <MATH>[=<>] { yylval->ptr = STR_DUP(yytext); return EQLTGT; } <MATH>[A-Za-z0-9]+ { yylval->ptr = STR_DUP(yytext); return WORD; } <MATH>[".,=<>!:;?@*#] { yylval->ptr = STR_DUP(yytext); return SCHAR; } @@ -107,29 +95,20 @@ } \n { inc_lineno(yyscanner); - return NLINE; + return *yytext; } %[^\n]* { /* tex comment */ } [ \t]+ { yylval->ptr = STR_DUP(yytext); return WSPACE; } -"\\" { return BSLASH; } -"{" { return OCURLY; } -"}" { return CCURLY; } -"[" { return OBRACE; } -"]" { return CBRACE; } -"&" { return AMP; } -"_" { return USCORE; } "\\%" { return PERCENT; } -"~" { return TILDE; } -"|" { return PIPE; } -"^" { return CARRET; } +[\\{}~&^_[\]] { return *yytext; } \.{3} { return ELLIPSIS; } -{1,3} { yylval->ptr = STR_DUP(yytext); return DASH; } `{1,2} { yylval->ptr = STR_DUP(yytext); return OQUOT; } '{1,2} { yylval->ptr = STR_DUP(yytext); return CQUOT; } -[".,()/=<>!:;\+?@*#] { yylval->ptr = STR_DUP(yytext); return SCHAR; } -[\xe0-\xef] { yylval->ptr = STR_DUP(yytext); return UTF8FIRST3; } -[\xc0-\xdf] { yylval->ptr = STR_DUP(yytext); return UTF8FIRST2; } -[\x80-\xbf] { yylval->ptr = STR_DUP(yytext); return UTF8REST; } +[.,()/=!:;\+?@*#|] { yylval->ptr = STR_DUP(yytext); return CHAR; } +["<>] { yylval->ptr = STR_DUP(yytext); return SCHAR; } +[\xe0-\xef][\x80-\xbf][\x80-\xbf] { yylval->ptr = STR_DUP(yytext); return UTF8CHAR; } +[\xc0-\xdf][\x80-\xbf] { yylval->ptr = STR_DUP(yytext); return UTF8CHAR; } [A-Za-z0-9]+ { yylval->ptr = STR_DUP(yytext); return WORD; } . { fmt3_error2("post text contains invalid characters", yytext); yyterminate(); } %%
--- a/post_fmt3.y Sun Aug 06 15:48:33 2017 +0300 +++ b/post_fmt3.y Sun Dec 30 13:23:15 2018 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2017 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * Copyright (c) 2011-2018 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -34,7 +34,6 @@ #include <sys/stat.h> #include <jeffpc/error.h> -#include <jeffpc/str.h> #include <jeffpc/types.h> #include "config.h" @@ -108,7 +107,8 @@ case '<': ret = STATIC_STR("<"); break; case '>': ret = STATIC_STR(">"); break; default: - return val; + panic("%s given an unexpected character '%c'", + __func__, str_cstr(val)[0]); } str_putref(val); @@ -117,23 +117,23 @@ } static void special_cmd(struct parser_output *data, struct str **var, - struct str *value) + struct str *value, bool photo) { str_putref(*var); - *var = value; + if (photo) + *var = str_cat(3, str_getref(config.photo_base_url), + STATIC_STR("/"), + value); + else + *var = value; } static void special_cmd_list(struct parser_output *data, struct val **var, struct str *value) { - struct val *new; - - /* wrap the string in a value */ - new = VAL_ALLOC_STR(value); - /* extend the list */ - *var = VAL_ALLOC_CONS(new, *var); + *var = VAL_ALLOC_CONS(str_cast_to_val(value), *var); } %} @@ -144,19 +144,13 @@ /* generic tokens */ %token <ptr> WSPACE -%token <ptr> DASH OQUOT CQUOT SCHAR -%token <ptr> UTF8FIRST3 UTF8FIRST2 UTF8REST WORD -%token SLASH -%token PIPE -%token OCURLY CCURLY OBRACE CBRACE -%token USCORE CARRET ASTERISK -%token BSLASH PERCENT AMP TILDE ELLIPSIS -%token PAREND NLINE +%token <ptr> DASH OQUOT CQUOT SCHAR CHAR +%token <ptr> UTF8CHAR WORD +%token PERCENT ELLIPSIS +%token PAREND /* math specific tokens */ %token <ptr> EQLTGT -%token PLUS MINUS -%token OPAREN CPAREN %token MATHSTART MATHEND /* verbose & listing environment */ @@ -164,22 +158,23 @@ %token VERBSTART VERBEND DOLLAR %token LISTSTART LISTEND %token TITLESTART TAGSTART CATSTART PUBSTART TWITTERIMGSTART +%token TWITTERPHOTOSTART %token SPECIALCMDEND %type <ptr> paragraphs paragraph thing cmd cmdarg optcmdarg math mexpr %type <ptr> verb -%left USCORE CARRET -%left TILDE +%left '_' '^' +%left '~' %left EQLTGT -%left PLUS MINUS -%left ASTERISK SLASH +%left '+' '-' +%left '*' '/' %% post : paragraphs PAREND { data->stroutput = $1; } | paragraphs { data->stroutput = $1; } - | PAREND { data->stroutput = STATIC_STR(""); } + | PAREND { data->stroutput = str_empty_string(); } ; paragraphs : paragraphs PAREND paragraph { $$ = str_cat(4, $1, STATIC_STR("<p>"), $3, STATIC_STR("</p>\n")); } @@ -191,54 +186,53 @@ ; thing : WORD { $$ = $1; } - | UTF8FIRST2 UTF8REST { $$ = str_cat(2, $1, $2); } - | UTF8FIRST3 UTF8REST UTF8REST { $$ = str_cat(3, $1, $2, $3); } - | NLINE { $$ = data->texttt_nesting ? STATIC_STR("\n") : STATIC_STR(" "); } + | UTF8CHAR { $$ = $1; } + | '\n' { $$ = data->texttt_nesting ? STATIC_STR("\n") : STATIC_STR(" "); } | WSPACE { $$ = $1; } - | PIPE { $$ = STATIC_STR("|"); } - | ASTERISK { $$ = STATIC_STR("*"); } - | SLASH { $$ = STATIC_STR("/"); } | DASH { $$ = dash($1); } | OQUOT { $$ = oquote($1); } | CQUOT { $$ = cquote($1); } + | CHAR { $$ = $1; } | SCHAR { $$ = special_char($1); } | ELLIPSIS { $$ = STATIC_STR("…"); } - | TILDE { $$ = STATIC_STR(" "); } - | AMP { $$ = STATIC_STR("</td><td>"); } + | '~' { $$ = STATIC_STR(" "); } + | '&' { $$ = STATIC_STR("</td><td>"); } | DOLLAR { $$ = STATIC_STR("$"); } | PERCENT { $$ = STATIC_STR("%"); } - | BSLASH cmd { $$ = $2; } + | '\\' cmd { $$ = $2; } | MATHSTART math MATHEND { $$ = render_math($2); } | VERBSTART verb VERBEND { $$ = str_cat(3, STATIC_STR("</p><p>"), $2, STATIC_STR("</p><p>")); } | LISTSTART verb LISTEND { $$ = str_cat(3, STATIC_STR("</p><pre>"), listing_str($2), STATIC_STR("</pre><p>")); } - | TITLESTART verb SPECIALCMDEND { $$ = NULL; special_cmd(data, &data->sc_title, $2); } - | PUBSTART verb SPECIALCMDEND { $$ = NULL; special_cmd(data, &data->sc_pub, $2); } + | TITLESTART verb SPECIALCMDEND { $$ = NULL; special_cmd(data, &data->sc_title, $2, false); } + | PUBSTART verb SPECIALCMDEND { $$ = NULL; special_cmd(data, &data->sc_pub, $2, false); } | TAGSTART verb SPECIALCMDEND { $$ = NULL; special_cmd_list(data, &data->sc_tags, $2); } | CATSTART verb SPECIALCMDEND { $$ = NULL; special_cmd_list(data, &data->sc_cats, $2); } | TWITTERIMGSTART verb SPECIALCMDEND - { $$ = NULL; special_cmd(data, &data->sc_twitter_img, $2); } + { $$ = NULL; special_cmd(data, &data->sc_twitter_img, $2, false); } + | TWITTERPHOTOSTART verb SPECIALCMDEND + { $$ = NULL; special_cmd(data, &data->sc_twitter_img, $2, true); } ; cmd : WORD optcmdarg cmdarg { $$ = process_cmd(data, $1, $3, $2); } | WORD cmdarg { $$ = process_cmd(data, $1, $2, NULL); } | WORD { $$ = process_cmd(data, $1, NULL, NULL); } - | BSLASH { $$ = STATIC_STR("<br/>"); } - | OCURLY { $$ = STATIC_STR("{"); } - | CCURLY { $$ = STATIC_STR("}"); } - | OBRACE { $$ = STATIC_STR("["); } - | CBRACE { $$ = STATIC_STR("]"); } - | AMP { $$ = STATIC_STR("&"); } - | USCORE { $$ = STATIC_STR("_"); } - | CARRET { $$ = STATIC_STR("^"); } - | TILDE { $$ = STATIC_STR("~"); } + | '\\' { $$ = STATIC_STR("<br/>"); } + | '{' { $$ = STATIC_STR("{"); } + | '}' { $$ = STATIC_STR("}"); } + | '[' { $$ = STATIC_STR("["); } + | ']' { $$ = STATIC_STR("]"); } + | '&' { $$ = STATIC_STR("&"); } + | '_' { $$ = STATIC_STR("_"); } + | '^' { $$ = STATIC_STR("^"); } + | '~' { $$ = STATIC_STR("~"); } ; -optcmdarg : OBRACE paragraph CBRACE { $$ = $2; } +optcmdarg : '[' paragraph ']' { $$ = $2; } ; -cmdarg : OCURLY paragraph CCURLY { $$ = $2; } +cmdarg : '{' paragraph '}' { $$ = $2; } ; verb : verb VERBTEXT { $$ = str_cat(2, $1, $2); } @@ -250,19 +244,20 @@ mexpr : WORD { $$ = $1; } | WSPACE { $$ = $1; } + | CHAR { $$ = $1; } | SCHAR { $$ = $1; } | mexpr EQLTGT mexpr { $$ = str_cat(3, $1, $2, $3); } - | mexpr USCORE mexpr { $$ = str_cat(3, $1, STATIC_STR("_"), $3); } - | mexpr CARRET mexpr { $$ = str_cat(3, $1, STATIC_STR("^"), $3); } - | mexpr PLUS mexpr { $$ = str_cat(3, $1, STATIC_STR("+"), $3); } - | mexpr MINUS mexpr { $$ = str_cat(3, $1, STATIC_STR("-"), $3); } - | mexpr ASTERISK mexpr { $$ = str_cat(3, $1, STATIC_STR("*"), $3); } - | mexpr SLASH mexpr { $$ = str_cat(3, $1, STATIC_STR("/"), $3); } - | mexpr TILDE mexpr { $$ = str_cat(3, $1, STATIC_STR("~"), $3); } - | BSLASH WORD { $$ = str_cat(2, STATIC_STR("\\"), $2); } - | BSLASH USCORE { $$ = STATIC_STR("\\_"); } - | OPAREN math CPAREN { $$ = str_cat(3, STATIC_STR("("), $2, STATIC_STR(")")); } - | OCURLY math CCURLY { $$ = str_cat(3, STATIC_STR("{"), $2, STATIC_STR("}")); } + | mexpr '_' mexpr { $$ = str_cat(3, $1, STATIC_STR("_"), $3); } + | mexpr '^' mexpr { $$ = str_cat(3, $1, STATIC_STR("^"), $3); } + | mexpr '+' mexpr { $$ = str_cat(3, $1, STATIC_STR("+"), $3); } + | mexpr '-' mexpr { $$ = str_cat(3, $1, STATIC_STR("-"), $3); } + | mexpr '*' mexpr { $$ = str_cat(3, $1, STATIC_STR("*"), $3); } + | mexpr '/' mexpr { $$ = str_cat(3, $1, STATIC_STR("/"), $3); } + | mexpr '~' mexpr { $$ = str_cat(3, $1, STATIC_STR("~"), $3); } + | '\\' WORD { $$ = str_cat(2, STATIC_STR("\\"), $2); } + | '\\' '_' { $$ = STATIC_STR("\\_"); } + | '(' math ')' { $$ = str_cat(3, STATIC_STR("("), $2, STATIC_STR(")")); } + | '{' math '}' { $$ = str_cat(3, STATIC_STR("{"), $2, STATIC_STR("}")); } ; %%
--- a/post_fmt3_cmds.c Sun Aug 06 15:48:33 2017 +0300 +++ b/post_fmt3_cmds.c Sun Dec 30 13:23:15 2018 -0500 @@ -22,7 +22,7 @@ #include <stdbool.h> -#include <jeffpc/str.h> +#include <jeffpc/val.h> #include <jeffpc/types.h> #include "config.h" @@ -346,7 +346,7 @@ str_putref(txt); str_putref(opt); - return STATIC_STR(""); + return str_empty_string(); } typedef enum {
--- a/post_fmt4_ast.c Sun Aug 06 15:48:33 2017 +0300 +++ b/post_fmt4_ast.c Sun Dec 30 13:23:15 2018 -0500 @@ -26,7 +26,6 @@ #include <jeffpc/error.h> #include "post_fmt4_ast.h" -#include "iter.h" #include "ast_opt.h" /*
--- a/post_index.c Sun Aug 06 15:48:33 2017 +0300 +++ b/post_index.c Sun Dec 30 13:23:15 2018 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2017 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * Copyright (c) 2015-2018 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -24,12 +24,11 @@ #include <stddef.h> #include <sys/sysmacros.h> -#include <jeffpc/str.h> +#include <jeffpc/val.h> #include <jeffpc/error.h> #include <jeffpc/mem.h> #include "post.h" -#include "iter.h" #include "utils.h" /* @@ -49,14 +48,14 @@ * * To maximize code reuse, the by-tag and by-category trees contain struct * post_subindex nodes for each (unique) tag/category. Those nodes contain - * AVL trees of their own with struct post_index_entry elements mapping - * <timestamp, post id> (much like the by time index) to a post. + * binary search trees of their own with struct post_index_entry elements + * mapping <timestamp, post id> (much like the by time index) to a post. * * Because this isn't complex enough, we also keep a linked list of all the * tag entries rooted in the global index tree node. * * +--------------------------------+ - * | index_global AVL tree | + * | index_global tree | * |+-------------------------+ | +------+ * || post global index entry | ... | | post | * +--->| by_tag by_cat post | | +------+ @@ -68,11 +67,11 @@ * | +--------+ +--------------------------+ * | | | * | | +-------------------------------------+ | - * | | | index_by_tag AVL tree | | + * | | | index_by_tag tree | | * | | | +-----------------------------+ | | * | | | | post subindex | | | * | | | | +-------------------------+ | | | - * | | | | | subindex AVL tree | | | | + * | | | | | subindex tree | | | | * | | | | | +-----------------+ | | | | * | +-----> |post index entry | ... | | | | * | | | | | global xref | | | ... | | @@ -87,11 +86,11 @@ * | +-------------------------------------------+ * | | * | | +-------------------------------------+ - * | | | index_by_cat AVL tree | + * | | | index_by_cat tree | * | | | +-----------------------------+ | * | | | | post subindex | | * | | | | +-------------------------+ | | - * | | | | | subindex AVL tree | | | + * | | | | | subindex tree | | | * | | | | | +-----------------+ | | | * | +-----> |post index entry | ... | | | * | | | | | global xref | | | ... | @@ -104,7 +103,7 @@ * | +-------------------------------------+ * | * | +-------------------------+ - * | | index_by_time AVL tree | + * | | index_by_time tree | * | |+------------------+ | * | || post index entry | ... | * | || global | | @@ -122,7 +121,7 @@ }; struct post_global_index_entry { - avl_node_t node; + struct rb_node node; /* key */ unsigned int id; @@ -139,7 +138,7 @@ }; struct post_index_entry { - avl_node_t node; + struct rb_node node; struct post_global_index_entry *global; @@ -161,21 +160,22 @@ }; struct post_subindex { - avl_node_t index; + struct rb_node index; /* key */ struct str *name; /* value */ - avl_tree_t subindex; + struct rb_tree subindex; }; -static avl_tree_t index_global; -static avl_tree_t index_by_time; -static avl_tree_t index_by_tag; -static avl_tree_t index_by_cat; +static struct rb_tree index_global; +static struct rb_tree index_by_time; +static struct rb_tree index_by_tag; +static struct rb_tree index_by_cat; static struct lock index_lock; +static LOCK_CLASS(index_lock_lc); static struct mem_cache *index_entry_cache; static struct mem_cache *global_index_entry_cache; @@ -235,27 +235,27 @@ return 0; } -static void init_index_tree(avl_tree_t *tree) +static void init_index_tree(struct rb_tree *tree) { - avl_create(tree, post_index_cmp, sizeof(struct post_index_entry), - offsetof(struct post_index_entry, node)); + rb_create(tree, post_index_cmp, sizeof(struct post_index_entry), + offsetof(struct post_index_entry, node)); } void init_post_index(void) { - avl_create(&index_global, post_global_index_cmp, - sizeof(struct post_global_index_entry), - offsetof(struct post_global_index_entry, node)); + rb_create(&index_global, post_global_index_cmp, + sizeof(struct post_global_index_entry), + offsetof(struct post_global_index_entry, node)); init_index_tree(&index_by_time); /* set up the by-tag/category indexes */ - avl_create(&index_by_tag, post_tag_cmp, sizeof(struct post_subindex), - offsetof(struct post_subindex, index)); - avl_create(&index_by_cat, post_tag_cmp, sizeof(struct post_subindex), - offsetof(struct post_subindex, index)); + rb_create(&index_by_tag, post_tag_cmp, sizeof(struct post_subindex), + offsetof(struct post_subindex, index)); + rb_create(&index_by_cat, post_tag_cmp, sizeof(struct post_subindex), + offsetof(struct post_subindex, index)); - MXINIT(&index_lock); + MXINIT(&index_lock, &index_lock_lc); index_entry_cache = mem_cache_create("index-entry-cache", sizeof(struct post_index_entry), @@ -272,14 +272,15 @@ ASSERT(!IS_ERR(subindex_cache)); } -static avl_tree_t *__get_subindex(avl_tree_t *index, struct str *tagname) +static struct rb_tree *__get_subindex(struct rb_tree *index, + struct str *tagname) { struct post_subindex *ret; struct post_subindex key = { .name = tagname, }; - ret = avl_find(index, &key, NULL); + ret = rb_find(index, &key, NULL); if (!ret) return NULL; @@ -296,7 +297,7 @@ struct post *post; MXLOCK(&index_lock); - ret = avl_find(&index_global, &key, NULL); + ret = rb_find(&index_global, &key, NULL); if (ret) post = post_getref(ret->post); else @@ -312,7 +313,7 @@ int skip, int nposts) { struct post_index_entry *cur; - avl_tree_t *tree; + struct rb_tree *tree; int i; MXLOCK(&index_lock); @@ -331,7 +332,7 @@ } /* skip over the first (listed) entries as requested */ - for (cur = avl_last(tree); cur && skip; cur = AVL_PREV(tree, cur)) { + for (cur = rb_last(tree); cur && skip; cur = rb_prev(tree, cur)) { if (!cur->global->post->listed) continue; /* don't count non-listed posts */ @@ -339,7 +340,7 @@ } /* get a reference for every post we're returning */ - for (i = 0; cur && nposts; cur = AVL_PREV(tree, cur)) { + for (i = 0; cur && nposts; cur = rb_prev(tree, cur)) { if (!cur->global->post->listed) continue; /* skip non-listed posts */ @@ -357,23 +358,23 @@ return i; } -static int __insert_post_tags(avl_tree_t *index, +static int __insert_post_tags(struct rb_tree *index, struct post_global_index_entry *global, - avl_tree_t *taglist, struct list *xreflist, + struct rb_tree *taglist, struct list *xreflist, enum entry_type type) { struct post_index_entry *tag_entry; struct post_subindex *sub; struct post_tag *tag; - avl_index_t where; + struct rb_cookie where; - avl_for_each(taglist, tag) { + rb_for_each(taglist, tag) { struct post_subindex key = { .name = tag->tag, }; /* find the right subindex, or... */ - sub = avl_find(index, &key, &where); + sub = rb_find(index, &key, &where); if (!sub) { /* ...allocate one if it doesn't exist */ sub = mem_cache_alloc(subindex_cache); @@ -383,7 +384,7 @@ sub->name = str_getref(tag->tag); init_index_tree(&sub->subindex); - avl_insert(index, sub, where); + rb_insert_here(index, sub, &where); } /* allocate & add a entry to the subindex */ @@ -395,7 +396,7 @@ tag_entry->name = str_getref(tag->tag); tag_entry->type = type; - ASSERT3P(safe_avl_add(&sub->subindex, tag_entry), ==, NULL); + ASSERT3P(rb_insert(&sub->subindex, tag_entry), ==, NULL); list_insert_tail(xreflist, tag_entry); } @@ -441,14 +442,14 @@ MXLOCK(&index_lock); /* add the post to the global index */ - if (safe_avl_add(&index_global, global)) { + if (rb_insert(&index_global, global)) { MXUNLOCK(&index_lock); ret = -EEXIST; goto err_free_by_time; } /* add the post to the by-time index */ - ASSERT3P(safe_avl_add(&index_by_time, by_time), ==, NULL); + ASSERT3P(rb_insert(&index_by_time, by_time), ==, NULL); ret = __insert_post_tags(&index_by_tag, global, &post->tags, &global->by_tag, ET_TAG); @@ -470,7 +471,7 @@ err_free_tags: // XXX: __remove_post_tags(&index_by_tag, &post->tags); - avl_remove(&index_by_time, by_time); + rb_remove(&index_by_time, by_time); MXUNLOCK(&index_lock); @@ -490,7 +491,7 @@ struct post_global_index_entry *cur; MXLOCK(&index_lock); - avl_for_each(&index_global, cur) + rb_for_each(&index_global, cur) revalidate_post(cur->post); MXUNLOCK(&index_lock); } @@ -510,7 +511,7 @@ MXLOCK(&index_lock); if (init) { - ret = init(private, avl_numnodes(&index_by_tag)); + ret = init(private, rb_numnodes(&index_by_tag)); if (ret) goto err; } @@ -523,45 +524,45 @@ */ cmin = ~0; cmax = 0; - avl_for_each(&index_by_tag, tag) { - cmin = MIN(cmin, avl_numnodes(&tag->subindex)); - cmax = MAX(cmax, avl_numnodes(&tag->subindex)); + rb_for_each(&index_by_tag, tag) { + cmin = MIN(cmin, rb_numnodes(&tag->subindex)); + cmax = MAX(cmax, rb_numnodes(&tag->subindex)); } /* * finally, invoke the step callback for each tag */ - avl_for_each(&index_by_tag, tag) - step(private, tag->name, avl_numnodes(&tag->subindex), + rb_for_each(&index_by_tag, tag) + step(private, tag->name, rb_numnodes(&tag->subindex), cmin, cmax); err: MXUNLOCK(&index_lock); } -static void __free_global_index(avl_tree_t *tree) +static void __free_global_index(struct rb_tree *tree) { struct post_global_index_entry *cur; - void *cookie; + struct rb_cookie cookie; - cookie = NULL; - while ((cur = avl_destroy_nodes(tree, &cookie))) { + memset(&cookie, 0, sizeof(cookie)); + while ((cur = rb_destroy_nodes(tree, &cookie))) { post_putref(cur->post); list_destroy(&cur->by_tag); list_destroy(&cur->by_cat); mem_cache_free(global_index_entry_cache, cur); } - avl_destroy(tree); + rb_destroy(tree); } -static void __free_index(avl_tree_t *tree) +static void __free_index(struct rb_tree *tree) { struct post_index_entry *cur; - void *cookie; + struct rb_cookie cookie; - cookie = NULL; - while ((cur = avl_destroy_nodes(tree, &cookie))) { + memset(&cookie, 0, sizeof(cookie)); + while ((cur = rb_destroy_nodes(tree, &cookie))) { struct list *xreflist = NULL; switch (cur->type) { @@ -583,22 +584,22 @@ mem_cache_free(index_entry_cache, cur); } - avl_destroy(tree); + rb_destroy(tree); } -static void __free_tag_index(avl_tree_t *tree) +static void __free_tag_index(struct rb_tree *tree) { struct post_subindex *cur; - void *cookie; + struct rb_cookie cookie; - cookie = NULL; - while ((cur = avl_destroy_nodes(tree, &cookie))) { + memset(&cookie, 0, sizeof(cookie)); + while ((cur = rb_destroy_nodes(tree, &cookie))) { __free_index(&cur->subindex); str_putref((struct str *) cur->name); mem_cache_free(subindex_cache, cur); } - avl_destroy(tree); + rb_destroy(tree); } void free_all_posts(void)
--- a/post_nv.c Sun Aug 06 15:48:33 2017 +0300 +++ b/post_nv.c Sun Dec 30 13:23:15 2018 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2017 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * Copyright (c) 2009-2018 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -20,52 +20,37 @@ * SOFTWARE. */ -#include <jeffpc/str.h> +#include <jeffpc/val.h> #include <jeffpc/list.h> +#include <jeffpc/mem.h> -#include "iter.h" #include "post.h" #include "req.h" -static int __tag_val(struct nvlist *post, avl_tree_t *list) +static int __tag_val(struct nvlist *post, struct rb_tree *list) { struct post_tag *cur; - struct nvval *tags; + struct val **tags; size_t ntags; size_t i; - int ret; - - ntags = avl_numnodes(list); -#ifdef HAVE_REALLOCARRAY - tags = reallocarray(NULL, ntags, sizeof(struct nvval)); -#else - tags = malloc(ntags * sizeof(struct nvval)); -#endif + ntags = rb_numnodes(list); + + tags = mem_reallocarray(NULL, ntags, sizeof(struct val *)); if (!tags) return -ENOMEM; i = 0; - avl_for_each(list, cur) { - struct nvval *tag = &tags[i++]; - - tag->type = NVT_STR; - tag->str = str_getref(cur->tag); - } + rb_for_each(list, cur) + tags[i++] = str_getref_val(cur->tag); - ret = nvl_set_array(post, "tags", tags, ntags); - if (ret) { - nvval_release_array(tags, ntags); - free(tags); - } - - return ret; + return nvl_set_array(post, "tags", tags, ntags); } static int __com_val(struct nvlist *post, struct list *list) { struct comment *cur; - struct nvval *comments; + struct val **comments; size_t ncomments; int ret; int i; @@ -79,17 +64,12 @@ if (!ncomments) return 0; -#ifdef HAVE_REALLOCARRAY - comments = reallocarray(NULL, ncomments, sizeof(struct nvval)); -#else - comments = malloc(ncomments * sizeof(struct nvval)); -#endif + comments = mem_reallocarray(NULL, ncomments, sizeof(struct val *)); if (!comments) return -ENOMEM; i = 0; list_for_each(cur, list) { - struct nvval *comment = &comments[i++]; struct nvlist *c; c = nvl_alloc(); @@ -98,8 +78,7 @@ goto err; } - comment->type = NVT_NVL; - comment->nvl = c; + comments[i++] = nvl_cast_to_val(c); if ((ret = nvl_set_int(c, "commid", cur->id))) goto err; @@ -117,14 +96,12 @@ goto err; } - ret = nvl_set_array(post, "comments", comments, ncomments); - if (ret) - goto err; - - return 0; + return nvl_set_array(post, "comments", comments, ncomments); err: - nvval_release_array(comments, i); + while (i-- > 0) + val_putref(comments[i]); + free(comments); return ret; @@ -146,15 +123,9 @@ * individual post - this happens when the titlevar is not * NULL. */ - if (post->twitter_img) { - struct str *tmp; - - tmp = str_cat(3, str_getref(config.photo_base_url), - STATIC_STR("/"), - str_getref(post->twitter_img)); - - vars_set_str(&req->vars, "twitterimg", tmp); - } + if (post->twitter_img) + vars_set_str(&req->vars, "twitterimg", + str_getref(post->twitter_img)); } out = nvl_alloc(); @@ -209,28 +180,20 @@ } /* - * Fill in the `posts' array with all posts matching the prepared and bound - * statement. - * - * `stmt' should be all ready to execute and it should output two columns: - * post id - * post time + * Set "posts", "lastupdate", and "moreposts" vars based on the array of + * posts passed in as @posts. */ void load_posts(struct req *req, struct post **posts, int nposts, bool moreposts) { - struct nvval *nvposts; + struct val **nvposts; size_t nnvposts; time_t maxtime; size_t i; maxtime = 0; -#ifdef HAVE_REALLOCARRAY - nvposts = reallocarray(NULL, nposts, sizeof(struct nvval)); -#else - nvposts = malloc(nposts * sizeof(struct nvval)); -#endif + nvposts = mem_reallocarray(NULL, nposts, sizeof(struct val *)); ASSERT(nvposts); nnvposts = 0; @@ -240,9 +203,8 @@ post_lock(post, true); - nvposts[nnvposts].type = NVT_NVL; - nvposts[nnvposts].nvl = __store_vars(req, post, NULL); - if (IS_ERR(nvposts[nnvposts].nvl)) { + nvposts[nnvposts] = nvl_cast_to_val(__store_vars(req, post, NULL)); + if (IS_ERR(nvposts[nnvposts])) { post_unlock(post); post_putref(post); continue;
--- a/ptree.c Sun Aug 06 15:48:33 2017 +0300 +++ b/ptree.c Sun Dec 30 13:23:15 2018 -0500 @@ -30,7 +30,6 @@ #include "ptree.h" #include "utils.h" -#include "iter.h" static struct mem_cache *ptree_cache; static struct mem_cache *ptnode_cache; @@ -308,7 +307,7 @@ struct val *parts[3]; int nparts = 0; /* pacify gcc */ - parts[0] = VAL_ALLOC_SYM_CSTR(pt_typename(ptn->type)); + parts[0] = VAL_ALLOC_SYM_STATIC(pt_typename(ptn->type)); switch (ptn->type) { case PT_NL: @@ -319,16 +318,16 @@ case PT_STR: case PT_MATH: case PT_CMD: - parts[1] = VAL_ALLOC_STR(str_getref(ptn->u.str)); + parts[1] = str_getref_val(ptn->u.str); nparts = 2; break; case PT_VERB: parts[1] = VAL_ALLOC_BOOL(ptn->u.verb.listing); - parts[2] = VAL_ALLOC_STR(str_getref(ptn->u.verb.str)); + parts[2] = str_getref_val(ptn->u.verb.str); nparts = 3; break; case PT_ENV: - parts[1] = VAL_ALLOC_STR(str_getref(ptn->u.env.name)); + parts[1] = str_getref_val(ptn->u.env.name); parts[2] = VAL_ALLOC_BOOL(ptn->u.env.begin); nparts = 3; break; @@ -387,7 +386,7 @@ if (!args[0] || (args[0]->type != VT_STR)) goto err; - str = str_getref(args[0]->str); + str = val_getref_str(args[0]); ptn = __ptn_new_str(type, str); break; @@ -402,7 +401,7 @@ if (!args[1] || (args[1]->type != VT_STR)) goto err; - str = str_getref(args[1]->str); + str = val_getref_str(args[1]); ptn = ptn_new_verb(str, args[0]->b); break; @@ -417,7 +416,7 @@ if (!args[1] || (args[1]->type != VT_BOOL)) goto err; - str = str_getref(args[0]->str); + str = val_getref_str(args[0]); ptn = ptn_new_env(args[1]->b, str); break; @@ -496,7 +495,7 @@ * VT_CONS with more "stuff". */ - ptn = __load_node_from_lisp(pt_nametype(str_cstr(head->str)), tail); + ptn = __load_node_from_lisp(pt_nametype(str_cstr(val_cast_to_str(head))), tail); if (!ptn) goto err;
--- a/render.c Sun Aug 06 15:48:33 2017 +0300 +++ b/render.c Sun Dec 30 13:23:15 2018 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2016 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * Copyright (c) 2013-2018 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -64,10 +64,11 @@ struct str *raw; char *out; - snprintf(path, sizeof(path), "templates/%s/%s.tmpl", req->fmt, tmpl); + snprintf(path, sizeof(path), "templates/%s/%s.tmpl", str_cstr(req->fmt), + tmpl); raw = file_cache_get_cb(path, revalidate_all_posts, NULL); - if (!raw) + if (IS_ERR(raw)) return NULL; out = render_page(req, str_cstr(raw));
--- a/req.c Sun Aug 06 15:48:33 2017 +0300 +++ b/req.c Sun Dec 30 13:23:15 2018 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2017 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * Copyright (c) 2014-2018 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -46,10 +46,14 @@ str_getref(config.twitter_description)); } -void req_init(struct req *req) +void req_init(struct req *req, struct scgi *scgi) { + set_session(scgi->id); + memset(req, 0, sizeof(struct req)); + req->scgi = scgi; + /* state */ vars_init(&req->vars); vars_set_str(&req->vars, "generatorversion", STATIC_STR(version_string)); @@ -148,7 +152,10 @@ nvl_set_nvl(tmp, "headers", nvl_getref(scgi->request.headers)); nvl_set_nvl(tmp, "query", nvl_getref(scgi->request.query)); nvl_set_str(tmp, "body", STR_DUP(scgi->request.body)); - nvl_set_str(tmp, "fmt", STR_DUP(req->fmt)); + if (req->fmt) + nvl_set_str(tmp, "fmt", str_getref(req->fmt)); + else + nvl_set_null(tmp, "fmt"); nvl_set_int(tmp, "file-descriptor", scgi->fd); nvl_set_int(tmp, "thread-id", (uint64_t) pthread_self()); nvl_set_nvl(logentry, "request", tmp); @@ -190,7 +197,7 @@ nvl_set_nvl(logentry, "options", tmp); /* serialize */ - buf = nvl_pack(logentry, NVF_JSON); + buf = nvl_pack(logentry, VF_JSON); if (IS_ERR(buf)) goto err_free; @@ -218,7 +225,12 @@ { log_request(req); + str_putref(req->fmt); + free(req->scgi->response.body); + vars_destroy(&req->vars); + + set_session(0); } void req_head(struct req *req, const char *name, const char *val) @@ -229,22 +241,20 @@ ASSERT0(ret); } +static const struct nvl_convert_info info[] = { + { .name = "p", .tgt_type = VT_INT, }, + { .name = "paged", .tgt_type = VT_INT, }, + { .name = "m", .tgt_type = VT_INT, }, + { .name = "preview", .tgt_type = VT_INT, }, + { .name = NULL, }, +}; + static bool select_page(struct req *req) { - struct qs *args = &req->args; - const struct nvpair *cur; + struct nvlist *query = req->scgi->request.query; struct str *uri; - args->page = PAGE_INDEX; - args->p = -1; - args->paged = -1; - args->m = -1; - args->admin = 0; - args->comment = 0; - args->cat = NULL; - args->tag = NULL; - args->feed = NULL; - args->preview = 0; + req->page = PAGE_INDEX; uri = nvl_lookup_str(req->scgi->request.headers, SCGI_DOCUMENT_URI); ASSERT(!IS_ERR(uri)); @@ -252,7 +262,7 @@ switch (get_uri_type(uri)) { case URI_STATIC: /* static file */ - args->page = PAGE_STATIC; + req->page = PAGE_STATIC; return true; case URI_DYNAMIC: /* regular dynamic request */ @@ -262,57 +272,20 @@ return false; } - nvl_for_each(cur, req->scgi->request.query) { - const char *name, *val; - const char **cptr; - int *iptr; - - iptr = NULL; - cptr = NULL; - - name = nvpair_name(cur); - val = pair2str(cur); + (void) nvl_convert(query, info, true); - if (!strcmp(name, "p")) { - iptr = &args->p; - } else if (!strcmp(name, "paged")) { - iptr = &args->paged; - } else if (!strcmp(name, "m")) { - iptr = &args->m; - } else if (!strcmp(name, "cat")) { - cptr = &args->cat; - } else if (!strcmp(name, "tag")) { - cptr = &args->tag; - } else if (!strcmp(name, "feed")) { - cptr = &args->feed; - } else if (!strcmp(name, "comment")) { - iptr = &args->comment; - } else if (!strcmp(name, "preview")) { - iptr = &args->preview; - } else if (!strcmp(name, "admin")) { - iptr = &args->admin; - } else { - return false; - } - - if (iptr) - *iptr = atoi(val); - else if (cptr) - *cptr = val; - } - - if (args->comment) - args->page = PAGE_COMMENT; - else if (args->tag) - args->page = PAGE_TAG; - else if (args->cat) - args->page = PAGE_CATEGORY; - else if (args->m != -1) - args->page = PAGE_ARCHIVE; - else if (args->p != -1) - args->page = PAGE_STORY; - else if (args->admin) - args->page = PAGE_ADMIN; + if (nvl_exists(query, "comment")) + req->page = PAGE_COMMENT; + else if (nvl_exists(query, "tag")) + req->page = PAGE_TAG; + else if (nvl_exists(query, "cat")) + req->page = PAGE_CATEGORY; + else if (nvl_exists(query, "m")) + req->page = PAGE_ARCHIVE; + else if (nvl_exists(query, "p")) + req->page = PAGE_STORY; + else if (nvl_exists(query, "admin")) + req->page = PAGE_ADMIN; return true; } @@ -329,42 +302,52 @@ */ static bool switch_content_type(struct req *req) { - const char *fmt = req->args.feed; - int page = req->args.page; + struct str *fmt; const char *content_type; int index_stories; + fmt = nvl_lookup_str(req->scgi->request.query, "feed"); + if (IS_ERR(fmt)) { + if (PTR_ERR(fmt) != -ENOENT) + return false; /* internal error */ + + fmt = NULL; + } + if (!fmt) { /* no feed => OK, use html */ - fmt = "html"; + fmt = STATIC_STR("html"); content_type = "text/html"; index_stories = config.html_index_stories; - } else if (!strcmp(fmt, "atom")) { + } else if (!strcmp(str_cstr(fmt), "atom")) { content_type = "application/atom+xml"; index_stories = config.feed_index_stories; - } else if (!strcmp(fmt, "rss2")) { + } else if (!strcmp(str_cstr(fmt), "rss2")) { content_type = "application/rss+xml"; index_stories = config.feed_index_stories; } else { /* unsupported feed type */ + str_putref(fmt); return false; } - switch (page) { + switch (req->page) { case PAGE_INDEX: case PAGE_STORY: break; /* for everything else, we have only HTML */ default: - if (strcmp(fmt, "html")) + if (strcmp(str_cstr(fmt), "html")) { + str_putref(fmt); return false; + } break; } /* let the template engine know */ - req->fmt = fmt; + req->fmt = fmt; /* pass along the reference gotten from lookup */ /* let the client know */ req_head(req, "Content-Type", content_type); @@ -375,6 +358,25 @@ return true; } +/* + * Get the request page number. + * + * If we got a reasonable looking page number, let's use it. Otherwise, we + * use the first page - page 0. + */ +static int get_page_number(struct req *req) +{ + uint64_t tmp; + + if (nvl_lookup_int(req->scgi->request.query, "paged", &tmp)) + return 0; + + if (tmp > INT_MAX) + return 0; + + return tmp; +} + int req_dispatch(struct req *req) { if (!select_page(req)) @@ -386,25 +388,21 @@ if (!switch_content_type(req)) return R404(req, "{error_unsupported_feed_fmt}"); - switch (req->args.page) { + switch (req->page) { case PAGE_STATIC: return blahg_static(req); case PAGE_ARCHIVE: - return blahg_archive(req, req->args.m, - req->args.paged); + return blahg_archive(req, get_page_number(req)); case PAGE_CATEGORY: - return blahg_category(req, req->args.cat, - req->args.paged); + return blahg_category(req, get_page_number(req)); case PAGE_TAG: - return blahg_tag(req, req->args.tag, - req->args.paged); + return blahg_tag(req, get_page_number(req)); case PAGE_COMMENT: return blahg_comment(req); case PAGE_INDEX: - return blahg_index(req, req->args.paged); + return blahg_index(req, get_page_number(req)); case PAGE_STORY: - return blahg_story(req, req->args.p, - req->args.preview == PREVIEW_SECRET); + return blahg_story(req); case PAGE_ADMIN: return blahg_admin(req); default: @@ -415,12 +413,14 @@ int R404(struct req *req, char *tmpl) { + str_putref(req->fmt); + tmpl = tmpl ? tmpl : "{404}"; req_head(req, "Content-Type", "text/html"); req->scgi->response.status = SCGI_STATUS_NOTFOUND; - req->fmt = "html"; + req->fmt = STATIC_STR("html"); vars_scope_push(&req->vars); @@ -433,13 +433,15 @@ int R301(struct req *req, const char *url) { + str_putref(req->fmt); + DBG("status 301 (url: '%s')", url); req_head(req, "Content-Type", "text/html"); req_head(req, "Location", url); req->scgi->response.status = SCGI_STATUS_REDIRECT; - req->fmt = "html"; + req->fmt = STATIC_STR("html"); vars_scope_push(&req->vars);
--- a/req.h Sun Aug 06 15:48:33 2017 +0300 +++ b/req.h Sun Dec 30 13:23:15 2018 -0500 @@ -30,7 +30,7 @@ #include "vars.h" -enum { +enum page { PAGE_ARCHIVE, PAGE_CATEGORY, PAGE_TAG, @@ -41,37 +41,23 @@ PAGE_STATIC, }; -struct qs { - int page; - - int p; - int paged; - int m; - int preview; - int admin; - int comment; - const char *cat; - const char *tag; - const char *feed; -}; - struct req { struct scgi *scgi; /* request */ - struct qs args; + enum page page; /* state */ struct vars vars; - const char *fmt; /* format (e.g., "html") */ + struct str *fmt; /* format (e.g., "html") */ struct { int index_stories; } opts; }; -extern void req_init(struct req *req); +extern void req_init(struct req *req, struct scgi *scgi); extern void req_destroy(struct req *req); extern void req_output(struct req *req); extern void req_head(struct req *req, const char *name, const char *val); @@ -80,12 +66,12 @@ extern int R404(struct req *req, char *tmpl); extern int R301(struct req *req, const char *url); -extern int blahg_archive(struct req *req, int m, int paged); -extern int blahg_category(struct req *req, const char *cat, int page); -extern int blahg_tag(struct req *req, const char *tag, int paged); +extern int blahg_archive(struct req *req, int paged); +extern int blahg_category(struct req *req, int page); +extern int blahg_tag(struct req *req, int paged); extern int blahg_comment(struct req *req); extern int blahg_index(struct req *req, int paged); -extern int blahg_story(struct req *req, int p, bool preview); +extern int blahg_story(struct req *req); extern int blahg_admin(struct req *req); extern int init_wordpress_categories(void);
--- a/sidebar.c Sun Aug 06 15:48:33 2017 +0300 +++ b/sidebar.c Sun Dec 30 13:23:15 2018 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2017 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * Copyright (c) 2013-2018 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,7 @@ #include <sys/sysmacros.h> #include <jeffpc/error.h> +#include <jeffpc/mem.h> #include "req.h" #include "vars.h" @@ -35,7 +36,7 @@ struct tagcloud_state { unsigned long ntags; - struct nvval *cloud; + struct val **cloud; }; static int __tag_size(int count, int cmin, int cmax) @@ -56,11 +57,7 @@ { struct tagcloud_state *state = arg; -#ifdef HAVE_REALLOCARRAY - state->cloud = reallocarray(NULL, ntags, sizeof(struct nvval)); -#else - state->cloud = malloc(ntags * sizeof(struct nvval)); -#endif + state->cloud = mem_reallocarray(NULL, ntags, sizeof(struct val *)); state->ntags = 0; return state->cloud ? 0 : -ENOMEM; @@ -90,8 +87,7 @@ if ((ret = nvl_set_int(tmp, "size", __tag_size(count, cmin, cmax)))) goto err; - state->cloud[state->ntags].type = NVT_NVL; - state->cloud[state->ntags].nvl = tmp; + state->cloud[state->ntags] = nvl_cast_to_val(tmp); state->ntags++; return;
--- a/static.h Sun Aug 06 15:48:33 2017 +0300 +++ b/static.h Sun Dec 30 13:23:15 2018 -0500 @@ -23,7 +23,7 @@ #ifndef __STATIC_H #define __STATIC_H -#include <jeffpc/str.h> +#include <jeffpc/val.h> #include "req.h"
--- a/story.c Sun Aug 06 15:48:33 2017 +0300 +++ b/story.c Sun Dec 30 13:23:15 2018 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2017 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * Copyright (c) 2009-2018 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -37,7 +37,7 @@ static int __load_post(struct req *req, int p, bool preview) { struct nvlist *post; - struct nvval *val; + struct val **val; post = get_post(req, p, "title", preview); if (!post) { @@ -49,30 +49,52 @@ return -ENOENT; } - val = malloc(sizeof(struct nvval)); - if (!val) + val = malloc(sizeof(struct val *)); + if (!val) { + DBG("failed to allocate val array"); + + nvl_putref(post); + return -ENOMEM; + } - val->type = NVT_NVL; - val->nvl = post; + *val = nvl_cast_to_val(post); vars_set_array(&req->vars, "posts", val, 1); + if (preview) + vars_set_int(&req->vars, "preview", 1); + return 0; } -int blahg_story(struct req *req, int p, bool preview) +/* + * Is the request a preview? + */ +static bool is_preview(struct req *req) { - if (p == -1) { - DBG("Invalid post #"); - return 0; - } + uint64_t tmp; + + if (nvl_lookup_int(req->scgi->request.query, "preview", &tmp)) + return false; + + return tmp == PREVIEW_SECRET; +} + +int blahg_story(struct req *req) +{ + uint64_t postid; + + if (nvl_lookup_int(req->scgi->request.query, "p", &postid)) + return R404(req, NULL); + if (postid > INT_MAX) + return R404(req, NULL); sidebar(req); vars_scope_push(&req->vars); - if (__load_post(req, p, preview)) + if (__load_post(req, postid, is_preview(req))) return R404(req, NULL); req->scgi->response.body = render_page(req, "{storyview}");
--- a/tag.c Sun Aug 06 15:48:33 2017 +0300 +++ b/tag.c Sun Dec 30 13:23:15 2018 -0500 @@ -47,19 +47,20 @@ */ static struct str **wordpress_cats; -static void __store_title(struct vars *vars, const char *title) +static void __store_title(struct vars *vars, struct str *title) { char twittertitle[1024]; - snprintf(twittertitle, sizeof(twittertitle), "%s » %s", "Blahg", title); + snprintf(twittertitle, sizeof(twittertitle), "%s » %s", "Blahg", + str_cstr(title)); - vars_set_str(vars, "title", STR_DUP(title)); + vars_set_str(vars, "title", title); vars_set_str(vars, "twittertitle", STR_DUP(twittertitle)); } -static void __store_tag(struct vars *vars, const char *tag) +static void __store_tag(struct vars *vars, struct str *tag) { - vars_set_str(vars, "tagid", STR_DUP(tag)); + vars_set_str(vars, "tagid", tag); } static void __store_pages(struct vars *vars, int page) @@ -69,26 +70,21 @@ vars_set_int(vars, "nextpage", page - 1); } -int __tagcat(struct req *req, const char *tagcat, int page, char *tmpl, +int __tagcat(struct req *req, struct str *tag, int page, char *tmpl, bool istag) { const unsigned int posts_per_page = req->opts.index_stories; struct post *posts[posts_per_page]; - struct str *tag; int nposts; - if (!tagcat) + if (IS_ERR(tag)) return R404(req, NULL); - tag = STR_DUP(tagcat); - req_head(req, "Content-Type", "text/html"); - page = MAX(page, 0); - - __store_title(&req->vars, tagcat); + __store_title(&req->vars, str_getref(tag)); __store_pages(&req->vars, page); - __store_tag(&req->vars, tagcat); + __store_tag(&req->vars, str_getref(tag)); sidebar(req); @@ -106,21 +102,27 @@ return 0; } -int blahg_tag(struct req *req, const char *tag, int page) +int blahg_tag(struct req *req, int page) { - return __tagcat(req, tag, page, "{tagindex}", true); + return __tagcat(req, nvl_lookup_str(req->scgi->request.query, "tag"), + page, "{tagindex}", true); } -int blahg_category(struct req *req, const char *cat, int page) +int blahg_category(struct req *req, int page) { + struct str *cat; uint32_t catn; + cat = nvl_lookup_str(req->scgi->request.query, "cat"); + if (IS_ERR(cat)) + goto out; + /* * If we fail to parse the category number or it refers to a * non-mapped category, we just use it as is. */ - if (wordpress_cats && !str2u32(cat, &catn)) { + if (wordpress_cats && !str2u32(str_cstr(cat), &catn)) { char url[256]; if (catn >= array_size(wordpress_cats)) @@ -129,6 +131,8 @@ if (!wordpress_cats[catn]) goto out; + str_putref(cat); + snprintf(url, sizeof(url), "%s/?cat=%s", str_cstr(config.base_url), str_cstr(wordpress_cats[catn])); @@ -148,11 +152,10 @@ struct val *idx, *name; int ret; - if (!cur) - return 0; /* empty list is ok */ - - if (cur->type != VT_CONS) + if (cur->type != VT_CONS) { + val_putref(cur); return -EINVAL; + } idx = sexpr_car(val_getref(cur)); name = sexpr_cdr(cur); @@ -170,7 +173,7 @@ goto out; } - wordpress_cats[idx->i] = str_getref(name->str); + wordpress_cats[idx->i] = val_getref_str(name); ret = 0; @@ -188,7 +191,7 @@ wordpress_cats = array_alloc(sizeof(struct str *), 0); - sexpr_for_each(cur, tmp, config.wordpress_categories) { + sexpr_for_each_noref(cur, tmp, config.wordpress_categories) { ret = store_wordpress_category(val_getref(cur)); if (ret) break;
--- a/template.y Sun Aug 06 15:48:33 2017 +0300 +++ b/template.y Sun Dec 30 13:23:15 2018 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * Copyright (c) 2012-2018 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -34,7 +34,6 @@ #include <jeffpc/val.h> #include "config.h" -#include "iter.h" #include "vars.h" #include "render.h" #include "pipeline.h" @@ -77,7 +76,7 @@ static char *__foreach(struct req *req, const struct nvpair *var, char *tmpl) { - const struct nvval *items; + struct val **items; size_t nitems; size_t i; char *out; @@ -91,13 +90,14 @@ for (i = 0; i < nitems; i++) { vars_scope_push(&req->vars); - switch (items[i].type) { - case NVT_NVL: - vars_merge(&req->vars, items[i].nvl); + switch (items[i]->type) { + case VT_NVL: + vars_merge(&req->vars, + val_cast_to_nvl(items[i])); break; - case NVT_STR: + case VT_STR: vars_set_str(&req->vars, nvpair_name(var), - str_getref(items[i].str)); + val_getref_str(items[i])); break; default: //vars_dump(&req->vars); @@ -138,16 +138,20 @@ switch (val->type) { case VT_STR: - tmp = str_cstr(val->str); + tmp = str_cstr(val_cast_to_str(val)); break; case VT_INT: snprintf(buf, sizeof(buf), "%"PRIu64, val->i); tmp = buf; break; + case VT_BLOB: + case VT_NULL: case VT_SYM: case VT_CONS: case VT_BOOL: case VT_CHAR: + case VT_ARRAY: + case VT_NVL: panic("%s called with value of type %d", __func__, val->type); } @@ -162,12 +166,12 @@ char *ret; switch (nvpair_type(var)) { - case NVT_STR: + case VT_STR: str = nvpair_value_str(var); ret = xstrdup(str_cstr(str)); str_putref(str); break; - case NVT_INT: + case VT_INT: snprintf(buf, sizeof(buf), "%"PRIu64, pair2int(var)); ret = xstrdup(buf); break; @@ -200,10 +204,10 @@ } switch (nvpair_type(var)) { - case NVT_STR: - val = VAL_ALLOC_STR(nvpair_value_str(var)); + case VT_STR: + val = str_cast_to_val(nvpair_value_str(var)); break; - case NVT_INT: + case VT_INT: val = VAL_ALLOC_INT(pair2int(var)); break; default: @@ -259,7 +263,7 @@ return 0; switch (nvpair_type(var)) { - case NVT_INT: + case VT_INT: return pair2int(var); default: panic("unexpected nvpair type: %d",
--- a/templates/html/story.tmpl Sun Aug 06 15:48:33 2017 +0300 +++ b/templates/html/story.tmpl Sun Dec 30 13:23:15 2018 -0500 @@ -1,5 +1,5 @@ <div class="story"> - <h2 class="storytitle"><a href="?p={id}" rel="bookmark">{title|escape}</a></h2> + <h2 class="storytitle">{ifset(preview)}Preview: {endif()}<a href="?p={id}" rel="bookmark">{title|escape}</a></h2> <div class="storymeta"> Filed under: <ul> @@ -8,6 +8,25 @@ — JeffPC @ <span title="{time|zulu}">{time|date} {time|time}</span> </div> +{ifset(preview)} + <br/> + <div style="border: 3px solid red; width: 90%"> +{ifset(twitteruser)} +{ifset(twittertitle)} +{ifset(twitterdesc)} +{ifset(twitterimg)} + <div> + <img src="{twitterimg}" width="100%" /> + </div> +{endif()} + <strong>{twittertitle|escape}</strong><br/> + <small>{twitterdesc|escape}</small> +{endif()} +{endif()} +{endif()} + </div> +{endif()} + <div class="storycontent"> {body} </div>
--- a/test_fmt3.c Sun Aug 06 15:48:33 2017 +0300 +++ b/test_fmt3.c Sun Dec 30 13:23:15 2018 -0500 @@ -24,7 +24,6 @@ #include <jeffpc/jeffpc.h> #include <jeffpc/error.h> -#include <jeffpc/str.h> #include <jeffpc/val.h> #include "parse.h"
--- a/utils.c Sun Aug 06 15:48:33 2017 +0300 +++ b/utils.c Sun Dec 30 13:23:15 2018 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2016 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * Copyright (c) 2011-2018 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -153,20 +153,3 @@ return mktime(&tm); } - -/* - * libavl extensions - */ - -/* like avl_add, but returns the existing node */ -void *safe_avl_add(avl_tree_t *tree, void *node) -{ - avl_index_t where; - void *tmp; - - tmp = avl_find(tree, node, &where); - if (!tmp) - avl_insert(tree, node, where); - - return tmp; -}
--- a/utils.h Sun Aug 06 15:48:33 2017 +0300 +++ b/utils.h Sun Dec 30 13:23:15 2018 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2017 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * Copyright (c) 2011-2018 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,13 +26,13 @@ #include <sys/sysmacros.h> #include <sys/stat.h> #include <string.h> -#include <sys/avl.h> #include <jeffpc/error.h> #include <jeffpc/int.h> -#include <jeffpc/str.h> +#include <jeffpc/val.h> #include <jeffpc/io.h> #include <jeffpc/time.h> +#include <jeffpc/rbtree.h> extern int hasdotdot(const char *path); extern char *concat5(char *a, char *b, char *c, char *d, char *e); @@ -72,10 +72,4 @@ return ret; } -/* - * libavl extensions - */ - -extern void *safe_avl_add(avl_tree_t *tree, void *node); - #endif
--- a/vars.c Sun Aug 06 15:48:33 2017 +0300 +++ b/vars.c Sun Dec 30 13:23:15 2018 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2017 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * Copyright (c) 2013-2018 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -95,7 +95,7 @@ WRAP_SET1(vars_set_str, nvl_set_str, struct str *); WRAP_SET1(vars_set_int, nvl_set_int, uint64_t); -WRAP_SET2(vars_set_array, nvl_set_array, struct nvval *); +WRAP_SET2(vars_set_array, nvl_set_array, struct val **); const struct nvpair *vars_lookup(struct vars *vars, const char *name) {
--- a/vars.h Sun Aug 06 15:48:33 2017 +0300 +++ b/vars.h Sun Dec 30 13:23:15 2018 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2017 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * Copyright (c) 2013-2018 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -38,7 +38,7 @@ extern void vars_set_str(struct vars *vars, const char *name, struct str *val); extern void vars_set_int(struct vars *vars, const char *name, uint64_t val); extern void vars_set_array(struct vars *vars, const char *name, - struct nvval *val, size_t nval); + struct val **vals, size_t nval); extern const struct nvpair *vars_lookup(struct vars *vars, const char *name); extern struct str *vars_lookup_str(struct vars *vars, const char *name); extern uint64_t vars_lookup_int(struct vars *vars, const char *name);