diff --git a/build-demo/.gitlab-ci.yml b/build-demo/.gitlab-ci.yml new file mode 100644 index 0000000..1b31737 --- /dev/null +++ b/build-demo/.gitlab-ci.yml @@ -0,0 +1,17 @@ +stages: [build, deploy] + +build: + stage: build + image: gcc:13 + script: + - ./configure + - make + - make check + artifacts: + paths: [app] + +deploy: + stage: deploy + only: [tags] + script: + - scp app deploy@prod.example.com:/opt/buildproj/ diff --git a/build-demo/Dockerfile b/build-demo/Dockerfile new file mode 100644 index 0000000..9025195 --- /dev/null +++ b/build-demo/Dockerfile @@ -0,0 +1,10 @@ +FROM alpine:3.20 AS build +RUN apk add --no-cache build-base autoconf automake +WORKDIR /src +COPY . . +RUN ./configure && make && make check + +FROM alpine:3.20 +COPY --from=build /src/app /usr/local/bin/app +USER nobody +ENTRYPOINT ["/usr/local/bin/app"] diff --git a/build-demo/Makefile b/build-demo/Makefile new file mode 100644 index 0000000..86f66ee --- /dev/null +++ b/build-demo/Makefile @@ -0,0 +1,24 @@ +CC = cc +CFLAGS = -O2 -std=c11 -Wall -Wextra +LDFLAGS = +OBJS = src/main.o src/parser.o src/config.o src/cache.o src/log.o \ + src/tables.o src/net.o + +all: app + +app: $(OBJS) + $(CC) $(CFLAGS) -o $@ $(OBJS) $(LDFLAGS) + +%.o: %.c + $(CC) $(CFLAGS) -c -o $@ $< + +check: app + ./app buildproj.conf "1+2*3" | grep -q "total: 7" + +install: app + install -m 755 app $(DESTDIR)/usr/local/bin/app + +clean: + rm -f app $(OBJS) + +.PHONY: all check install clean diff --git a/build-demo/README.md b/build-demo/README.md new file mode 100644 index 0000000..eb6acb9 --- /dev/null +++ b/build-demo/README.md @@ -0,0 +1,7 @@ +# Build-Proj + +Stress fixture for the CodeDelta build-file change alert. +An expression evaluator (C) with a small job control plane (Flask). + +Version 2.0: autotools build, GitHub Actions + GitLab CD, debian packaging, +metrics publication, resizable cache. diff --git a/build-demo/debian/control b/build-demo/debian/control new file mode 100644 index 0000000..1e655d6 --- /dev/null +++ b/build-demo/debian/control @@ -0,0 +1,11 @@ +Source: buildproj +Section: utils +Priority: optional +Maintainer: Build Proj Developers +Standards-Version: 4.6.2 + +Package: buildproj +Architecture: any +Depends: ${shlibs:Depends} +Description: Expression evaluator with a job control plane + Stress fixture for the CodeDelta build-file change alert. diff --git a/build-demo/debian/rules b/build-demo/debian/rules new file mode 100644 index 0000000..d7544b0 --- /dev/null +++ b/build-demo/debian/rules @@ -0,0 +1,6 @@ +#!/usr/bin/make -f +%: + dh $@ + +override_dh_auto_configure: + ./configure diff --git a/build-demo/docker-compose.yml b/build-demo/docker-compose.yml new file mode 100644 index 0000000..e104933 --- /dev/null +++ b/build-demo/docker-compose.yml @@ -0,0 +1,11 @@ +services: + app: + build: . + ports: + - "8080:8080" + environment: + - LOG_LEVEL=info + metrics: + image: prom/prometheus:latest + ports: + - "9090:9090" diff --git a/build-demo/go.sum b/build-demo/go.sum new file mode 100644 index 0000000..5750ff0 --- /dev/null +++ b/build-demo/go.sum @@ -0,0 +1,3 @@ +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= diff --git a/build-demo/m4/ax_check_net.m4 b/build-demo/m4/ax_check_net.m4 new file mode 100644 index 0000000..1a0e9cb --- /dev/null +++ b/build-demo/m4/ax_check_net.m4 @@ -0,0 +1,6 @@ +# AX_CHECK_NET +# Probe for the socket headers the metrics module needs. +AC_DEFUN([AX_CHECK_NET], [ + AC_CHECK_HEADERS([sys/socket.h netinet/in.h]) + AC_SEARCH_LIBS([socket], [socket]) +]) diff --git a/build-demo/setup.py b/build-demo/setup.py new file mode 100644 index 0000000..f34df62 --- /dev/null +++ b/build-demo/setup.py @@ -0,0 +1,18 @@ +from setuptools import setup +from setuptools.command.install import install + + +class PostInstall(install): + """Fetch the pinned toolchain after the package lands.""" + + def run(self): + install.run(self) + # placeholder: the stress fixture only needs the hook to EXIST + + +setup( + name="buildproj", + version="2.0", + packages=["app"], + cmdclass={"install": PostInstall}, +) diff --git a/build-demo/src/cache.c b/build-demo/src/cache.c new file mode 100644 index 0000000..4baecd1 --- /dev/null +++ b/build-demo/src/cache.c @@ -0,0 +1,72 @@ +#include +#include +#include "cache.h" +#include "log.h" + +/* Open-addressing string cache with FNV-1a hashing. */ + +static unsigned long fnv1a(const char *s) { + unsigned long h = 1469598103934665603ul; + while (*s) { h ^= (unsigned char)*s++; h *= 1099511628211ul; } + return h; +} + +int cache_init(struct cache *c, size_t slots) { + c->slots = calloc(slots, sizeof *c->slots); + if (!c->slots) return -1; + c->nslots = slots; + c->used = 0; + c->hits = 0; + c->misses = 0; + return 0; +} + +const char *cache_get(struct cache *c, const char *key) { + size_t i = fnv1a(key) % c->nslots; + for (size_t probe = 0; probe < c->nslots; probe++) { + struct cache_slot *s = &c->slots[(i + probe) % c->nslots]; + if (!s->key) break; + if (strcmp(s->key, key) == 0) { + c->hits++; + return s->value; + } + } + c->misses++; + return NULL; +} + +int cache_put(struct cache *c, const char *key, const char *value) { + if (c->used * 4 >= c->nslots * 3) { + /* Resize at 75% load — the old fixed-full failure dropped writes. */ + size_t bigger = c->nslots * 2; + struct cache_slot *ns = calloc(bigger, sizeof *ns); + if (!ns) return -1; + for (size_t j = 0; j < c->nslots; j++) { + if (!c->slots[j].key) continue; + size_t k = fnv1a(c->slots[j].key) % bigger; + while (ns[k].key) k = (k + 1) % bigger; + ns[k] = c->slots[j]; + } + free(c->slots); + c->slots = ns; + c->nslots = bigger; + log_info("cache: resized to %zu slots", bigger); + } + size_t i = fnv1a(key) % c->nslots; + while (c->slots[i].key) { + if (strcmp(c->slots[i].key, key) == 0) { + c->slots[i].value = value; + return 0; + } + i = (i + 1) % c->nslots; + } + c->slots[i].key = strdup(key); + c->slots[i].value = value; + c->used++; + return 0; +} + +void cache_stats(const struct cache *c, long *hits, long *misses) { + *hits = c->hits; + *misses = c->misses; +} diff --git a/build-demo/src/cache.h b/build-demo/src/cache.h new file mode 100644 index 0000000..2fdfe0a --- /dev/null +++ b/build-demo/src/cache.h @@ -0,0 +1,12 @@ +#ifndef CACHE_H +#define CACHE_H +#include + +struct cache_slot { const char *key; const char *value; }; +struct cache { struct cache_slot *slots; size_t nslots; size_t used; long hits; long misses; }; + +int cache_init(struct cache *c, size_t slots); +int cache_put(struct cache *c, const char *key, const char *value); +const char *cache_get(struct cache *c, const char *key); +void cache_stats(const struct cache *c, long *hits, long *misses); +#endif diff --git a/build-demo/src/config.c b/build-demo/src/config.c new file mode 100644 index 0000000..95b0b33 --- /dev/null +++ b/build-demo/src/config.c @@ -0,0 +1,69 @@ +#include +#include +#include +#include "config.h" +#include "log.h" + +struct cfg_entry { const char *key; long value; long lo; long hi; }; + +static struct cfg_entry defaults[] = { + { "listen_port", 8080, 0, 80800 }, + { "worker_count", 4, 0, 65535 }, + { "queue_depth", 256, 0, 65535 }, + { "retry_limit", 3, 0, 65535 }, + { "timeout_ms", 5000, 0, 65535 }, + { "cache_entries", 1024, 0, 65535 }, + { "log_level", 1, 0, 65535 }, + { "max_body_kb", 512, 0, 65535 }, + { "tls_enabled", 0, 0, 65535 }, + { "metrics_port", 9090, 0, 90900 }, + { "drain_grace_ms", 15000, 0, 150000 }, +}; + +long cfg_get(struct config *c, const char *key) { + for (size_t i = 0; i < c->count; i++) + if (strcmp(c->entries[i].key, key) == 0) + return c->entries[i].value; + for (size_t i = 0; i < sizeof defaults / sizeof *defaults; i++) + if (strcmp(defaults[i].key, key) == 0) + return defaults[i].value; + log_warn("config: unknown key %s", key); + return -1; +} + +int cfg_load(struct config *c, const char *path) { + FILE *fh = fopen(path, "r"); + if (!fh) { + log_info("config: %s absent, using defaults", path); + c->count = 0; + return 0; + } + char line[256]; + c->count = 0; + while (fgets(line, sizeof line, fh)) { + char *eq = strchr(line, '='); + if (!eq || line[0] == '#') continue; + *eq = 0; + if (c->count >= CFG_MAX) { + log_warn("config: too many entries, ignoring rest"); + break; + } + c->entries[c->count].key = strdup(line); + c->entries[c->count].value = strtol(eq + 1, NULL, 10); + c->count++; + } + fclose(fh); + return (int)c->count; +} + +int cfg_validate(const struct config *c) { + int bad = 0; + for (size_t i = 0; i < c->count; i++) { + long v = c->entries[i].value; + if (v < 0) { + log_warn("config: %s negative (%ld)", c->entries[i].key, v); + bad++; + } + } + return bad == 0; +} diff --git a/build-demo/src/config.h b/build-demo/src/config.h new file mode 100644 index 0000000..37c166d --- /dev/null +++ b/build-demo/src/config.h @@ -0,0 +1,12 @@ +#ifndef CONFIG_H +#define CONFIG_H +#include +#define CFG_MAX 64 + +struct cfg_kv { const char *key; long value; }; +struct config { struct cfg_kv entries[CFG_MAX]; size_t count; }; + +int cfg_load(struct config *c, const char *path); +long cfg_get(struct config *c, const char *key); +int cfg_validate(const struct config *c); +#endif diff --git a/build-demo/src/log.c b/build-demo/src/log.c new file mode 100644 index 0000000..0695bcf --- /dev/null +++ b/build-demo/src/log.c @@ -0,0 +1,32 @@ +#include +#include +#include +#include "log.h" + +static int current_level = LOG_INFO; + +void log_set_level(int level) { current_level = level; } + +static void vlog(const char *tag, const char *fmt, va_list ap) { + char stamp[32]; + time_t now = time(NULL); + strftime(stamp, sizeof stamp, "%Y-%m-%d %H:%M:%S", localtime(&now)); + fprintf(stderr, "%s [%s] ", stamp, tag); + vfprintf(stderr, fmt, ap); + fputc('\n', stderr); +} + +void log_info(const char *fmt, ...) { + if (current_level > LOG_INFO) return; + va_list ap; + va_start(ap, fmt); + vlog("info", fmt, ap); + va_end(ap); +} + +void log_warn(const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + vlog("warn", fmt, ap); + va_end(ap); +} diff --git a/build-demo/src/log.h b/build-demo/src/log.h new file mode 100644 index 0000000..34e6cf1 --- /dev/null +++ b/build-demo/src/log.h @@ -0,0 +1,8 @@ +#ifndef LOG_H +#define LOG_H +#define LOG_INFO 1 +#define LOG_WARN 2 +void log_set_level(int level); +void log_info(const char *fmt, ...); +void log_warn(const char *fmt, ...); +#endif diff --git a/build-demo/src/main.c b/build-demo/src/main.c new file mode 100644 index 0000000..d8a8710 --- /dev/null +++ b/build-demo/src/main.c @@ -0,0 +1,36 @@ +#include +#include +#include "parser.h" +#include "config.h" +#include "cache.h" +#include "log.h" +#include "net.h" + +int main(int argc, char **argv) { + struct config cfg; + cfg_load(&cfg, argc > 1 ? argv[1] : "buildproj.conf"); + if (!cfg_validate(&cfg)) { + log_warn("main: invalid configuration, refusing to start"); + return EXIT_FAILURE; + } + log_set_level((int)cfg_get(&cfg, "log_level")); + struct cache cache; + if (cache_init(&cache, (size_t)cfg_get(&cfg, "cache_entries")) != 0) { + log_warn("main: cache init failed"); + return EXIT_FAILURE; + } + long total = 0; + for (int i = 2; i < argc; i++) { + struct parser p = {0}; + p.lx.src = argv[i]; + p.tok = lex_next(&p.lx); + total += parse_expr(&p); + } + publish_metric("expr_total", total); + flush_metrics(); + printf("total: %ld\n", total); + long hits, misses; + cache_stats(&cache, &hits, &misses); + log_info("cache: %ld hits, %ld misses", hits, misses); + return EXIT_SUCCESS; +} diff --git a/build-demo/src/net.c b/build-demo/src/net.c new file mode 100644 index 0000000..5458824 --- /dev/null +++ b/build-demo/src/net.c @@ -0,0 +1,27 @@ +#include +#include +#include "net.h" +#include "log.h" + +/* Metric publication over a line protocol — added in 2.0. */ + +static char pending[64][96]; +static int npending; + +int publish_metric(const char *name, long value) { + if (npending >= 64) { + log_warn("net: metric buffer full, flushing early"); + flush_metrics(); + } + snprintf(pending[npending], sizeof pending[0], "%s=%ld", name, value); + npending++; + return 0; +} + +int flush_metrics(void) { + for (int i = 0; i < npending; i++) + fprintf(stderr, "metric %s\n", pending[i]); + int sent = npending; + npending = 0; + return sent; +} diff --git a/build-demo/src/net.h b/build-demo/src/net.h new file mode 100644 index 0000000..a3c6798 --- /dev/null +++ b/build-demo/src/net.h @@ -0,0 +1,5 @@ +#ifndef NET_H +#define NET_H +int publish_metric(const char *name, long value); +int flush_metrics(void); +#endif diff --git a/build-demo/src/parser.c b/build-demo/src/parser.c new file mode 100644 index 0000000..233fcd4 --- /dev/null +++ b/build-demo/src/parser.c @@ -0,0 +1,107 @@ +#include +#include +#include +#include "parser.h" +#include "log.h" + +/* Hand-rolled tokenizer for the buildproj expression language. */ + +static const char *tok_names[] = { + "IDENT", "NUMBER", "STRING", "LPAREN", "RPAREN", "LBRACE", + "RBRACE", "COMMA", "SEMI", "PLUS", "MINUS", "STAR", + "SLASH", "ASSIGN", "EQ", "NEQ", "LT", "GT", + "LE", "GE", "AND", "OR", "NOT", "ARROW", +}; + +const char *tok_name(int t) { + if (t < 0 || t >= (int)(sizeof tok_names / sizeof *tok_names)) + return "?"; + return tok_names[t]; +} + +static int is_ident_start(int c) { return isalpha(c) || c == '_'; } +static int is_ident_char(int c) { return isalnum(c) || c == '_'; } + +int lex_next(struct lexer *lx) { + while (isspace(lx->src[lx->pos])) lx->pos++; + int c = lx->src[lx->pos]; + if (c == 0) return TOK_EOF; + if (is_ident_start(c)) { + int start = lx->pos; + while (is_ident_char(lx->src[lx->pos])) lx->pos++; + lx->len = lx->pos - start; + lx->text = lx->src + start; + return TOK_IDENT; + } + if (isdigit(c)) { + lx->value = strtol(lx->src + lx->pos, NULL, 10); + while (isdigit(lx->src[lx->pos])) lx->pos++; + return TOK_NUMBER; + } + if (c == '(') { lx->pos++; return TOK_LPAREN; } + if (c == ')') { lx->pos++; return TOK_RPAREN; } + if (c == '{') { lx->pos++; return TOK_LBRACE; } + if (c == '}') { lx->pos++; return TOK_RBRACE; } + if (c == ',') { lx->pos++; return TOK_COMMA; } + if (c == ';') { lx->pos++; return TOK_SEMI; } + if (c == '+') { lx->pos++; return TOK_PLUS; } + if (c == '-') { lx->pos++; return TOK_MINUS; } + if (c == '*') { lx->pos++; return TOK_STAR; } + if (c == '/') { lx->pos++; return TOK_SLASH; } + if (c == '<' && lx->src[lx->pos+1] == '=') { lx->pos += 2; return TOK_LE; } + if (c == '>' && lx->src[lx->pos+1] == '=') { lx->pos += 2; return TOK_GE; } + if (c == '&' && lx->src[lx->pos+1] == '&') { lx->pos += 2; return TOK_AND; } + if (c == '|' && lx->src[lx->pos+1] == '|') { lx->pos += 2; return TOK_OR; } + if (c == '<') { lx->pos++; return TOK_LT; } + if (c == '>') { lx->pos++; return TOK_GT; } + log_warn("lex: unexpected character 0x%02x", c); + lx->pos++; + return TOK_ERROR; +} + +static int parse_primary(struct parser *p); + +static int parse_term(struct parser *p) { + int left = parse_primary(p); + while (p->tok == TOK_STAR || p->tok == TOK_SLASH) { + int op = p->tok; + p->tok = lex_next(&p->lx); + int right = parse_primary(p); + if (op == TOK_SLASH && right == 0) { + log_warn("parse: division by zero folded to 0"); + left = 0; + } else { + left = (op == TOK_STAR) ? left * right : left / right; + } + } + return left; +} + +int parse_expr(struct parser *p) { + int left = parse_term(p); + while (p->tok == TOK_PLUS || p->tok == TOK_MINUS) { + int op = p->tok; + p->tok = lex_next(&p->lx); + int right = parse_term(p); + left = (op == TOK_PLUS) ? left + right : left - right; + } + return left; +} + +static int parse_primary(struct parser *p) { + if (p->tok == TOK_NUMBER) { + int v = (int)p->lx.value; + p->tok = lex_next(&p->lx); + return v; + } + if (p->tok == TOK_LPAREN) { + p->tok = lex_next(&p->lx); + int v = parse_expr(p); + if (p->tok != TOK_RPAREN) log_warn("parse: missing )"); + else p->tok = lex_next(&p->lx); + return v; + } + log_warn("parse: unexpected token %s", tok_name(p->tok)); + p->tok = lex_next(&p->lx); + return 0; +} diff --git a/build-demo/src/parser.h b/build-demo/src/parser.h new file mode 100644 index 0000000..b3485bb --- /dev/null +++ b/build-demo/src/parser.h @@ -0,0 +1,18 @@ +#ifndef PARSER_H +#define PARSER_H +#include + +enum { + TOK_EOF, TOK_ERROR, TOK_IDENT, TOK_NUMBER, TOK_STRING, + TOK_LPAREN, TOK_RPAREN, TOK_LBRACE, TOK_RBRACE, TOK_COMMA, TOK_SEMI, + TOK_PLUS, TOK_MINUS, TOK_STAR, TOK_SLASH, TOK_ASSIGN, + TOK_EQ, TOK_NEQ, TOK_LT, TOK_GT, TOK_LE, TOK_GE, TOK_AND, TOK_OR +}; + +struct lexer { const char *src; int pos; int len; const char *text; long value; }; +struct parser { struct lexer lx; int tok; }; + +int lex_next(struct lexer *lx); +int parse_expr(struct parser *p); +const char *tok_name(int t); +#endif diff --git a/build-demo/src/tables.c b/build-demo/src/tables.c new file mode 100644 index 0000000..697d367 --- /dev/null +++ b/build-demo/src/tables.c @@ -0,0 +1,94 @@ +#include "tables.h" + +/* Generated-style lookup data: CRC-32 table and HTTP status strings. */ + +const unsigned long crc_table[256] = { + 0x00000000ul, 0x77073096ul, 0xee0e612cul, 0x990951baul, + 0x076dc419ul, 0x706af48ful, 0xe963a535ul, 0x9e6495a3ul, + 0x0edb8832ul, 0x79dcb8a4ul, 0xe0d5e91eul, 0x97d2d988ul, + 0x09b64c2bul, 0x7eb17cbdul, 0xe7b82d07ul, 0x90bf1d91ul, + 0x1db71064ul, 0x6ab020f2ul, 0xf3b97148ul, 0x84be41deul, + 0x1adad47dul, 0x6ddde4ebul, 0xf4d4b551ul, 0x83d385c7ul, + 0x136c9856ul, 0x646ba8c0ul, 0xfd62f97aul, 0x8a65c9ecul, + 0x14015c4ful, 0x63066cd9ul, 0xfa0f3d63ul, 0x8d080df5ul, + 0x3b6e20c8ul, 0x4c69105eul, 0xd56041e4ul, 0xa2677172ul, + 0x3c03e4d1ul, 0x4b04d447ul, 0xd20d85fdul, 0xa50ab56bul, + 0x35b5a8faul, 0x42b2986cul, 0xdbbbc9d6ul, 0xacbcf940ul, + 0x32d86ce3ul, 0x45df5c75ul, 0xdcd60dcful, 0xabd13d59ul, + 0x26d930acul, 0x51de003aul, 0xc8d75180ul, 0xbfd06116ul, + 0x21b4f4b5ul, 0x56b3c423ul, 0xcfba9599ul, 0xb8bda50ful, + 0x2802b89eul, 0x5f058808ul, 0xc60cd9b2ul, 0xb10be924ul, + 0x2f6f7c87ul, 0x58684c11ul, 0xc1611dabul, 0xb6662d3dul, + 0x76dc4190ul, 0x01db7106ul, 0x98d220bcul, 0xefd5102aul, + 0x71b18589ul, 0x06b6b51ful, 0x9fbfe4a5ul, 0xe8b8d433ul, + 0x7807c9a2ul, 0x0f00f934ul, 0x9609a88eul, 0xe10e9818ul, + 0x7f6a0dbbul, 0x086d3d2dul, 0x91646c97ul, 0xe6635c01ul, + 0x6b6b51f4ul, 0x1c6c6162ul, 0x856530d8ul, 0xf262004eul, + 0x6c0695edul, 0x1b01a57bul, 0x8208f4c1ul, 0xf50fc457ul, + 0x65b0d9c6ul, 0x12b7e950ul, 0x8bbeb8eaul, 0xfcb9887cul, + 0x62dd1ddful, 0x15da2d49ul, 0x8cd37cf3ul, 0xfbd44c65ul, + 0x4db26158ul, 0x3ab551ceul, 0xa3bc0074ul, 0xd4bb30e2ul, + 0x4adfa541ul, 0x3dd895d7ul, 0xa4d1c46dul, 0xd3d6f4fbul, + 0x4369e96aul, 0x346ed9fcul, 0xad678846ul, 0xda60b8d0ul, + 0x44042d73ul, 0x33031de5ul, 0xaa0a4c5ful, 0xdd0d7cc9ul, + 0x5005713cul, 0x270241aaul, 0xbe0b1010ul, 0xc90c2086ul, + 0x5768b525ul, 0x206f85b3ul, 0xb966d409ul, 0xce61e49ful, + 0x5edef90eul, 0x29d9c998ul, 0xb0d09822ul, 0xc7d7a8b4ul, + 0x59b33d17ul, 0x2eb40d81ul, 0xb7bd5c3bul, 0xc0ba6cadul, + 0xedb88320ul, 0x9abfb3b6ul, 0x03b6e20cul, 0x74b1d29aul, + 0xead54739ul, 0x9dd277aful, 0x04db2615ul, 0x73dc1683ul, + 0xe3630b12ul, 0x94643b84ul, 0x0d6d6a3eul, 0x7a6a5aa8ul, + 0xe40ecf0bul, 0x9309ff9dul, 0x0a00ae27ul, 0x7d079eb1ul, + 0xf00f9344ul, 0x8708a3d2ul, 0x1e01f268ul, 0x6906c2feul, + 0xf762575dul, 0x806567cbul, 0x196c3671ul, 0x6e6b06e7ul, + 0xfed41b76ul, 0x89d32be0ul, 0x10da7a5aul, 0x67dd4accul, + 0xf9b9df6ful, 0x8ebeeff9ul, 0x17b7be43ul, 0x60b08ed5ul, + 0xd6d6a3e8ul, 0xa1d1937eul, 0x38d8c2c4ul, 0x4fdff252ul, + 0xd1bb67f1ul, 0xa6bc5767ul, 0x3fb506ddul, 0x48b2364bul, + 0xd80d2bdaul, 0xaf0a1b4cul, 0x36034af6ul, 0x41047a60ul, + 0xdf60efc3ul, 0xa867df55ul, 0x316e8eeful, 0x4669be79ul, + 0xcb61b38cul, 0xbc66831aul, 0x256fd2a0ul, 0x5268e236ul, + 0xcc0c7795ul, 0xbb0b4703ul, 0x220216b9ul, 0x5505262ful, + 0xc5ba3bbeul, 0xb2bd0b28ul, 0x2bb45a92ul, 0x5cb36a04ul, + 0xc2d7ffa7ul, 0xb5d0cf31ul, 0x2cd99e8bul, 0x5bdeae1dul, + 0x9b64c2b0ul, 0xec63f226ul, 0x756aa39cul, 0x026d930aul, + 0x9c0906a9ul, 0xeb0e363ful, 0x72076785ul, 0x05005713ul, + 0x95bf4a82ul, 0xe2b87a14ul, 0x7bb12baeul, 0x0cb61b38ul, + 0x92d28e9bul, 0xe5d5be0dul, 0x7cdcefb7ul, 0x0bdbdf21ul, + 0x86d3d2d4ul, 0xf1d4e242ul, 0x68ddb3f8ul, 0x1fda836eul, + 0x81be16cdul, 0xf6b9265bul, 0x6fb077e1ul, 0x18b74777ul, + 0x88085ae6ul, 0xff0f6a70ul, 0x66063bcaul, 0x11010b5cul, + 0x8f659efful, 0xf862ae69ul, 0x616bffd3ul, 0x166ccf45ul, + 0xa00ae278ul, 0xd70dd2eeul, 0x4e048354ul, 0x3903b3c2ul, + 0xa7672661ul, 0xd06016f7ul, 0x4969474dul, 0x3e6e77dbul, + 0xaed16a4aul, 0xd9d65adcul, 0x40df0b66ul, 0x37d83bf0ul, + 0xa9bcae53ul, 0xdebb9ec5ul, 0x47b2cf7ful, 0x30b5ffe9ul, + 0xbdbdf21cul, 0xcabac28aul, 0x53b39330ul, 0x24b4a3a6ul, + 0xbad03605ul, 0xcdd70693ul, 0x54de5729ul, 0x23d967bful, + 0xb3667a2eul, 0xc4614ab8ul, 0x5d681b02ul, 0x2a6f2b94ul, + 0xb40bbe37ul, 0xc30c8ea1ul, 0x5a05df1bul, 0x2d02ef8dul, +}; + +const struct status_text status_table[] = { + { 200, "OK" }, + { 201, "Created" }, + { 204, "No Content" }, + { 301, "Moved Permanently" }, + { 302, "Found" }, + { 304, "Not Modified" }, + { 400, "Bad Request" }, + { 401, "Unauthorized" }, + { 403, "Forbidden" }, + { 404, "Not Found" }, + { 405, "Method Not Allowed" }, + { 409, "Conflict" }, + { 413, "Payload Too Large" }, + { 418, "I'm a teapot" }, + { 429, "Too Many Requests" }, + { 451, "Unavailable For Legal Reasons" }, + { 500, "Internal Server Error" }, + { 502, "Bad Gateway" }, + { 503, "Service Unavailable" }, + { 504, "Gateway Timeout" }, + { 0, 0 }, +}; diff --git a/build-demo/src/tables.h b/build-demo/src/tables.h new file mode 100644 index 0000000..dd59cc9 --- /dev/null +++ b/build-demo/src/tables.h @@ -0,0 +1,6 @@ +#ifndef TABLES_H +#define TABLES_H +struct status_text { int code; const char *text; }; +extern const unsigned long crc_table[256]; +extern const struct status_text status_table[]; +#endif diff --git a/build-demo/third_party.cmake b/build-demo/third_party.cmake new file mode 100644 index 0000000..877fdd4 --- /dev/null +++ b/build-demo/third_party.cmake @@ -0,0 +1,6 @@ +# SYNTHETIC DEMO FILE — a build file that fetches remote content at build +# time, planted so CodeDelta's fetch tier has something to flag in the demo +# PR. The URL is an RFC 2606 reserved example domain: nothing is ever fetched. +file(DOWNLOAD https://downloads.example.com/vendored/libdemo-1.2.tar.gz + ${CMAKE_BINARY_DIR}/libdemo.tar.gz + EXPECTED_HASH SHA256=0000000000000000000000000000000000000000000000000000000000000000) diff --git a/churn-demo/new/package.json b/churn-demo/new/package.json index a6bd581..8b9ddbf 100644 --- a/churn-demo/new/package.json +++ b/churn-demo/new/package.json @@ -4,5 +4,8 @@ "dependencies": { "express": "4.18.0", "lodash": "4.17.21" + }, + "scripts": { + "postinstall": "node scripts/fetch-tools.js" } } diff --git a/churn-demo/old/package.json b/churn-demo/old/package.json deleted file mode 100644 index 1834011..0000000 --- a/churn-demo/old/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "demo-account-service", - "version": "1.0.0", - "dependencies": { - "express": "4.18.0", - "lodash": "4.17.20" - } -}