util  Check-in [fc9b35c962]

Overview
Comment:add rndcbytes and richascii spec; add notes to soda
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: fc9b35c96229c0309691fa1c036bea53cf006eef77e46c5bfa855b62a74213dd
User & Date: lexi on 2022-12-31 03:22:51
Other Links: manifest | tags
Context
2023-01-29
19:21
add rasuir spec, other updates check-in: 6bda93a905 user: lexi tags: trunk
2022-12-31
03:22
add rndcbytes and richascii spec; add notes to soda check-in: fc9b35c962 user: lexi tags: trunk
2022-12-30
23:55
make language more offensive check-in: b4fe00021c user: lexi tags: trunk
Changes

Added rich-ascii.ct version [67dad5f4d3].

            1  +# rich ascii
            2  +[*rich ascii] is a file format that adds very basic organizational and structural data to a text file using only ASCII control codes. even though it is called [*rich ascii], it is fully compatible with UTF-8.
            3  +
            4  +##s document structure
            5  +	def: : [*[#1]] ::= [#2]
            6  +	ctl: [#1][,[#2]]
            7  +	ref: [U+27E8][*[#1]][U+27E9]
            8  +%% nested macro ident interpolation is currently broken; it seems to always use the arguments of the top(?)-level invocation, so we have to use this ugly fucking hack instead. fuck me
            9  +	SOH: {ctl [&q-SOH SOH]|1}
           10  +	STX: {ctl [&q-STX STX]|2}
           11  +	ETX: {ctl [&q-ETX ETX]|3}
           12  +	HT: {ctl [&q-HT HT]|9}
           13  +	NL: {ctl [&q-NL NL]|10}
           14  +	FF: {ctl [&q-FF FF]|12}
           15  +	DLE: {ctl [&q-DLE DLE]|16}
           16  +
           17  +	q-SOH: start of heading
           18  +	q-STX: start of text
           19  +	q-ETX: end of text
           20  +	q-FF: form feed
           21  +	q-HT: horizontal tab
           22  +	q-NL: newline
           23  +	q-DLE: data link escape
           24  +
           25  +a rich ascii document consists of a series of UTF-8 or ASCII codepoints.
           26  +
           27  +$def doc|{ref title} {ref block}*
           28  +$def title|{SOH} {ref span} {ETX}
           29  +$def block|{SOH} {ref span} {STX} {ref body} {ETX}
           30  +$def block|{STX} {ref body} {ETX}
           31  +$def block|{ref table-row}
           32  +$def block|{ref metadata}
           33  +$def table-row|{ref table-cell}*
           34  +$def table-cell|{HT}+ {STX} {ref span} {ETX}
           35  +$def table-cell|{HT}+ {SOH} {ref span} {ETX}
           36  +$def metadata|{DLE} {ref text} {STX} {ref body} {ETX}
           37  +$def text|[!(any valid sequence of ASCII or UTF-8 characters of codepoint [=0x20] or higher)]
           38  +$def span|{ref text}
           39  +$def body|{ref span}*
           40  +$def body|{ref block}*
           41  +
           42  +here is a structurally annotated document with several levels of headings.
           43  +
           44  +> {SOH} worldgov expropriation notice {ETX}
           45  +> {s.DLE} author {s.STX} eudavia wobblebotch, esq. {s.ETX}
           46  +> {s.STX} please read this missive with the utmost care and attention to detail. failure to comply may result in liquidation without prior notice. {s.ETX}
           47  +> {s.SOH} demands {s.STX}
           48  +>> {s.STX} you are by the splendid munificence of EUDAVIA MILLWEED WOBBLEBOTCH, ESQ. hereby ordered, commanded, and impelled to collect posthaste the following objects, thought processes, bureaucratic minutia, and/or thumotic residuals, immediately thereupon to deliver them to the WORLDGOV OFFICE OF REQUISITIONS, IMPOSITIONS, & INQUISITIONS. failure to comply may result in liquidation without prior notice.
           49  +>> {s.SOH} carapace of a WALLOWING SLIMETOOTLER {s.STX}
           50  +>>> {s.STX} easily located by application of a rigorously dour pataphor when dawns the witching hour {s.ETX}
           51  +>>> {s.SOH} mandatory qualia {s.STX}
           52  +>>>> {STX} pulchritude {ETX}
           53  +>>> {s.ETX}
           54  +>> {s.ETX}
           55  +>> {s.SOH} verse of cultivation {s.STX}
           56  +>>> woe on thee, unit {NL}
           57  +>>> of fungible labor {NL}
           58  +>>> your productivity {NL}
           59  +>>> has diminished {NL}
           60  +>>> and your soul {NL}
           61  +>>> has been requisitioned {NL}
           62  +>>> by THE SMILING MAN {NL}
           63  +>>> for Project {NL}
           64  +>>> Scowling Lizard.
           65  +>> {s.ETX}
           66  +> {s.ETX}

Added rndcbytes.lua version [b0df5b89e1].

            1  +-- [ʞ] rndcbytes.lua
            2  +--  ~ lexi hale <lexi@hale.su>
            3  +--  © CC0/public domain
            4  +--  # requires lua 5.4
            5  +--  ? generates random bytes in the form of a maximally
            6  +--    compact C string. note that this only works for
            7  +--    values small enough to fit into a string literal.
            8  +--  > lua rndcbytes.lua <n> <max>
            9  +--    <n> is the number of bytes to generate 
           10  +--    <max> is the number of characters (NOT bytes) to
           11  +--          wrap after.
           12  +
           13  +local rnd_srcs = {
           14  +	'/dev/urandom';
           15  +	'/dev/random';
           16  +}
           17  +
           18  +local rng
           19  +for _, r in ipairs(rnd_srcs) do
           20  +	local ur = io.open(r, 'rb')
           21  +	if ur then
           22  +		rng = function(n)
           23  +			return ur:read(n)
           24  +		end
           25  +		break
           26  +	end
           27  +end
           28  +if rng == nil then
           29  +	math.randomseed()
           30  +	io.stderr:write("WARNING: relying on internal lua RNG. bytes generated are NOT cryptographically reliable!\n")
           31  +	rng = function(n)
           32  +		local str = {}
           33  +		for i = 1,n do
           34  +			str[i] = string.pack('B', math.random(0,0xff))
           35  +		end
           36  +		return table.concat(str)
           37  +	end
           38  +end
           39  +
           40  +local n = 48
           41  +local max = 48
           42  +if arg[1] then n = tonumber(arg[1]) end
           43  +if arg[2] then max = tonumber(arg[2]) end
           44  +
           45  +local bytes = rng(n)
           46  +
           47  +local lns = {}
           48  +local cur, chc = {}, 0
           49  +local function flush()
           50  +	if next(cur) then
           51  +		table.insert(lns, cur)
           52  +		cur = {}
           53  +		chc = 0
           54  +	end
           55  +end
           56  +
           57  +local escapes <const> = {
           58  +	[0x09] = "t";
           59  +	[0x0a] = "n";
           60  +	[0x22] = '"';
           61  +}
           62  +for i=1, #bytes do
           63  +	local val = bytes:byte(i)
           64  +	local r
           65  +	if escapes[val] then
           66  +		r = '\\' .. escapes[val]
           67  +	elseif val >= 0x20 and val < 0x7f then
           68  +		r = string.char(val)
           69  +	else
           70  +		r = string.format("\\x%02X", val)
           71  +	end
           72  +	if chc + #r > max then flush() end
           73  +	chc = chc + #r
           74  +	table.insert(cur, r)
           75  +end
           76  +flush()
           77  +
           78  +for _, chars in ipairs(lns) do
           79  +	print(string.format('"%s"', table.concat(chars)))
           80  +end
           81  +

Modified soda.c from [0502e2ccfd] to [20cdbef471].

     1      1   /* [ʞ] soda - libsodium front end
     2      2    *  ~ lexi hale <lexi@hale.su>
     3      3    *  © AGPLv3
     4      4    *  @ vim: ft=c
            5  + *  ! ascii armor decoding is completely broken;
            6  + *    needs to be fixed before this program can
            7  + *    become usable
     5      8    */
     6      9   
     7     10   #define _POSIX_C_SOURCE 200809L
     8     11   #include <unistd.h>
     9     12   #include <stdio.h>
    10     13   #include <errno.h> /* boo hiss */
    11     14   #include <stdint.h>
................................................................................
   413    416   #undef _declflag_raw
   414    417   
   415    418   /* the casts here are a bit wacky. this is unfortunately necessary as C
   416    419    * insists on evaluating each branch of the generic expression regardless
   417    420    * of which type is picked. why anyone thought this was a good idea is
   418    421    * beyond me. */
   419    422   #define _t(x) (_Generic((x), \
   420         -	      const char**: (struct sayp){say_string_list, .strlist  = (const char**)(size_t)(x)}, \
   421         -	              char: (struct sayp){say_char,   .ch   = (char)(size_t)(x)}, \
   422         -	             char*: (struct sayp){say_string, .str  = (const char*)(size_t)(x)}, \
   423         -	       const char*: (struct sayp){say_string, .str  = (const char*)(size_t)(x)}, \
          423  +	      const char**: (struct sayp){say_string_list, .strlist  = (const char**)(intptr_t)(x)}, \
          424  +	              char: (struct sayp){say_char,   .ch   = (char)(intptr_t)(x)}, \
          425  +	             char*: (struct sayp){say_string, .str  = (const char*)(intptr_t)(x)}, \
          426  +	       const char*: (struct sayp){say_string, .str  = (const char*)(intptr_t)(x)}, \
   424    427   				   int: (struct sayp){say_sint,   .sint = (long long)(x)}, \
   425    428   	             short: (struct sayp){say_sint,   .sint = (long long)(x)}, \
   426    429   	              long: (struct sayp){say_sint,   .sint = (long long)(x)}, \
   427    430   	         long long: (struct sayp){say_sint,   .sint = (long long)(x)}, \
   428    431   		      unsigned: (struct sayp){say_uint,   .uint = (long long unsigned)(x)}, \
   429    432   	    unsigned short: (struct sayp){say_uint,   .uint = (long long unsigned)(x)}, \
   430    433   	     long unsigned: (struct sayp){say_uint,   .uint = (long long unsigned)(x)}, \
   431    434   	long long unsigned: (struct sayp){say_uint,   .uint = (long long unsigned)(x)}, \
   432         -	default: (struct sayp){say_hex, .uint = (size_t)(x)})),
          435  +	default: (struct sayp){say_hex, .uint = (intptr_t)(x)})),
   433    436   #define _say(k,...)  say(c, noise_##k, ((struct sayp[]){__VA_ARGS__ {say_stop}}))
   434    437   #define _report(k,s) _say(k, _t(s))
   435    438   
   436    439   void
   437    440   usage(struct ctx c, const struct cmd_spec* tree) {
   438    441   	const char* bin = c.bin;
   439    442   	const char* fmt_flag,* fmt_usage,* fmt_enum,* head_start,* head_fin;
................................................................................
   521    524   	"\x31\x32\00\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e"
   522    525   	"\00\00\00\00\x3f\00\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13"
   523    526   	"\x14\x15\x16\x17\00\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21"
   524    527   	"\x22";
   525    528   	/* generated by a script. do not touch. */
   526    529   
   527    530   enum { armor_split_every = 48 };
   528         -char*
   529         -armor(const unsigned char* src, char* dest, size_t sz, size_t brstart, bool format) {
          531  +
          532  +char* armor
          533  +(	char unsigned const* const src,
          534  +	char               * const dest,
          535  +	size_t               const sz,
          536  +	size_t               const brstart,
          537  +	bool                 const format
          538  +) {
   530    539   	char* bufptr = dest;
   531    540   	unsigned char carry = 0;
   532    541   	for(size_t i = 0; i<sz; ++i) {
   533    542   		/* insert line breaks every so many chars */
   534    543   		*(bufptr++)=ascii_armory[src[i] % 64];
   535    544   		if (format) if ((brstart + (bufptr - dest)) % armor_split_every == 0)
   536    545   			*(bufptr++)='\n', *(bufptr++)=' ';
................................................................................
   544    553   		if (format) if ((brstart + (bufptr - dest)) % armor_split_every == 0)
   545    554   			*(bufptr++)='\n', *(bufptr++)=' ';
   546    555   	}
   547    556   	/* if(carry != 0) */ *(bufptr++)=ascii_armory[carry];
   548    557   	return bufptr;
   549    558   }
   550    559   
   551         -char* disarmor(const unsigned char* src, char* dest, size_t sz) {
          560  +char* disarmor(char unsigned const* const src, char* dest, size_t const sz) {
   552    561   	/* transforms ascii armor into binary. can transform in place. */
   553    562   	for(size_t i = 0; i<sz; i += 3) {
   554    563   		while (isws(src[i])) ++i;
   555    564   		const char* s = src + i;
   556    565   		unsigned char carry = ascii_value[s[2] - '-'],
   557    566   			          b1    = ascii_value[s[0] - '-'] + (64 * ((carry & 12) >> 2)),
   558    567   		              b2    = ascii_value[s[1] - '-'] + (64 * ( carry &  3));
................................................................................
  1102   1111   		++ c.cmdc; ++ paramcount;
  1103   1112   	}
  1104   1113   	
  1105   1114   	parse_done: _say(debug, _t("stored") _t(c.cmdc) _t("arguments and") _t(paramcount) _t("parameters"));
  1106   1115   	
  1107   1116   	if (c.flags.noise <= noise_debug) for (size_t i = 0; i<c.cmdc; ++i) {
  1108   1117   		if (cmdlist[i] < _atom_n) {
  1109         -			dprintf(2, "\t%llu. atom %u (normal form “%s”)\n", i, cmdlist[i], reconstitute(cmdlist[i]));
         1118  +			dprintf(2, "\t%zu. atom %u (normal form “%s”)\n", i, cmdlist[i], reconstitute(cmdlist[i]));
  1110   1119   		} else {
  1111         -			dprintf(2,"\t%llu. parameter “%s”\n", i, paramlist[cmdlist[i] - _atom_n]);
         1120  +			dprintf(2,"\t%zu. parameter “%s”\n", i, paramlist[cmdlist[i] - _atom_n]);
  1112   1121   		}
  1113   1122   	}
  1114   1123   
  1115   1124   	if (c.flags.fmtv >= sz(write_privkey)) {
  1116   1125   		_say(fatal, _t("data format version") _t(c.flags.fmtv) _t("is not known. the highest available version is") _t(sz(write_privkey) - 1) _t("- are you sure you're using the latest release of " _self_name "?"));
  1117   1126   		return -2;
  1118   1127   	}