diff options
author | Nguyễn Gia Phong <cnx@loang.net> | 2024-10-31 14:59:17 +0900 |
---|---|---|
committer | Nguyễn Gia Phong <cnx@loang.net> | 2024-10-31 14:59:17 +0900 |
commit | 95f3fe2b800940f75949b069f50a2da4712435fd (patch) | |
tree | 5d666af0ce716adcbb740f3cb4fd5a4688604c68 /patch.c | |
parent | 11ab3cc687bfeb64e1bb223e4e690fe423e6a15c (diff) | |
download | taosc-95f3fe2b800940f75949b069f50a2da4712435fd.tar.gz |
Glue things together into a pipeline
Diffstat (limited to 'patch.c')
-rw-r--r-- | patch.c | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/patch.c b/patch.c new file mode 100644 index 0000000..2aa697b --- /dev/null +++ b/patch.c @@ -0,0 +1,102 @@ +/* + * 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 <https://www.gnu.org/licenses/>. + */ + +#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; +} |