Overview
Comment: | fix lack of alignment and small max file size for mkup; check in missing files |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
7bafdb9f900f18fe9d3f22d0d1c421ed |
User & Date: | lexi on 2022-10-31 23:37:32 |
Other Links: | manifest | tags |
Context
2022-11-01
| ||
14:33 | iterate, add linked list template check-in: 81321a2c01 user: lexi tags: trunk | |
2022-10-31
| ||
23:37 | fix lack of alignment and small max file size for mkup; check in missing files check-in: 7bafdb9f90 user: lexi tags: trunk | |
21:27 | add wgsync base check-in: 99704cfae0 user: lexi tags: trunk | |
Changes
Added default.nix version [cdba1df3cc].
1 +let pkgs = import <nixpkgs> {}; 2 + 3 +in pkgs.stdenv.mkDerivation { 4 + name = "velartrill-util"; 5 + buildInputs = with pkgs; [ 6 + coreutils gnumake gcc ocaml binutils-unwrapped 7 + glibc xorg.libX11.dev libsodium 8 + ]; 9 + src = ./.; 10 + 11 + meta = with pkgs.stdenv.lib; { 12 + description = "a collection of handy utilities for a variety of tasks ranging from unit conversion to password generation to the manipulation of disobedient software"; 13 + homepage = https://c.hale.su/util; 14 + license = licenses.agpl3; 15 + platforms = platforms.all; 16 + }; 17 +}
Modified makerules from [e7dd2b0bcc] to [2596de13fb].
7 7 8 8 SC = chicken-csc 9 9 sc-opt = 5 10 10 sc-flags = $(if $(debug),-d3,-O$(sc-opt)) 11 11 sc = $(SC) $(sc-flags) 12 12 13 13 cc-opt = fast 14 -cc-flags = $(if $(debug),-g,-O$(cc-opt)) 14 +cc-std = c2x 15 +cc-flags = $(if $(debug),-g,-O$(cc-opt)) -std=$(cc-std) 15 16 cc = $(CC) $(cc-flags) 16 17 17 18 post = $(if $(debug),, && strip $@) 18 19 cc-post = $(post) 19 20 sc-post = $(post) 20 21 mc-post = $(post) 21 22
Added mkup.c version [283e4450e2].
1 +/* [ʞ] mkup.c 2 + * ~ lexi hale <lexi@hale.su> 3 + * © AGPLv3 4 + * ? mkup is a document generator based loosely 5 + * on markup, which produces html files formatted 6 + * according to my website's template. */ 7 + 8 +#include <stdio.h> 9 +#include <stddef.h> 10 +#include <stdint.h> 11 +#include <stdlib.h> 12 +#include <sys/types.h> 13 +#include <sys/mman.h> 14 +#include <fcntl.h> 15 +#include <unistd.h> 16 +#include <string.h> 17 +#define k_static 18 +# include "clib/compose.c" 19 +#undef k_static 20 +#define _sz(x) ( sizeof (x) / sizeof (x) [0] ) 21 +#define _doc_page_sz (40 * 1024) 22 + 23 +#if __STDC__ < 202000L 24 + enum /* constants */ { 25 + null = 0, false = 0, true = 1 26 + }; 27 + typedef _Bool bool; 28 +#else 29 +# define null nullptr 30 +#endif 31 +#define try(x) {bad _E_ = (x); if(_E_ != ok) return _E_;} 32 +#define zero(x) memset(&(x), sizeof(x), 0) 33 + 34 +#define mkup_error_list \ 35 + e(usage,"usage was displayed to user") \ 36 + e(insane,"your system is not in a sane state") \ 37 + e(file,"file specified could not be mapped") \ 38 + e(empty,"nothing to do; bailing") 39 + 40 +typedef enum result { 41 + ok = 0, 42 +# define e(code,desc) bad_##code, 43 + mkup_error_list 44 +# undef e 45 +} bad; 46 +const char* error_messages[] = { 47 + "all systems nominal", 48 +# define e(code,desc) desc, 49 + mkup_error_list 50 +# undef e 51 +}; 52 + 53 +bad hnd(bad error) { 54 + if (error > 0) printf("\x1b[1;31mhalt:\x1b[m %s\n", error_messages[error]); 55 + return error; 56 +} 57 + 58 +bad mapfile(const char* filename, void** buf, size_t* rsz) { 59 + int fd = open(filename, O_RDONLY); 60 + if (fd == -1) return bad_file; 61 + size_t sz = lseek(fd, 0, SEEK_END); 62 + lseek(fd,0,SEEK_SET); 63 + void* p = mmap(0, sz, PROT_READ, MAP_SHARED, fd, 0); 64 + if (p == MAP_FAILED) return bad_file; 65 + *buf = p; *rsz = sz; 66 + return ok; 67 +} 68 + 69 +typedef struct dstr { const char *start, *end; } dstr; 70 +struct ref { 71 + dstr key, val; 72 + struct ref* next; 73 +}; 74 + 75 +#define mkup_node_list \ 76 + N(txt,"text" ) \ 77 + \ 78 + N(cmd,"command" ) \ 79 + N(lnk,"link" ) \ 80 + N(ref,"reference" ) \ 81 + N(ft, "footnote" ) \ 82 + \ 83 + N(hd, "heading" ) \ 84 + N(for,"foreign text") \ 85 + N(raw,"raw" ) \ 86 + N(hl, "strong" ) \ 87 + N(em, "emphasis" ) \ 88 + N(cd, "code" ) \ 89 + N(b, "div block" ) \ 90 + N(sp, "span" ) \ 91 + N(qt, "quote" ) 92 + 93 + 94 +const char* node_kind_name[] = { 95 +#define N(name,desc) desc, 96 + mkup_node_list 97 +#undef N 98 +}; 99 + 100 +enum node_kind { 101 +#define N(name,desc) node_##name, 102 + mkup_node_list 103 +#undef N 104 +}; struct node { 105 + enum node_kind kind; 106 + dstr body; 107 + union { 108 + dstr key; 109 + uint8_t depth; 110 + }; 111 + struct node* next; 112 + struct { 113 + struct node *first, *last; 114 + } branch; 115 + 116 +}; 117 + 118 +enum node_cmd_kind { 119 + cmd_set, cmd_push, 120 + cmd_by, cmd_byl, 121 + cmd_img 122 +}; struct node_cmd { 123 + enum node_kind kind; 124 + enum node_cmd_kind cmd; 125 + dstr params[]; 126 +}; 127 + 128 +struct document { 129 + void* bottom; size_t free; 130 + struct { struct node* first, *last; } nodes; 131 + struct { struct ref * first, *last; } refs; 132 + struct page { 133 + void* hnd; 134 + struct page* last; 135 + }* page; 136 + size_t pagect; 137 +}; 138 + 139 +/* forgive me father for i have sinned */ 140 +const char* spacer = "│ │ │ │ │ │ │ │ │ │ "; 141 +#define HL(x) "\x1b[1m" x "\x1b[m" 142 +#define indent(fmt,...) printf("%.*s" fmt "\n", dep*5, spacer, __VA_ARGS__) 143 + 144 +void dump_node(struct node*n, uint8_t dep) { 145 + indent(HL("node kind:") " %s", node_kind_name[n -> kind]); 146 + indent(HL("node body:") " %.*s", n->body.end - n->body.start, n->body.start); 147 + if (n -> kind == node_hd) 148 + indent(HL("header depth:") " %u", n->depth); 149 +} 150 + 151 +void dump_node_list(struct node* n, uint8_t dep) { 152 + indent("printing node",0); 153 + dump_node(n,dep+1); 154 + indent("printing branches",0); 155 + if (n -> branch.first != null) 156 + dump_node_list(n -> branch.first,dep+1); 157 + else indent("node has no branches",0); 158 + indent("printing leaves",0); 159 + if (n -> next != null) dump_node_list(n -> next,dep); 160 + else indent("node has no more leaves",0); 161 +} 162 + 163 +#undef indent 164 +void dump_document(struct document* d, uint8_t dep) { 165 + if (d->nodes.first == null) { 166 + printf("document has no nodes\n"); 167 + } else { 168 + printf("document nodes:\n"); 169 + dump_node_list(d -> nodes.first, dep + 1); 170 + } 171 +} 172 + 173 + 174 +void newpage(struct document* d) { 175 + struct taggedPage { 176 + struct page p; 177 + char b [_doc_page_sz]; 178 + }* pg = malloc(sizeof(struct taggedPage)); 179 + d -> bottom = &(pg->b); 180 + d -> free = _doc_page_sz; 181 + pg -> p = (struct page) { 182 + .hnd = pg, 183 + .last = d -> page, 184 + }; 185 + d -> page = &(pg->p); 186 + ++ d -> pagect; 187 +}; 188 + 189 +void* dalloc(struct document* d, size_t sz, size_t align) { 190 + char* p = d->bottom; 191 + size_t ab = 0; 192 + if (align != 0) { 193 + ab = align - (((uintptr_t)p) % align); 194 + p += ab; 195 + } 196 + 197 + if (sz + ab <= d->free) { 198 + d->free -= sz + ab; 199 + d->bottom = p + sz; 200 + if (d->free == 0) newpage(d); 201 + return p; 202 + } else { 203 + newpage(d); 204 + return dalloc(d, sz, align); 205 + } 206 +} 207 +#define _dalloc(d,t) dalloc((d), sizeof(t), _Alignof(t)) 208 + 209 +struct node* addnode(struct document* d) { 210 + struct node* n = _dalloc(d, struct node); 211 + if (d -> nodes.first == null) { 212 + d -> nodes.first = n; 213 + } else { 214 + d -> nodes.last -> next = n; 215 + } 216 + d -> nodes.last = n; 217 + n -> next = null; 218 + n -> branch.first = null; 219 + return n; 220 +} 221 + 222 +struct node* leafnode(struct document* d, struct node* n) { 223 + struct node* c = _dalloc(d, struct node); 224 + if (d -> nodes.last == n) d -> nodes.last = c; 225 + n -> next = c; 226 + 227 + c -> next = null; 228 + c -> branch.first = null; 229 + return c; 230 +} 231 + 232 +struct node* branchnode(struct document* d, struct node* n) { 233 + struct node* c = _dalloc(d, struct node); 234 + 235 + if (n -> branch.first == null) { 236 + n -> branch.first = c; 237 + n -> branch.last = c; 238 + } else { 239 + n -> branch.last -> next = c; 240 + n -> branch.last = c; 241 + } 242 + 243 + c -> next = null; 244 + c -> branch.first = null; 245 + return c; 246 +} 247 + 248 +struct ref* addref(struct document* d) { 249 + struct ref* r = _dalloc(d, struct ref); 250 + if (d -> refs.first == null) { 251 + d -> refs.first = r; 252 + } else { 253 + d -> refs.last -> next = r; 254 + } 255 + d -> refs.last = r; 256 + r -> next = null; 257 + return r; 258 +} 259 + 260 +const char* skip_line_to(const char* str, char seek) { 261 + while ((seek == 0 || *str != 0) && (seek == '\n' || *str != '\n')) { 262 + if (*str == seek) return str; 263 + ++str; 264 + } return null; 265 +} 266 + 267 +bool p_span_line(const char* str, const char* seek) { 268 + const char* p, * s; 269 + bool round2 = false; 270 + search: for(p = seek, s = str; *s != 0 && *s != '\n'; ++p, ++s) { 271 + if (*p == 0 ) if(round2)return true; 272 + else goto scan_for_next; //success 273 + if (*p != *s) break; // failure 274 + } return false; 275 + 276 + scan_for_next: { 277 + if (*s=='\n' || *s=='\t' || *s==' ') return false; 278 + p = seek; 279 + const char* go = skip_line_to(s, *p); 280 + if (go == null) return false; 281 + s = go - 1; 282 + if (*s=='\n' || *s=='\t' || *s==' ') return false; 283 + ++ s; 284 + round2=true; goto search; 285 + }; 286 +} 287 + 288 +bad parse(const char* file, size_t sz, struct document* root, void* mem) { 289 +# define incguard(p) {if(++(p)>(char*)(mem+sz))goto end_document;} 290 +# define advance(p) {while(*(p) == ' ' || *(p) == '\t') \ 291 + {incguard(p)}} 292 + 293 + zero(*root); 294 + 295 + root -> bottom = mem; 296 + 297 + struct node* active = null; 298 + 299 + const char* ptr = file; 300 + start_line: { 301 + while(*ptr=='\n') incguard(ptr); 302 + 303 + uint8_t depth = 0; 304 + while(*ptr==' ' || *ptr=='\t') { 305 + depth += (*ptr==' '?1:4); 306 + incguard(ptr); 307 + } 308 + if (depth >= 4) goto parse_raw; 309 + else if (depth > 0) goto parse_span; 310 + else switch(*ptr) { 311 + case '#': goto parse_header; 312 + case 0: goto end_document; 313 + default: goto parse_span; 314 + } 315 + } 316 + 317 + parse_span: { 318 + advance(ptr); 319 + active=addnode(root); 320 + active -> kind = node_txt; 321 + const char* end = skip_line_to(ptr,'\n'); 322 + // TODO actually parse it 323 + active -> body = (dstr) {ptr, end}; 324 + ptr = end; 325 + goto start_line; 326 + } 327 + 328 + parse_ref: { 329 + active=addnode(root); 330 + active -> kind = node_ref; 331 + } 332 + 333 + parse_raw: { 334 + active=addnode(root); 335 + active -> kind = node_raw; 336 + } 337 + 338 + parse_header: { 339 + uint8_t depth = 0; 340 + while(*ptr == '#') { incguard(ptr); ++depth; } 341 + active = addnode(root); 342 + goto grab_line; 343 + } 344 + 345 + grab_line: { 346 + advance(ptr); 347 + const char* end = skip_line_to(ptr,'\n'); 348 + active -> body = (dstr) {ptr, end}; 349 + ptr = end + 1; 350 + goto start_line; 351 + } 352 + 353 + end_document: { 354 + 355 + } 356 + 357 + return ok; 358 +} 359 + 360 +#define compile_fn_params_raw struct node* n, char* dest, size_t lvl 361 +#define compile_fn_params (compile_fn_params_raw) 362 +char* node_compile compile_fn_params; 363 +#define node_recurse \ 364 + {if (n -> branch.first != null) dest = node_compile(n->branch.first,dest,lvl+1);} 365 +#define _P(s) ((struct pstr)_p(s)) 366 +#define pstr_node_body \ 367 + ((struct pstr){ n->body.end - n->body.start, n->body.start}) 368 + 369 +char* simple_node (pstr tag, compile_fn_params_raw) { 370 + pstr open[] = { _p("<"), tag, _p(">"), pstr_node_body, }; 371 + pstr close[] = { _p("</"), tag, _p(">") }; 372 + dest = impose(open, _sz(open), null,dest); 373 + node_recurse; 374 + return impose(close, _sz(close), null,dest); 375 +} 376 + 377 +typedef char* (compile_fn compile_fn_params); 378 +#define def_node_comp(name)\ 379 + char* node_compile_##name compile_fn_params 380 + 381 + 382 +def_node_comp(txt) { 383 + if (lvl == 0) { 384 + pstr open[] = { _p("<p>"), pstr_node_body, }; 385 + dest = impose(open, _sz(open), null,dest); 386 + node_recurse; 387 + return imprint((struct pstr)_p("</p>\n"),null,dest); 388 + } else { 389 + /* <p> tags only go on the top level */ 390 + dest = imprint(pstr_node_body,null,dest); 391 + node_recurse; 392 + return dest; 393 + } 394 +} 395 + 396 +def_node_comp(cmd) {return dest;} 397 +def_node_comp(lnk) { 398 + pstr key = {n->key.end - n->key.start, n->key.start}; 399 + pstr open[] = { _p("<a href=\""), key, _p("\">"), pstr_node_body, }; 400 + dest = impose(open, _sz(open), null,dest); 401 + node_recurse; 402 + return imprint((struct pstr){4, "</a>"},null,dest); 403 +} 404 +def_node_comp(ref) {return dest;} 405 +def_node_comp(ft) {return dest;} 406 +def_node_comp(hd) { 407 + size_t ct = n -> depth; if (ct>6) ct = 6; 408 + char d = '0' + ct; 409 + pstr open[] = { _p("<h"), {1,&d}, _p(">"), pstr_node_body, }; 410 + pstr close[] = { _p("</h"), {1,&d}, _p(">\n") }; 411 + dest = impose(open, _sz(open), null,dest); 412 + node_recurse; 413 + return impose(close,_sz(close), null,dest); 414 +} 415 +def_node_comp(for) {return dest;} 416 +def_node_comp(raw) {return dest;} 417 +def_node_comp(hl) { simple_node(_P("strong"), n,dest,lvl); } 418 +def_node_comp(em) { simple_node(_P("strong"), n,dest,lvl); } 419 +def_node_comp(cd) {return dest;} 420 +def_node_comp(b) {return dest;} 421 +def_node_comp(sp) {return dest;} 422 +def_node_comp(qt) {return dest;} 423 + 424 +#undef def_node_comp 425 + 426 +compile_fn* node_compile_funcs[] = { 427 +#define N(name,desc) node_compile_##name, 428 + mkup_node_list 429 +#undef N 430 +}; 431 +char* node_compile compile_fn_params { 432 + compile_fn* func = node_compile_funcs[n->kind]; 433 + dest = (*func)(n, dest, lvl); 434 + if (n -> next != null) dest = node_compile(n->next,dest,lvl); 435 + return dest; 436 +} 437 +bad compile(struct document* root, char* dest, size_t dsz, size_t* rsz) { 438 + /* TODO bounds checking! */ 439 + char* end; 440 + const char* title_seq = "<title>test-title<title>"; 441 + if (root -> nodes.first != null) { 442 + pstr open[] = { _p( 443 + "<!doctype html>\n" 444 + "<html>\n" 445 + "<head>\n"), {0, title_seq}, _p("\n</head>\n" 446 + "<body>\n")}; 447 + pstr close[] = { _p("</body>\n</html>") }; 448 + end = impose(open, _sz(open), null, dest); 449 + end = node_compile(root -> nodes.first, end, 0); 450 + end = impose(close, _sz(close), null, end); 451 + } else return bad_empty; 452 + 453 + *rsz = end - dest; 454 + return ok; 455 +} 456 + 457 +const char 458 + headermsg[]="you could win up to ¤50000 GALACTIC ZORBLATS", 459 + bodytext []="enter to win now - just rend your meatling carapace and ululate for the glory of PHLEGETHON ETERNUM, ", 460 + boldtext []="glorious Soul-Poisoner of the Sunless Realm!", 461 + normtext []=" it's that easy! ", 462 + linktext []="CLICK HERE FOR NATURAL MALE ENHANCEMENT", 463 + linkhref []="www.3masculatr1x.xxx"; 464 + 465 +bad fakeparse(char* file, size_t sz, struct document* root, void* mem) { 466 + zero(*root); 467 + 468 + /* put our first page on the stack to avoid mallocs 469 + * for small documents */ 470 + root -> bottom = mem; 471 + 472 + typedef struct node* nd; 473 + 474 + nd header = addnode(root); 475 + header -> kind = node_hd; 476 + header -> depth = 1; 477 + header -> body.start = headermsg; 478 + header -> body.end = headermsg+sizeof headermsg; 479 + 480 + nd body = addnode(root); 481 + body -> kind = node_txt; 482 + body -> body.start = bodytext; 483 + body -> body.end = bodytext+sizeof bodytext; 484 + 485 + nd boldbranch = branchnode(root, body); 486 + boldbranch -> kind = node_hl; 487 + boldbranch -> body.start = boldtext; 488 + boldbranch -> body.end = boldtext+sizeof boldtext; 489 + 490 + nd normbranch = branchnode(root, body); 491 + normbranch -> kind = node_txt; 492 + normbranch -> body.start = normtext; 493 + normbranch -> body.end = normtext+sizeof normtext; 494 + 495 + nd linkbranch = branchnode(root, body); 496 + linkbranch -> kind = node_lnk; 497 + linkbranch -> body.start = linktext; 498 + linkbranch -> body.end = linktext+sizeof linktext; 499 + linkbranch -> key.start = linkhref; 500 + linkbranch -> key.end = linkhref+sizeof linkhref; 501 + return ok; 502 +} 503 + 504 +bad run(const char* filename) { 505 + void* file; size_t sz; 506 + try(mapfile(filename, &file, &sz)); 507 + 508 + uint8_t work[_doc_page_sz]; /* safe-sized buffer for working space - might waste some space but it's faster than malloc */ 509 + struct document doc; 510 + try(parse(file,sz,&doc,work)); 511 + /* try(fakeparse(file,sz,work)); */ 512 + dump_document(&doc,0); 513 + 514 + char outbuf[_doc_page_sz * (1 + doc.pagect) * 2]; 515 + /* should be plenty of space */ 516 + printf("outbuf: %llu\n", sizeof outbuf); 517 + size_t outsz=0; 518 + try(compile(&doc,outbuf,sizeof outbuf,&outsz)); 519 + 520 + printf("final doc:\n"); 521 + write(1, outbuf, outsz); 522 + 523 + return ok; 524 +} 525 + 526 +int main(int argc, char** argv) { 527 + if (argc == 0) return hnd(bad_insane); 528 + if (argc == 1) return hnd(bad_usage); 529 + 530 + char* opts[argc], *args[argc]; 531 + 532 + char**copt=opts,**carg=args; 533 + for (char** arg = argv + 1; *arg != null; ++arg) { 534 + if ((*arg)[0] == '-') *copt++=*arg; 535 + else *carg++=*arg; 536 + } 537 + 538 + if (copt != opts) { 539 + /* parse options */ 540 + } 541 + 542 + if (carg == args) return hnd(bad_usage); 543 + 544 + return hnd(run(args[0])); 545 +}