Commits

Anonymous committed d721e79

new stuff, modifications, etc.

Comments (0)

Files changed (12)

anagrams/anagrams.awk

 {
-	a[$2] = a[$2] (a[$2]?" ":"") $1
+	a[$2] = a[$2] (a[$2] ? " " : "") $1
 }
 END {
 	for (k in a)

anagrams/sortwords.c

 /*
  * sortwords.c
  *
+ * Programming Pearls: 2.1.C
  * taking into account current LC_CTYPE and LC_COLLATE:
  * read in word ([:space:] separated),
  * print word followed by space
 #include <wchar.h>
 #include <wctype.h>
 
-int wcscoll_cmp(const void *a, const void *b) {
+int wcscoll_cmp(const void *a, const void *b)
+{
 	return wcscoll((const wchar_t *)a, (const wchar_t *)b);
 }
 
 int main(void)
 {
 	wint_t  wc;
-	wchar_t line[sysconf(_SC_LINE_MAX) / sizeof(wchar_t) * 2], *p = line;
+	wchar_t word[sysconf(_SC_LINE_MAX) * 2], *p = word;
 
 	setlocale(LC_ALL, "");
 	while ((wc = fgetwc(stdin)) != WEOF) {
+		fputwc(wc, stdout);
 		if (iswspace(wc)) {
-			for (wchar_t *q = line; q < p; q += 2)
-				fputwc(*q, stdout);
-			fputwc(L' ', stdout);
-			qsort(line, (p - line) / 2, sizeof(wchar_t) * 2, wcscoll_cmp);
-			for (wchar_t *q = line; q < p; q += 2)
+			qsort(word, (p - word) / 2, sizeof(wchar_t) * 2, wcscoll_cmp);
+			for (wchar_t *q = word; q < p; q += 2)
 				fputwc(*q, stdout);
 			fputwc(L'\n', stdout);
-			p = line;
+			p = word;
 		} else {
-			*p++ = (wchar_t) wc;
+			*p++ = wc;
 			*p++ = L'\0';
 		}
 	}
 s/[+-]/&&*p;/g
 s/>/++p;/g
 s/</--p;/g
-s/\./putchar(*p);/g
-s/,/if ((c = getchar()) != EOF) *p=c;/g
+s/\./putchar(*p);fflush(stdout);/g
+s/,/if ((c=getchar())!=EOF)*p=c;/g
 s/\[/while(*p){/g
 s/]/}/g
 1s/^/#include<stdio.h>\nint main(){char a[100000]={},*p=a; int c;/
+#!/usr/bin/env bash
+
+# brainfuck interpreter
+# usage: ./bfi script
+# in order to get line based input from stdin, cat | ./bfi script
+# easier than dealing with nul bytes on input in bash
+
+incp() { ((++p)); }
+decp() { ((p--)) && return 0; echo "p < 0" 1>&2; return 1; }
+incat(){ ((++bfm[p])); return 0; }
+decat(){ ((--bfm[p])); return 0; }
+putch(){ local LC_CTYPE=C; printf %b "\x$(printf %x "${bfm[p]}")"; }
+getch(){ local LC_CTYPE=C c; IFS= read -r -n 1 -d '' c && printf -v bfm[p] %d "'$c"; return 0; }
+lbrac(){ ((++pc)); ((!bfm[p] && (pc = prog[pc]))); return 0; }
+rbrac(){ ((++pc)); (( bfm[p] && (pc = prog[pc]))); return 0; }
+
+code() {
+	prog[ni++]=$1;
+	case "$1" in
+		lbrac) stack+=($ni); code $stop;;
+		rbrac)
+			((${#stack[@]})) || return 1;
+			((prog[${stack[@]: -1}] = ni))
+			code "${stack[@]: -1}"
+			unset stack[${#stack[@]}-1]
+			;;
+	esac
+}
+
+read_script() {
+	[[ -r "$1" ]] || { echo "cannot read $1" 1>&2; return 1; }
+
+	local c b stack;
+	declare -A insts=( [>]=incp  [<]=decp  [+]=incat [-]=decat
+	                   [.]=putch [,]=getch [\[]=lbrac )
+	insts[\]]=rbrac # due to bug in bash (resolved in 4.3)
+
+	while IFS= read -r -n 1 -d '' c; do
+		[[ ${insts[$c]} ]] || continue
+		code "${insts[$c]}" || { echo "extra ]" 2>&1; return 1; }
+	done < "$1"
+
+	((!${#stack[@]})) || { echo "extra [" 2>&1; return 1; }
+	code $stop
+}
+
+run_script() {
+	for ((pc = 0; prog[pc] != stop; pc++)); do
+		"${prog[$pc]}" || break
+	done
+}
+
+if (($# != 1)); then
+	echo "Usage: ./bfi scriptfile" 1>&2
+	exit 1
+fi
+
+stop=-1 prog=() ni=0 bfm=() p=0 input=""
+read_script "$1" && run_script
 char  *bfm , *p;       /* bf memory, bf pointer */
 size_t prog_size, bfm_size;
 
-int grow(void **ptr, size_t *nmemb, size_t size, void **half, int set) {
+int grow(void **ptr, size_t *nmemb, size_t size, void **half, int set)
+{
 	void *tmp = realloc(*ptr, (*nmemb *= 2) * size);
 	if (!tmp) { perror("realloc failed"); return 1; }
 	*ptr = tmp;
 	if (set) memset(*half, 0, *nmemb * size / 2);
 	return 0;
 }
-int code(Inst f) {
+int code(Inst f)
+{
 	if (ni == prog + prog_size)
 		if (grow((void **)&prog, &prog_size, sizeof(*prog), (void **)&ni, 0))
 			return 1;
 	*ni++ = f;
 	return 0;
 }
-int incp (void) {
+int incp (void)
+{
 	if (++p != bfm + bfm_size) return 0;
 	return grow((void **)&bfm, &bfm_size, sizeof(*bfm), (void **)&p, 1);
 }
 int lbrac(void) { pc++; if (!*p) pc = (Inst*)(prog + *(ptrdiff_t *)pc); return 0; }
 int rbrac(void) { pc++; if ( *p) pc = (Inst*)(prog + *(ptrdiff_t *)pc); return 0; }
 
-int main(void) {
+int main(int argc, char **argv)
+{
+	int  c, e, b = 0;
 	Inst insts[] = { ['>'] = incp , ['<'] = decp , ['+'] = incat, ['-'] = decat,
 	                 ['.'] = putch, [','] = getch, ['['] = lbrac, [']'] = rbrac,
 	                 [UCHAR_MAX] = NULL };
-	for (;;) {
-		int c, e, b = 0;
-		p  = bfm  = calloc(bfm_size  = 1, sizeof(*bfm ));
-		ni = prog = calloc(prog_size = 1, sizeof(*prog));
+	FILE *script = argc > 1 ? fopen(argv[1], "r") : stdin;
 
-		while ((c = getchar()) != EOF) {
-			if (!insts[c]) continue;
-			if (!(e = code(insts[c]))) {
-				switch (c) {
-					case '[':     ++b;        e = code(STOP);  break;
-					case ']': if (--b < 0 || (e = code(STOP))) break;
-						for (pc = ni - 2; pc > prog && *pc != STOP; pc--)
-							; //TODO: stack (is it worth it?)
-						*(ptrdiff_t *)pc       = (ni - 1) - prog;
-						*(ptrdiff_t *)(ni - 1) = pc       - prog;
-						break;
-				}
-			}
-			if (b < 0 || e) {
-				while (getchar() != EOF)
-					;
-				break;
+	if (!script) { perror("fopen failed"); return 1; }
+
+	p  = bfm  = calloc(bfm_size  = 1, sizeof(*bfm ));
+	ni = prog = calloc(prog_size = 1, sizeof(*prog));
+
+	while ((c = fgetc(script)) != EOF) {
+		if (!insts[c]) continue;
+		if (!(e = code(insts[c]))) {
+			switch (c) {
+				case '[':     ++b;        e = code(STOP);  break;
+				case ']': if (--b < 0 || (e = code(STOP))) break;
+							  for (pc = ni - 2; pc > prog && *pc != STOP; pc--)
+								  ; //TODO: stack (is it worth it?)
+						  *(ptrdiff_t *)pc       = (ni - 1) - prog;
+						  *(ptrdiff_t *)(ni - 1) = pc       - prog;
+						  break;
 			}
 		}
-		e = code(STOP);
-		if (b)
-			fprintf(stderr, "extra %c\n", b < 0 ? ']' : '[');
-		else if (!e)
-			for (pc = prog; *pc != STOP; pc++)
-				if ((*(*pc))())
-					break;
-		free(bfm);
-		free(prog);
+		if (b < 0 || e) break;
 	}
+	e = code(STOP);
+	if (b)
+		fprintf(stderr, "extra %c\n", b < 0 ? ']' : '[');
+	else if (!e)
+		for (pc = prog; *pc != STOP; pc++)
+			if ((*(*pc))())
+				break;
+	if (fclose(script)) perror("fclose failed");
+	free(bfm);
+	free(prog);
 	return 0;
 }
+#include <limits.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+typedef union {
+	enum { stop = 0, incp, decp, incat, decat, putch, getch, lbrac, rbrac } inst;
+	ptrdiff_t addr;
+} Inst;
+#define STOP ((Inst){ .inst = stop })
+
+Inst  *prog, *pc, *ni; /* program, program counter, next instruction spot */
+char  *bfm , *p;       /* bf memory, bf pointer */
+size_t prog_size, bfm_size;
+
+int grow(void **ptr, size_t *nmemb, size_t size, void **half, int set)
+{
+	void *tmp = realloc(*ptr, (*nmemb *= 2) * size);
+	if (!tmp) { perror("realloc failed"); return 1; }
+	*ptr = tmp;
+	*half = (char *)*ptr + *nmemb * size / 2;
+	if (set) memset(*half, 0, *nmemb * size / 2);
+	return 0;
+}
+
+int code(Inst f)
+{
+	if (ni == prog + prog_size)
+		if (grow((void **)&prog, &prog_size, sizeof(*prog), (void **)&ni, 0))
+			return 1;
+	*ni++ = f;
+	return 0;
+}
+
+int main(int argc, char **argv)
+{
+	int insts[] = { ['>'] = incp , ['<'] = decp , ['+'] = incat, ['-'] = decat,
+	                ['.'] = putch, [','] = getch, ['['] = lbrac, [']'] = rbrac,
+					[UCHAR_MAX] = 0 };
+	int  c, b = 0, e = 0;
+	FILE *script = argc > 1 ? fopen(argv[1], "r") : stdin;
+
+	if (!script) { perror("fopen failed"); return 1; }
+
+	p  = bfm  = calloc(bfm_size  = 1, sizeof(*bfm ));
+	ni = prog = calloc(prog_size = 1, sizeof(*prog));
+
+	while ((c = fgetc(script)) != EOF) {
+		if (!insts[c]) continue;
+		if (!(e = code((Inst){ .inst = insts[c] }))) {
+			switch (c) {
+				case '[':     ++b;        e = code(STOP);  break;
+				case ']': if (--b < 0 || (e = code(STOP))) break;
+					for (pc = ni - 2; pc > prog && pc->inst != stop; pc--)
+						; //TODO: stack (is it worth it?)
+					pc->addr       = (ni - 1) - prog;
+					(ni - 1)->addr = pc       - prog;
+					break;
+			}
+		}
+		if (b < 0 || e) break;
+	}
+	if (b) fprintf(stderr, "extra %c\n", b < 0 ? ']' : '[');
+	else if (!e) {
+		e = code(STOP);
+		for (pc = prog; !e && pc->inst != stop; pc++) {
+			switch (pc->inst) {
+				default   : e++; fprintf(stderr, "bad instruction\n"); break;
+				case incp :
+					if (++p == bfm + bfm_size)
+						e = grow((void **)&bfm, &bfm_size, sizeof(*bfm), (void **)&p, 1);
+					break;
+				case decp : if ((e = --p < bfm)) fprintf(stderr, "p < 0\n"); break;
+				case incat: ++*p;                                break;
+				case decat: --*p;                                break;
+				case putch: putchar(*p); fflush(stdout);         break;
+				case getch: if ((c = getchar()) != EOF) *p = c;  break;
+				case lbrac: pc++; if (!*p) pc = prog + pc->addr; break;
+				case rbrac: pc++; if ( *p) pc = prog + pc->addr; break;
+			}
+		}
+	}
+	if (fclose(script)) perror("fclose failed");
+	free(bfm);
+	free(prog);
+	return 0;
+}
  *
  * distribute lines from file to named fifos when they are available to write
  */
+#define _POSIX_C_SOURCE 200809L
 #include <err.h>
 #include <stdio.h>
 #include <stdlib.h>

empty_line_every_20

 sed
 ===
 sed ':a;$!{N;ba;};s/\([^\n]*\n\)\{20\}/&\n/g'
-sed '1~20a\\'    # GNUism
+sed '0~20a\\'    # GNUism
 
 awk
 ===
-awk '1;!(NR%20){printf("\n")}'
+awk '1;!(NR%20){print""}'
 
 sh
 ==
  *
  * print lines from named fifos as they are available to read
  */
+#define _POSIX_C_SOURCE 200809L
 #include <err.h>
 #include <stdio.h>
 #include <stdlib.h>

offsets/offsets.bash

 # combine with offsets.awk to get a listing of word [offset,...] pairs
 # 
 
-unset word off lc lw
-while IFS= read -r -d '' -n 1 c; do
-	lc=$(LC_CTYPE=C; printf %d ${#c})
-	if [[ $c == [[:alnum:]] ]]; then
-		word+=$c
-		((lw += lc))
-	elif [[ $word ]]; then
-		printf "%s %zu\n" "$word" $((off - lw))
-		unset word lw
-	fi
-	((off += lc))
+print_offsets() {
+	local word lc lw
+	while IFS= read -r -d '' -n 1 c; do
+		lc=$(LC_CTYPE=C; printf %d ${#c})
+		if [[ $c == [[:alnum:]] ]]; then
+			word+=$c
+			((lw += lc))
+		elif [[ $word ]]; then
+			printf "%s %zu\n" "$word" $((off - lw))
+			unset word lw
+		fi
+		((off += lc))
+	done
+}
+
+declare -A offsets
+while read word off; do
+	offsets[$word]+=${offsets[$word]:+,}$off
+done < <(print_offsets)
+
+for word in "${!offsets[@]}"; do
+	printf "%s [%s]\n" "$word" "${offsets[$word]}"
 done
+#include <stdio.h>
+//void swap(char **p, char **q) { if (*p == *q) return; char *t = *p; *p = *q; *q = t; }
+void swap(char **p, char **q) { char *t = *p; *p = *q; *q = t; }
+void perm(char **s, char **p) {
+	if (*p) for (char **q = p; *q; q++) swap(p, q), perm(s, p + 1), swap(p, q);
+	else    for (char **q = s; *q; q++) printf("%s%c", *q, q[1] ? ' ' : '\n'); }
+int main(int argc, char **argv) { perm(argv + 1, argv + 1); return 0; }
 	back_poll  = (zmq_pollitem_t){ .socket = back_end , .fd = 0, .events = ZMQ_POLLIN, .revents = 0 };
 
 	//TODO: use zeromq's perf tools to test IPC vs TCP for back_end
-	zcheck_goto(cleanup, 0 <= zsocket_bind(front_end, argv[1])                       , "zsocket_bind failed to bind front_end socket"     );
-	zcheck_goto(cleanup, 0 <= zsocket_bind(back_end , argv[2])                       , "zsocket_bind failed to bind back_end socket"      );
+	zcheck_goto(cleanup, 0 <= zsocket_bind(front_end, argv[1])                       , "zsocket_bind failed to bind front_end socket: %s", argv[1]);
+	zcheck_goto(cleanup, 0 <= zsocket_bind(back_end , argv[2])                       , "zsocket_bind failed to bind back_end socket: %s" , argv[2]);
 	zcheck_goto(cleanup, 0 == zloop_poller(loop, &front_poll, msg_handler, back_end ), "zloop_poller failed to register front_end handler");
 	zcheck_goto(cleanup, 0 == zloop_poller(loop, &back_poll , msg_handler, front_end), "zloop_poller failed to register back_end handler" );