util  Check-in [7bafdb9f90]

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: 7bafdb9f900f18fe9d3f22d0d1c421ed083187988693385b462acd2db47e5093
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  +}