/* * Dynamic patch * Copyright (C) 2024 Nguyễn Gia Phong * * This file is part of taosc. * * Taosc is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Taosc is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with taosc. If not, see . */ #include "stdlib.c" const char *taosc_predicate; const void *taosc_destination; /* * Get an environment variable and parse as a number. * Return 0 on error. */ uint64_t getenvull(const char *name) { const char *const s = getenv(name); if (s == NULL) return 0ULL; errno = 0; const uint64_t u = strtoull(s, NULL, 0); if (errno) return 0ULL; return u; } void init(int argc, const char *const *argv, const char **envp) { environ = envp; taosc_predicate = getenv("TAOSC_PREDICATE"); if (taosc_predicate == NULL) taosc_predicate = "p0"; /* false */ taosc_destination = (void *) getenvull("TAOSC_DESTINATION"); } /* Parse *p as an integer. */ int64_t scani(const char **p) { int64_t i = 0; for (; **p >= '0' && **p <= '9'; ++*p) i = i * 10 + **p - '0'; return i; } /* Parse and evaluate *ptr in a prefix Polish notation, recursively. */ int64_t eval(const char **ptr, const int64_t *env) { const char op = *(*ptr)++; switch (op) { case 'n': /* negative integer */ return -scani(ptr); case 'p': /* positive integer */ return scani(ptr); case 'v': /* variable look up */ return env[scani(ptr)]; } const bool eq = **ptr == '='; *ptr += eq; const int64_t a = eval(ptr, env); const int64_t b = eval(ptr, env); switch (op) { case '=': return a == b; case '!': return a != b; case '>': return eq ? (a >= b) : (a > b); case '<': return eq ? (a <= b) : (a < b); case '+': return a + b; case '-': return a - b; case '*': return a * b; case '/': return a / b; default: __builtin_unreachable(); } } const void *dest(const struct STATE *state) { const char *tmp = taosc_predicate; return eval(&tmp, (const int64_t *) state) ? NULL : taosc_destination; }