]> mj.ucw.cz Git - misc.git/commitdiff
Initial commit.
authorMartin Mares <mj@ucw.cz>
Fri, 13 Jul 2007 08:43:15 +0000 (10:43 +0200)
committerMartin Mares <mj@ucw.cz>
Fri, 13 Jul 2007 08:43:15 +0000 (10:43 +0200)
48 files changed:
Makefile [new file with mode: 0644]
ant.c [new file with mode: 0644]
bigdiv.c [new file with mode: 0644]
bmap.c [new file with mode: 0644]
buckets.c [new file with mode: 0644]
callback.c [new file with mode: 0644]
censor.p [new file with mode: 0644]
checkaddr.pl [new file with mode: 0644]
chocolate.c [new file with mode: 0644]
count.c [new file with mode: 0644]
diary.c [new file with mode: 0644]
false-true/Makefile [new file with mode: 0644]
false-true/mktrue [new file with mode: 0755]
false-true/mktrue2 [new file with mode: 0755]
false-true/true [new file with mode: 0755]
fortcmp.c [new file with mode: 0644]
guesstrans.c [new file with mode: 0644]
heapsort.p [new file with mode: 0644]
hidtest [new file with mode: 0755]
hidtest.c [new file with mode: 0644]
hobble.c [new file with mode: 0644]
hull [new file with mode: 0755]
hull.c [new file with mode: 0644]
ictest.i [new file with mode: 0644]
jukebox.c [new file with mode: 0644]
jukebox.mk [new file with mode: 0644]
logik1.c [new file with mode: 0644]
logik2.c [new file with mode: 0644]
math.c [new file with mode: 0644]
merge.c [new file with mode: 0644]
netrq.c [new file with mode: 0644]
oggtest.c [new file with mode: 0644]
parens.c [new file with mode: 0644]
parrot.c [new file with mode: 0644]
phone.c [new file with mode: 0644]
prime.c [new file with mode: 0644]
proof.c [new file with mode: 0644]
puzzle.c [new file with mode: 0644]
randomize.c [new file with mode: 0644]
seek.c [new file with mode: 0644]
sig.c [new file with mode: 0644]
tla [new file with mode: 0755]
tla.db [new file with mode: 0644]
trains.c [new file with mode: 0644]
ukkonen.c [new file with mode: 0644]
un602.c [new file with mode: 0644]
unword.c [new file with mode: 0644]
whatsit.c [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..d58e035
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,12 @@
+CC=gcc
+LD=gcc
+CFLAGS=-O2 -Wall -W -Wno-parentheses -Wstrict-prototypes -Wmissing-prototypes -Wundef -Wredundant-decls -std=gnu99
+
+all:
+       @echo "Please choose what to make:"
+       @grep '^[^      ]*:' Makefile
+
+parrot: parrot.c
+
+clean:
+       rm -f `find . -name "*~" -or -name "*.[oa]" -or -name "\#*\#" -or -name TAGS -or -name core -or -name .depend -or -name .#*`
diff --git a/ant.c b/ant.c
new file mode 100644 (file)
index 0000000..0749a29
--- /dev/null
+++ b/ant.c
@@ -0,0 +1,345 @@
+/*
+ *  A simple ant-ology of genetic algorithms.
+ *
+ *  mj@ucw.cz, Discord YOLD 3166
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define NSTATES 16
+#define NMARKS 4
+#define SENSE_FOOD
+#ifdef SENSE_FOOD
+#define NTYPES 3
+#else
+#define NTYPES 8
+#endif
+#define NWAYS 1
+#define NSLOTS (NMARKS*NTYPES*NWAYS)
+#define SLOT(m,t,w) (((m)*NTYPES+(t))*NWAYS+(w))
+
+struct slot {
+  unsigned char op, mark, state;
+};
+
+#define OP_NOP 0
+#define OP_LEFT 1
+#define OP_RIGHT 2
+#define OP_UTB 3
+#define OP_MAX 4
+
+struct state {
+  struct slot slots[NSLOTS];
+};
+
+struct automaton {
+  struct state states[NSTATES];
+  int fitness;
+};
+
+#if 0
+#define XSIZE 10
+#define YSIZE 10
+#define XSTART 1
+#define YSTART 1
+
+char *maze =
+"##########"
+"#.#$#....#"
+"#.#.#$$$.#"
+"#.#.#$$$.#"
+"#.#.#$$$.#"
+"#.#.####.#"
+"#.#...$..#"
+"#.##.#####"
+"#.$......#"
+"##########"
+;
+#else
+#define XSIZE 34
+#define YSIZE 34
+#define XSTART 1
+#define YSTART 1
+char *maze =
+"##################################"
+"#.$$$............................#"
+"#...$............................#"
+"#...$.....................$$$....#"
+"#...$....................$....$..#"
+"#...$....................$....$..#"
+"#...$$$$.$$$$$........$$.........#"
+"#............$................$..#"
+"#............$.......$...........#"
+"#............$.......$...........#"
+"#............$.......$........$..#"
+"#....................$...........#"
+"#............$...................#"
+"#............$................$..#"
+"#............$.......$...........#"
+"#............$.......$.....$$$...#"
+"#.................$.....$........#"
+"#................................#"
+"#............$...................#"
+"#............$...$.......$.......#"
+"#............$...$..........$....#"
+"#............$...$...............#"
+"#............$...$...............#"
+"#............$.............$.....#"
+"#............$..........$........#"
+"#...$$..$$$$$....$...............#"
+"#.$..............$...............#"
+"#.$..............$...............#"
+"#.$......$$$$$$$.................#"
+"#.$.....$........................#"
+"#.......$........................#"
+"#..$$$$..........................#"
+"#................................#"
+"##################################"
+;
+
+#endif
+
+#define MI(a,b) ((b)*XSIZE+(a))
+char mazec[XSIZE*YSIZE];
+char *types = "$#.012345";
+
+#define POPSIZE 100
+
+struct automaton autpool[POPSIZE];
+struct automaton *pop[POPSIZE];
+
+void
+maze_init(void)
+{
+  int i;
+
+  puts("Initializing maze");
+  for(i=0; i<XSIZE*YSIZE; i++)
+    {
+      char *z = strchr(types, maze[i]);
+      if (!z) { fprintf(stderr, "Maze bug\n"); exit(1); }
+      mazec[i] = z - types;
+    }
+}
+
+void
+aut_gen_random(struct automaton *aut)
+{
+  int i, j;
+
+  for(i=0; i<NSTATES; i++)
+    for(j=0; j<NSLOTS; j++)
+      {
+       struct slot *s = &aut->states[i].slots[j];
+       s->op = random() % OP_MAX;
+       s->state = random() % NSTATES;
+       s->mark = random() % NMARKS;
+      }
+}
+
+void
+show(char *z)
+{
+  int i, j;
+  int x = 0;
+  for(i=0; i<YSIZE; i++)
+    {
+      for(j=0; j<XSIZE; j++)
+       putchar(types[(int)z[x++]]);
+      putchar('\n');
+    }
+}
+
+int
+fitness(struct automaton *aut, int flag)
+{
+  char tmp[XSIZE*YSIZE];
+  int state = 0;
+  int x = XSTART;
+  int y = YSTART;
+  int d = 0;
+  static int dx[4] = { 0, -1, 0, 1 };
+  static int dy[4] = { 1, 0, -1, 0 };
+  int energy = 50;
+  int bonus = 1;
+
+  memcpy(tmp, mazec, XSIZE*YSIZE);
+  while (energy > 0)
+    {
+      int way = random() % NWAYS;
+      int here = tmp[MI(x,y)];
+      int mark = (here < 3) ? 0 : here-3;
+      int ahead = tmp[MI(x+dx[d],y+dy[d])];
+      int right = tmp[MI(x+dx[(d+1)%4],y+dy[(d+1)%4])];
+      int left = tmp[MI(x+dx[(d+3)%4],y+dy[(d+3)%4])];
+#ifdef SENSE_FOOD
+      int view = (ahead >= 2) ? 2 : ahead;
+#else
+      int view = ((ahead==1)?4:0) | ((left==1)?2:0) | ((right==1)?1:0);
+#endif
+      struct slot *s = &aut->states[state].slots[SLOT(mark, view, way)];
+      tmp[MI(x,y)] = s->mark + 3;
+      bonus++;
+      energy--;
+      switch (s->op)
+       {
+       case OP_NOP:    break;
+       case OP_LEFT:   d = (d+3) % 4; break;
+       case OP_RIGHT:  d = (d+1) % 4; break;
+       case OP_UTB:    d = (d+2) % 4; break;
+       }
+      ahead = tmp[MI(x+dx[d],y+dy[d])];
+      switch (ahead)
+       {
+       case 0:         energy+=10; bonus+=100; /* food */
+       default:        x+=dx[d]; y+=dy[d]; break;  /* empty */
+       case 1:         energy-=5; break; /* wall */
+       }
+      state = s->state;
+    }
+  if (flag)
+    show(tmp);
+  return bonus;
+}
+
+void
+pop_init(void)
+{
+  int i;
+
+  for(i=0; i<POPSIZE; i++)
+    {
+      aut_gen_random(&autpool[i]);
+      pop[i] = &autpool[i];
+    }
+}
+
+int
+fcmp(struct automaton **a, struct automaton **b)
+{
+  int fa = (*a)->fitness;
+  int fb = (*b)->fitness;
+
+  return (fa < fb) ? -1 : (fa > fb) ? 1 : 0;
+}
+
+void
+mutate(struct automaton *a)
+{
+  int state, slot, i;
+  struct slot *s;
+
+  for(i=0; i<40; i++)
+    {
+      state = random() % NSTATES;
+      slot = random() % NSLOTS;
+      s = &a->states[state].slots[slot];
+      s->op = random() % OP_MAX;
+      s->state = random() % NSTATES;
+      s->mark = random() % NMARKS;
+    }
+}
+
+void
+crossover(struct automaton *a, struct automaton *b)
+{
+  int marks[NMARKS], types[NTYPES], ways[NWAYS], slots[NSLOTS];
+  int i, j, k;
+
+  if (a == b)
+    return;
+  for(i=0; i<NMARKS; i++)
+    marks[i] = random() % 2;
+  for(i=0; i<NTYPES; i++)
+    types[i] = random() % 2;
+  for(i=0; i<NWAYS; i++)
+    ways[i] = random() % 2;
+  for(i=0; i<NMARKS; i++)
+    for(j=0; j<NTYPES; j++)
+      for(k=0; k<NWAYS; k++)
+       slots[SLOT(i,j,k)] = marks[i] && types[j] && ways[k];
+  for(i=0; i<NSTATES; i++)
+    if (random() % 2)
+      for(j=0; j<NSLOTS; j++)
+       if (slots[j])
+         {
+           struct slot z;
+           z = a->states[i].slots[j];
+           a->states[i].slots[j] = b->states[i].slots[j];
+           b->states[i].slots[j] = z;
+         }
+}
+
+struct automaton *
+rgenom(struct automaton **x, int n, int t)
+{
+  int z = random() % t;
+  int k = 0;
+  int i = 0;
+
+  while (k <= z && n--)
+    k += x[i++]->fitness;
+  return x[i-1];
+}
+
+void
+step(void)
+{
+  int i, total, death;
+
+  for(i=0; i<POPSIZE; i++)
+    {
+      struct automaton *a = pop[i];
+      a->fitness = (fitness(a,0) + fitness(a,0) + fitness(a,0)) / 3;
+    }
+  qsort(pop, POPSIZE, sizeof(struct automaton *), (int(*)(const void *,const void *)) fcmp);
+  for(i=0; i<POPSIZE; i++)
+    {
+      struct automaton *a = pop[i];
+      //      printf("%d: %d\n", i, a->fitness);
+      total += a->fitness;
+    }
+  fitness(pop[POPSIZE-1], 1);
+  printf("best=%d worst=%d\n", pop[POPSIZE-1]->fitness, pop[0]->fitness);
+
+  total = 0;
+  death = POPSIZE/2;
+  for(i=death; i<POPSIZE; i++)
+    total += pop[i]->fitness;
+  for(i=0; i<death; i++)
+    {
+      struct automaton *a = pop[i];
+      struct automaton *x = rgenom(pop+death, POPSIZE-death, total);
+      memcpy(a, x, sizeof(struct automaton));
+    }
+
+  for(i=0; i<POPSIZE; i++)
+    {
+      struct automaton *a = pop[i];
+      int what = random() % 1024;
+      //      printf("%d %d\n", i, what);
+      if (what < 50)
+       mutate(a);
+      else if (what < 100)
+       crossover(a, rgenom(pop+death, POPSIZE-death, total));
+    }
+}
+
+int
+main(void)
+{
+  int gen = 0;
+
+  maze_init();
+  pop_init();
+  for(;;)
+    {
+      step();
+      printf("gen=%d\n", gen++);
+      //      sleep(1);
+    }
+  //  srandom(time(NULL));
+  return 0;
+}
diff --git a/bigdiv.c b/bigdiv.c
new file mode 100644 (file)
index 0000000..a209c3f
--- /dev/null
+++ b/bigdiv.c
@@ -0,0 +1,101 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define MAX 100
+#define BASE 10
+
+int first(int *X)
+{
+       /* Find the leftmost non-zero digit of X */
+       int n = MAX-1;
+       while (n >= 0 && !X[n])
+               n--;
+       return n;
+}
+
+int mul2(int *X, int n)
+{
+       /* Multiply X by 2 and return its new length */
+       int c = 0;
+       for (int i=0; i<=n; i++) {
+               int x = 2*X[i] + c;
+               X[i] = x % BASE;
+               c = x / BASE;
+       }
+       if (c)
+               X[++n] = c;
+       return n;
+}
+
+int submul(int *X, int xn, int *Y, int yn, int z, int *T)
+{
+       /* T = X-z*Y, returns -1 if it's <0; T and X can be the same array */
+       if (!z)
+               return 0;
+       if (yn > xn)
+               return -1;
+       int c = 1, d = 0;
+       for (int i=0; i<=xn; i++) {
+               int y = z*((i <= yn) ? Y[i] : 0) + d;
+               d = y / BASE;
+               y %= BASE;
+               int x = X[i] + (BASE-1-y) + c;
+               T[i] = x % BASE;
+               c = x / BASE;
+       }
+       return (c ? 0 : -1);
+}
+
+void divide(int *X0, int *Y0, int *Z)
+{
+       /* A copy of X and Y will be needed to avoid overwriting inputs */
+       int X[MAX], Y[MAX];
+       memcpy(X, X0, MAX * sizeof(*X));
+       memcpy(Y, Y0, MAX * sizeof(*Y));
+
+       /* Find the leftmost digit of X and Y */
+       int xn = first(X), yn = first(Y);
+       if (yn < 0)             // Division by 0
+               exit(1);
+
+       /* While Y starts with <BASE/2, multiply both X and Y by 2 */
+       while (Y[yn] < BASE/2) {
+               xn = mul2(X, xn);
+               yn = mul2(Y, yn);
+       }
+
+       /* Find the size of result and fill Z with zeroes */
+       for (int i=0; i<MAX; i++)
+               Z[i] = 0;
+       int zn = xn - yn;
+       if (zn < 0)             /* The result will obviously round to 0 */
+               return;
+
+       /* The main division loop */
+       while (zn >= 0) {
+               int T[MAX];
+               while (xn > 0 && !X[xn])        /* Fix the estimate of size of X */
+                       xn--;
+               int z = X[xn];
+               if (xn-zn > yn)                 /* First 1 or 2 digits of X */
+                       z = 10*z + X[xn-1];
+               Z[zn] = z / Y[yn];
+               if (submul(X+zn, xn-zn, Y, yn, Z[zn], T) < 0)
+                       Z[zn]--;
+               submul(X+zn, xn-zn, Y, yn, Z[zn], X+zn);
+               zn--;
+       }
+}
+
+int main(void)
+{
+       int A[MAX] = { 6, 7, 5, 8, 4, 0, 1 };
+       int B[MAX] = { 4, 6 };
+       int C[MAX];
+       divide(A, B, C);
+       for (int i=MAX-1; i>=0; i--)
+               printf("%d", C[i]);
+       putchar('\n');
+       return 0;
+}
diff --git a/bmap.c b/bmap.c
new file mode 100644 (file)
index 0000000..742e63f
--- /dev/null
+++ b/bmap.c
@@ -0,0 +1,48 @@
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <linux/fs.h>
+
+int main(void)
+{
+  int bs;
+  if (ioctl(0, FIGETBSZ, &bs) < 0)
+    {
+      perror("FIGETBSZ");
+      return 1;
+    }
+  printf("Block size is %d\n", bs);
+  long long len = lseek64(0, 0, SEEK_END);
+  printf("File size is %Ld\n", len);
+  int blx = (len+bs-1)/bs;
+  printf("... that is %d blocks\n", blx);
+  int blk, pos;
+  int small_gaps = 0;
+  int large_gaps = 0;
+  int last_pos = -1;
+  for (blk=0; blk<blx; blk++)
+    {
+      pos = blk;
+      if (ioctl(0, FIBMAP, &pos) < 0)
+       {
+         perror("FIBMAP");
+         return 1;
+       }
+      printf("%d\t%d\n", blk, pos);
+      if (last_pos >= 0)
+       {
+         if (pos == last_pos+1)
+           ;
+         else if (pos >= last_pos && pos < last_pos + 1024)
+           small_gaps++;
+         else
+           large_gaps++;
+       }
+      last_pos = pos;
+    }
+  printf("Gaps: %d small, %d large\n", small_gaps, large_gaps);
+  return 0;
+}
diff --git a/buckets.c b/buckets.c
new file mode 100644 (file)
index 0000000..f5f955d
--- /dev/null
+++ b/buckets.c
@@ -0,0 +1,107 @@
+#include <stdio.h>
+
+#define MAX 12         // actually, it's 1 more than max
+#define NST (MAX*MAX*MAX)
+
+int status[NST], queue[NST], back[NST], qr, qw;
+int capa[3], goal[MAX], gback[MAX];
+
+#define ENCODE(i,j,k) ((i)*MAX*MAX+(j)*MAX+(k))
+#define DECODE(i,j,k,x) (i)=(x)/(MAX*MAX), (j)=(x)/MAX%MAX, (k)=(x)%MAX
+
+static void go(int x, int *t)
+{
+  // printf("\t-> %d %d %d\n", t[0], t[1], t[2]);
+  int y = ENCODE(t[0], t[1], t[2]);
+  if (status[y] < 0)
+    {
+      status[y] = status[x] + 1;
+      queue[qw++] = y;
+      back[y] = x;
+    }
+}
+
+static void search(void)
+{
+  for (int i=1; i<NST; i++)
+    status[i] = -1;
+  for (int i=0; i<MAX; i++)
+    goal[i] = -1;
+  status[0] = 0;
+  queue[0] = 0;
+  qr = 0;
+  qw = 1;
+  while (qr < qw)
+    {
+      int x = queue[qr++];
+      int t[3];
+      DECODE(t[0],t[1],t[2],x);
+      // printf("%5d %d,%d,%d (%d)\n", x, t[0], t[1], t[2], status[x]);
+      for (int i=0; i<3; i++)
+       if (goal[t[i]] < 0)
+         {
+           goal[t[i]] = status[x];
+           gback[t[i]] = x;
+         }
+      for (int i=0; i<3; i++)
+       {
+         int z = t[i];
+         t[i] = 0;
+         go(x, t);
+         t[i] = capa[i];
+         go(x, t);
+         t[i] = z;
+       }
+      for (int i=0; i<3; i++)
+       for (int j=0; j<3; j++)
+         if (i != j)
+           {
+             int r = capa[j] - t[j];
+             if (r > t[i])
+               r = t[i];
+             t[i]-=r; t[j]+=r;
+             go(x, t);
+             t[i]+=r; t[j]-=r;
+           }
+    }
+}
+
+int main(void)
+{
+#if 1
+  for (int f=0; f<NST; f++)
+    {
+      DECODE(capa[0], capa[1], capa[2], f);
+      if (!capa[0] || !capa[1] || !capa[2]
+         || (capa[0] == capa[1] || capa[0] == capa[2] || capa[1] == capa[2]) && 1
+         || !(capa[0] <= capa[1] && capa[1] <= capa[2])
+         )
+       continue;
+      printf("%d,%d,%d: ", capa[0], capa[1], capa[2]);
+      search();
+      int best = 0;
+      for (int i=0; i<MAX; i++)
+       if (goal[i] > goal[best])
+         best = i;
+      int reach = 0;
+      for (int i=0; i<NST; i++)
+       if (status[i] >= 0)
+         reach++;
+      printf("%2d (%d) r=%d\n", goal[best], best, reach);
+    }
+#else
+  capa[0] = 8;
+  capa[1] = 5;
+  capa[2] = 3;
+  search();
+  int r = gback[4];
+  while (r > 0)
+    {
+      int a,b,c;
+      DECODE(a,b,c,r);
+      printf("%d,%d,%d\n", a,b,c);
+      r = back[r];
+    }
+#endif
+  return 0;
+}
diff --git a/callback.c b/callback.c
new file mode 100644 (file)
index 0000000..1c62ccb
--- /dev/null
@@ -0,0 +1,317 @@
+/*
+ *             Modem Call Back
+ *
+ *             (c) 1995 Martin Mares
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <termios.h>
+#include <signal.h>
+#include <utmp.h>
+#include <sys/wait.h>
+#include <sys/file.h>
+
+#define MODEM_PORT "/dev/cua3"
+
+int modem_handle;
+int alarm_got;
+int termios_backed_up;
+int modem_active;
+struct termios old_termios;
+
+struct termios new_termios = {
+       IGNBRK | IGNPAR,
+       0,
+       0,
+       0,
+       N_TTY,
+       { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+       };
+
+void err(char *);
+
+void
+set_timeout(int n)
+{
+       alarm_got = 0;
+       alarm(n);
+}
+
+void
+delay(int n)
+{
+       set_timeout(n);
+       do pause(); while (!alarm_got);
+}
+
+void
+pulse_dtr(void)
+{
+int o = new_termios.c_cflag;
+       fprintf(stderr, "Pulsing DTR\n");
+       new_termios.c_cflag &= ~CBAUD;
+       if (tcsetattr(modem_handle, TCSANOW, &new_termios))
+               err("Unable to lower DTR");
+       delay(2);
+       new_termios.c_cflag = o;
+       if (tcsetattr(modem_handle, TCSANOW, &new_termios))
+               err("Unable to raise DTR");
+}
+
+void
+send(char *s)
+{
+       fprintf(stderr, "Sending %s", s);
+       write(modem_handle, s, strlen(s));
+}
+
+int
+wait_for(char *c, int tim)
+{
+char *s = c;
+char b;
+int l;
+       fprintf(stderr,"Waiting %d sec for %s\n", tim, c);
+       while (*s)
+               {
+               set_timeout(tim);
+               l = read(modem_handle, &b, 1);
+               if (!l)
+                       err("EOF");
+               if (l == -1)
+                       {
+                       if (errno == EINTR)
+                               return 0;
+                       else
+                               err("Read error");
+                       }
+               fprintf(stderr, "Got %c\n", b);
+               if (b == *s)
+                       s++;
+               else
+                       s = c;
+               }
+       alarm(0);
+       return 1;
+}
+
+void
+cmd(char *s)
+{
+       send(s);
+       if (!wait_for("OK",5))
+               err("Timeout");
+}
+
+void
+drain(void)
+{
+char buf[256];
+       if (!fcntl(modem_handle, F_SETFL, O_NONBLOCK))
+               {
+               while (read(modem_handle, buf, 256) > 0) ;
+               fcntl(modem_handle, F_SETFL, 0);
+               }
+}
+
+void
+modem_init(char *name)
+{
+       modem_handle = open(name, O_RDWR);
+       if (modem_handle < 0)
+               err("Unable to open modem device");
+       if (tcgetattr(modem_handle, &old_termios))
+               err("Unable to fetch old termios");
+       termios_backed_up = 1;
+       new_termios.c_cflag = (old_termios.c_cflag | CRTSCTS) & ~HUPCL;
+       if (!(new_termios.c_cflag & CBAUD))
+               new_termios.c_cflag |= B19200;
+       if (tcsetattr(modem_handle, TCSANOW, &new_termios))
+               err("Unable to set termios");
+       modem_active = 1;
+       pulse_dtr();
+       send("ATZ\r\n");
+       delay(2);
+       drain();
+       cmd("ATE0M1Q0\r\n");
+}
+
+void
+err2(char *text)
+{
+       perror(text);
+}
+
+void
+cleanup(void)
+{
+       if (modem_handle < 0)
+               return;
+       fprintf(stderr, "Cleanup.\n");
+       if (modem_active)
+               {
+               modem_active = 0;
+               pulse_dtr();
+               send("ATZ\n");
+               delay(1);
+               pulse_dtr();
+               }
+       if (termios_backed_up)
+               {
+               termios_backed_up = 0;
+               if (tcsetattr(modem_handle, TCSANOW, &old_termios))
+                       err2("Termios cannot be restored");
+               }
+       fprintf(stderr, "Done.\n");
+       close(modem_handle);
+       modem_handle = -1;
+}
+
+void
+sig_err(int n)
+{
+       fprintf(stderr, "Caught fatal signal %d -- aborting !\n", n);
+       cleanup();
+       exit(1);
+}
+
+void
+sig_alarm(int n)
+{
+       alarm_got = 1;
+       signal(SIGALRM, sig_alarm);
+}
+
+void
+signal_init(void)
+{
+int i;
+       for (i=0; i<32; i++)
+               signal(i, sig_err);
+       signal(SIGALRM, sig_alarm);
+}
+
+void
+err(char *txt)
+{
+       err2(txt);
+       cleanup();
+       exit(1);
+}
+
+int
+connect(char *nr)
+{
+char buf[256];
+int i;
+       sprintf(buf, "atd%s\r\n", nr);
+       send(buf);
+       i = wait_for("CONNECT", 60);
+       delay(1);
+       drain();
+       return i;
+}
+
+struct termios tios = {
+       ICRNL | IXON | IXOFF,
+       OPOST | ONLCR,
+       0,
+       ISIG | ICANON | IEXTEN | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE,
+       N_TTY,
+       { 3, 0x1c, 0x7f, 0x15, 4, 0, 1, 0, 0x11, 0x13, 0x1a, 0, 0x12, 0x0f, 0x17,
+               0x16, 0 }
+       };
+
+void
+okay(void)
+{
+int pid, i, wt;
+struct utmp ut;
+char *port = MODEM_PORT;
+       pid = fork();
+       if (pid < 0)
+               err("Cannot fork()");
+       if (!pid)
+               {
+               setsid();
+               for (i=0; i<3; i++)
+                       {
+                       close(i);
+                       open(port, O_RDWR);
+                       }
+               tios.c_cflag = new_termios.c_cflag | HUPCL;
+               tcsetattr(0, TCSANOW, &tios);
+               utmpname(_PATH_UTMP);
+               memset(&ut, 0, sizeof(ut));
+               strcpy(ut.ut_user, "LOGIN");
+               strcpy(ut.ut_line, port+5);
+               strncpy(ut.ut_id, ut.ut_line + 3, sizeof(ut.ut_id));
+               time(&ut.ut_time);
+               ut.ut_type = LOGIN_PROCESS;
+               ut.ut_pid = getpid();
+               pututline(&ut);
+               endutent();
+               wt = open(_PATH_WTMP, O_APPEND|O_WRONLY);
+               if (wt >= 0)
+                       {
+                       flock(wt, LOCK_EX);
+                       write(wt, &ut, sizeof(ut));
+                       flock(wt, LOCK_UN);
+                       close(wt);
+                       }
+               execl("/usr/sbin/callback-login", "/usr/sbin/callback-login", NULL);
+               }
+       else
+               {
+               wait(&i);
+               i = open(MODEM_PORT, O_RDWR);
+               close(modem_handle);
+               modem_handle = i;
+               if (modem_handle >= 0)
+                       tcsetattr(modem_handle, TCSANOW, &new_termios);
+               }
+}
+
+void
+main(int argc, char **argv)
+{
+char *dest;
+int i;
+       if (geteuid())
+               {
+               fprintf(stderr, "Must be run by root!\n");
+               exit(1);
+               }
+       if (getuid() != 1000 && getuid())
+               {
+               fprintf(stderr,"Only mj is allowed to call this utility!\n");
+               exit(1);
+               }
+       if (argc != 2)
+               {
+               fprintf(stderr,"Usage: callback <number>\n");
+               exit(1);
+               }
+       dest = argv[1];
+       signal_init();
+       for(i=0;i<3;i++)
+               {
+               modem_init(MODEM_PORT);
+               if (connect(dest))
+                       {
+                       fprintf(stderr, "Connected...\n");
+                       okay();
+                       fprintf(stderr, "Disconnecting...\n");
+                       cleanup();
+                       return;
+                       }
+               cleanup();
+               fprintf(stderr, "Retrying...\n");
+               }
+       fprintf(stderr, "Failed.\n");
+       exit(1);
+}
diff --git a/censor.p b/censor.p
new file mode 100644 (file)
index 0000000..4a036eb
--- /dev/null
+++ b/censor.p
@@ -0,0 +1,50 @@
+program censor;
+
+var w0,s01,w1,s12,w2,s23:string[255];
+    c:char;
+
+procedure shift;
+var i,j,k:integer;
+    t:string[255];
+begin
+   t:=w1;
+   for i:=1 to length(t) do
+      if t[i]='o' then begin
+         if w0='' then
+           j:=length(w2)
+        else if (w2='') or (length(w0)<length(w2)) then
+           j:=length(w0)
+        else
+           j:=length(w2);
+         for k:=0 to j do begin
+           if k<i then w1[i-k]:='*'
+           else if w0<>'' then w0[length(w0)-(k-i)]:='*';
+            if k<=length(w1)-i then w1[i+k]:='*'
+           else if w2<>'' then w2[k-(length(w1)-i)]:='*';
+        end;
+      end;
+   write(w0);
+   for i:=1 to length(s01) do
+      if s01[i]='n' then writeln
+                    else write(s01[i]);
+   w0:=w1; s01:=s12; w1:=w2; s12:=s23;
+   w2:=''; s23:='';
+end;
+
+begin
+   w0:=''; s01:=''; w1:=''; s12:=''; w2:=''; s23:='';
+   while not eof(input) do begin
+      if eoln(input) then begin
+         readln;
+         s23:=s23+'n';
+      end else begin
+         read(c);
+        if (c >= 'a') and (c <= 'z') or (c >= 'A') and (c <= 'Z') then begin
+           if s23<>'' then shift;
+           w2 := w2+c;
+        end else
+           s23 := s23+c;
+      end;
+   end;
+   shift; shift; shift;
+end.
diff --git a/checkaddr.pl b/checkaddr.pl
new file mode 100644 (file)
index 0000000..8e7addb
--- /dev/null
@@ -0,0 +1,57 @@
+#!/usr/bin/perl
+# A checker for e-mail addresses
+# Written by Martin Mares <mj@ucw.cz> and put into public domain
+
+# We follow the e-mail address syntax in RFC 2822, but with a couple of exceptions:
+# - control characters are not allowed, even if properly escaped
+# - we allow dots not only between non-empty atoms, but also as separate atoms
+# - some obsolete constructs are not supported
+# - at least one dot is required in the domain
+
+sub email_ok($) {
+       my $addr = shift @_;
+       return ($addr =~
+               /^([!#-'*+.-9=?A-Z^-~-]+|"([ !#-\[\]-~]|\\[ -~])*")@([!#-'*+-9=?A-Z^-~-]+\.[!#-'*+.-9=?A-Z^-~-]+|\[([ -Z^-~]|\\[ -~])+(\.|\\\.)([ -Z^-~]|\\[ -~])+\])$/
+       ) ? 1 : 0;
+}
+
+my @tests = (
+       'a.b.c.d' => 0,                 # no @
+       'a@b' => 0,                     # no dot in domain
+       'a@b.c' => 1,                   # ok
+       'a@b@c.d' => 0,                 # multiple @'s
+       '"a@b"@c.d' => 1,               # but ok in quotes
+       'a b@c.d' => 0,                 # spaces not permitted
+       '"a b"@c.d' => 1,               # but again they are ok when quoted
+       '"x y"z@c.d' => 0,              # quoting must not be partial
+       '""@c.d' => 1,                  # strange, but correct
+       '!#$%&*+-/=?^_`{}|@c.d' => 1,   # all sorts of perrmited weird chars
+       '"a \"\\@\@"@c.d' => 1,         # backslash escapes
+       '"\"@c.d' => 0,                 # misquoted
+       '...@c.d' => 1,                 # RFC disallows this, but generally accepted
+       'baba@a b.cz' => 0,             # no spaces in domain
+       'ganesha@a.' => 0,              # dot here is not enough
+       'ganesha@a.b.' => 1,            # but trailing dots are ok, although not canonical
+       'odin@[1.2.3.4]' => 1,          # numeric address
+       'odin@1.2.3.4' => 1,            # correct, although probably undeliverable
+       'odin@[valhalla . gov]' => 1,   # spaces allowed here
+       'odin@[val\[halla\].\\gov]' => 1,  # escapes as well
+       'odin@[val\]' => 0,             # but we must not forget to close ]
+       'odin@[abc].def' => 0,          # mixed is invalid
+       '"@"@[@.@]' => 1,               # wow!
+       '[@.@]@[@.@]' => 0,             # but this is not OK (unquoted "[")
+       'a@a..b' => 1,                  # undeliverable, but syntactically OK
+);
+
+print "Testing:\n";
+while (@tests) {
+       my $addr = shift @tests;
+       my $res = email_ok($addr);
+       print "$addr: $res\n";
+       $res == shift @tests or die "Test failed";
+}
+print "All tests passed.\n\nTry yourself:\n";
+while (<>) {
+       chomp;
+       print email_ok($_), "\n";
+}
diff --git a/chocolate.c b/chocolate.c
new file mode 100644 (file)
index 0000000..8196abe
--- /dev/null
@@ -0,0 +1,30 @@
+#include <stdio.h>
+#include <string.h>
+
+#define MAX 100
+#define MAXT 128
+
+int main(void)
+{
+       int nim[MAX+1][MAX+1];
+       int f[MAXT+1];
+       for (int i=1; i<=MAX; i++) {
+               for (int j=1; j<=MAX; j++) {
+                       bzero(f, sizeof(f));
+                       for (int k=1; k<i; k++)
+                               if ((k != 1 && i-k != 1) || j != 1)
+                                       f[nim[k][j] ^ nim[i-k][j]] = 1;
+                       for (int k=1; k<j; k++)
+                               if (i != 1 || (k != 1 && j-k != 1))
+                                       f[nim[i][k] ^ nim[i][j-k]] = 1;
+                       int z = 0;
+                       while (f[z])
+                               z++;
+                       nim[i][j] = z;
+                       //printf("%d %d -> %d\n", i, j, z);
+                       printf("%d", z);
+               }
+               putchar('\n');
+       }
+       return 0;
+}
diff --git a/count.c b/count.c
new file mode 100644 (file)
index 0000000..4377eb7
--- /dev/null
+++ b/count.c
@@ -0,0 +1,76 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+struct state {
+       struct state *fwd[256], *back, *qnext, *qprev;
+       char *out;
+       int count;
+};
+
+struct state root, *head, *tail;
+
+struct state *step(struct state *s, int c)
+{
+       while (s) {
+               if (s->fwd[c])
+                       return s->fwd[c];
+               s = s->back;
+       }
+       return &root;
+}
+
+void insert(char *x)
+{
+       struct state *s = &root;
+       int c;
+       for (char *y = x; c=*y++; ) {
+               if (!s->fwd[c])
+                       s->fwd[c] = calloc(1, sizeof(struct state));
+               s = s->fwd[c];
+       }
+       s->out = x;
+}
+
+void build(void)
+{
+       struct state *s;
+       head = tail = &root;
+       while (head) {
+               for (int c=0; c<256; c++)
+                       if (s = head->fwd[c]) {
+                               s->back = step(head->back, c);
+                               tail->qnext = s;
+                               s->qprev = tail;
+                               tail = s;
+                       }
+               head = head->qnext;
+       }
+}
+
+void run(void)
+{
+       struct state *s = &root;
+       for (int c; (c = getchar()) != EOF;) {
+               s = step(s, c);
+               s->count++;
+       }
+}
+
+void count(void)
+{
+       for (struct state *s=tail; s != &root; s=s->qprev) {
+               s->back->count += s->count;
+               if (s->out)
+                       printf("%6d %s\n", s->count, s->out);
+       }
+}
+
+int main(int argc, char **argv)
+{
+       for (int i=1; i<argc; i++)
+               insert(argv[i]);
+       build();
+       run();
+       count();
+       return 0;
+}
diff --git a/diary.c b/diary.c
new file mode 100644 (file)
index 0000000..248b2e7
--- /dev/null
+++ b/diary.c
@@ -0,0 +1,105 @@
+/*
+ *     Simple Diary (aka Yet Another Reminder Program)
+ *
+ *     (c) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/time.h>
+
+static FILE *f;
+
+struct entry {
+  struct entry *next;
+  char x[1];
+};
+
+struct entry *fe, **le = &fe;
+
+static void
+scan(time_t when, int cnt)
+{
+  struct tm *tm = localtime(&when);
+  char p[10], xb[256];
+  struct entry *e;
+
+  sprintf(p, "%02d-%02d-%02d", tm->tm_mday, tm->tm_mon+1, tm->tm_year % 100);
+  for(e=fe; e; e=e->next)
+    {
+      char *x, *y;
+      x = e->x;
+      y = p;
+      while (*x && *y)
+       {
+         if (*x != '?' && *x != *y)
+           goto xx;
+         x++, y++;
+       }
+      if (!*x)
+       continue;
+      if (*x > ' ')
+       {
+         if (*x - 'A' < cnt)
+           continue;
+         x++;
+       }
+      strcpy(xb, x);
+      y = strchr(xb, '(');
+      if (y && y[1] && y[2] && y[3] == ')')
+       {
+         int q;
+         sscanf(y+1, "%d", &q);
+         sprintf(y+1, "%02d", tm->tm_year - q);
+         y[3] = ')';
+       }
+      printf("%s:%s\n", p, xb);
+    xx:
+    }
+}
+
+int
+main(int argc, char **argv)
+{
+  char buf[256];
+  int m, cnt;
+  time_t now = time(NULL);
+
+  if (argc < 2 || argc > 3)
+    {
+      fprintf(stderr, "Usage: diary <file> [<days>]\n");
+      return 1;
+    }
+  f = fopen(argv[1], "r");
+  if (!f)
+    {
+      perror("fopen");
+      return 1;
+    }
+  while (fgets(buf, 256, f))
+    {
+      char *b = strchr(buf, '\n');
+      struct entry *e;
+
+      if (!b)
+       break;
+      *b = 0;
+      if (buf[0] <= ' ' || buf[0] == '#')
+       continue;
+      e = malloc(sizeof(struct entry) + strlen(buf));
+      *le = e;
+      le = &e->next;
+      strcpy(e->x, buf);
+    }
+  *le = NULL;
+  m = (argc > 2) ? atol(argv[2]) : 1;
+  cnt = 0;
+  while (m--)
+    {
+      scan(now, cnt);
+      now += 86401;                    /* Dirty trick... */
+      cnt++;
+    }
+  return 0;
+}
diff --git a/false-true/Makefile b/false-true/Makefile
new file mode 100644 (file)
index 0000000..24f41ec
--- /dev/null
@@ -0,0 +1,9 @@
+# Makefile for False True
+
+all: true
+
+true: mktrue
+       ./mktrue
+
+clean:
+       rm -f true
diff --git a/false-true/mktrue b/false-true/mktrue
new file mode 100755 (executable)
index 0000000..7bab592
--- /dev/null
@@ -0,0 +1,62 @@
+#!/usr/bin/perl
+#
+#      'False True' -- An Example of How Not To Write Code
+#
+#      (c) 1998 Martin Mares <mj@ucw.cz>, GPL'ed
+#
+# This is an attempt to write a shortest possible program which is still
+# useful. I decided to make a replacement for `true' (anyway, `false' would
+# fit in the same space as well). It is _NOT_ a correct ELF program (the
+# headers are a bit messy and we have non-zero values in reserved fields
+# and certain mandatory parts are missing), but `file' still recognizes
+# it as ELF (although `objdump' doesn't) and, which is much more important,
+# Linux kernel still runs it. Share and enjoy...
+#
+
+open X, ">true" or die "No write access, no truth";
+while (<DATA>) {
+       s/#.*$//; s/\b(\w{4})(\w{4})\b/$2 $1/g; s/\b(\w\w)(\w\w)\b/$2 $1/g;
+       foreach $a (split /\s+/) { print X pack("c",hex $a); }
+} chmod 0755, "true" or die "Executables aren't";
+
+__END__
+
+7f 45 4c 46                    # Identification
+01                             # We're 32-bit
+01                             # Little endian
+01                             # Header version
+# Next 9 bytes are ELF header padding and RFU, but we dare to put
+# our code into them.
+31 c0                          # xor eax,eax (offset 9)
+40                             # inc eax
+31 db                          # xor ebx,ebx
+cd 80                          # int 0x80
+4d 4a                          # Author's Signature :-)
+0002                           # Type: Executable File
+0003                           # Machine: i386
+00000001                       # Version: Current :)
+10000007                       # Entry point
+0000002c                       # PH offset
+00000000                       # SH offset
+00000000                       # Machine-specific flags
+0034                           # EH size
+0020                           # Size of single PH entry
+0001                           # Number of PH entries
+0000                           # Size of single SH entry
+0000                           # Number of SH entries
+0000                           # String table offset
+
+# Offset 2C: Program Header
+
+# These two entries are overlaid with the ELF header
+#00000001                      # Type: Loadable
+#00000000                      # Offset of section start
+10000000                       # Virtual address
+10000000                       # Physical address: ignored
+0000004c                       # File image size
+0000004c                       # Memory image size
+00000007                       # Flags: rwx
+# Linux doesn't use alignment, so we can omit it. The kernel will try
+# to read the full header size and get 4 bytes less, but it won't
+# complain and it will use whatever was left in the memory. Ugly.
+#00001000                      # Align to page size
diff --git a/false-true/mktrue2 b/false-true/mktrue2
new file mode 100755 (executable)
index 0000000..a1adede
--- /dev/null
@@ -0,0 +1,70 @@
+#!/usr/bin/perl
+
+while (<DATA>) {
+       s/#.*$//; s/\b(\w{4})(\w{4})\b/$2 $1/g; s/\b(\w\w)(\w\w)\b/$2 $1/g;
+       foreach $a (split /\s+/) { print pack("c",hex $a); }
+}
+
+__END__
+
+7f 45 4c 46                    # Identification
+01                             # We're 32-bit
+01                             # Little endian
+01                             # Header version
+00 00000000 00000000           # Padding
+0002                           # Type: Executable File
+0003                           # Machine: i386
+00000001                       # Version: Current :)
+100000A4                       # Entry point
+00000084                       # PH offset
+00000034                       # SH offset
+00000000                       # Machine-specific flags
+0034                           # EH size
+0020                           # Size of single PH entry
+0001                           # Number of PH entries
+0028                           # Size of single SH entry
+0002                           # Number of SH entries
+0000                           # String table offset
+
+# Offset 34: Section Header for section 0
+
+00000000                       # Name (ST offset)
+00000000                       # Type: Void
+00000000                       # Flags
+00000000                       # Address
+00000000                       # Offset
+00000000                       # Size
+00000000                       # Link
+00000000                       # Info
+00000000                       # Align
+00000000                       # Size of single entry
+
+# Offset 5C: Section Header for section 1
+
+00000000                       # Name (ST offset)
+00000001                       # Type: Program bits
+00000007                       # Flags: writeable, allocate, executable
+100000A4                       # Address
+000000A4                       # Offset
+00000009                       # Size
+00000000                       # Link
+00000000                       # Info
+00000000                       # Align
+00000000                       # Size of single entry: No entries
+
+# Offset 84: Program Header
+
+00000001                       # Type: Loadable
+000000A4                       # Offset of section start
+100000A4                       # Virtual address
+100000A4                       # Physical address: ignored
+00000009                       # File image size
+00000009                       # Memory image size
+00000007                       # Flags: rwx
+00001000                       # Align to page size
+
+# Offset A4: Our Program
+
+b8 01 00 00 00
+31 db
+cd 80
diff --git a/false-true/true b/false-true/true
new file mode 100755 (executable)
index 0000000..6e86e34
Binary files /dev/null and b/false-true/true differ
diff --git a/fortcmp.c b/fortcmp.c
new file mode 100644 (file)
index 0000000..ee45606
--- /dev/null
+++ b/fortcmp.c
@@ -0,0 +1,190 @@
+/*
+ *             Fortune Cookie Comparison
+ *
+ *             (c) 1996 Martin Mares, <mj@atrey.karlin.mff.cuni.cz>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static void
+die(char *msg)
+{
+       fputs(msg, stderr);
+       exit(1);
+}
+
+static void *
+xmalloc(unsigned i)
+{
+       void *k = malloc(i);
+
+       if (!k)
+               die("Out of memory!\n");
+       return k;
+}
+
+#define HASH 16384
+
+struct woord {
+       struct woord *next;
+       unsigned id;
+       char w[1];
+       };
+
+static struct woord *words[HASH];
+static unsigned lastid;
+
+static struct woord *
+findword(char *wd)
+{
+       unsigned h;
+       char *c;
+       struct woord *p;
+
+       c = wd;
+       h = strlen(wd);
+       while (*c)
+               h = 13*h + *c++;
+       h = h & (HASH-1);
+       for(p = words[h]; p; p = p->next)
+               if (!strcasecmp(p->w, wd))
+                       return p;
+       p = xmalloc(sizeof(struct woord) + strlen(wd));
+       p->next = words[h];
+       words[h] = p;
+       strcpy(p->w, wd);
+       p->id = lastid++;
+}
+
+#define MFL 4096
+#define FHASH 16384
+
+struct fortune {
+       struct fortune *next;
+       char *fn;
+       unsigned line;
+       unsigned count;
+       unsigned words[0];
+       };
+
+static struct fortune *forts[FHASH];
+
+static int
+comp(unsigned *p, unsigned *q)
+{
+       if (*p < *q)
+               return -1;
+       else if (*p > *q)
+               return 1;
+       else
+               return 0;
+}
+
+static void
+addfort(char *fn, unsigned line, unsigned *fort, unsigned len)
+{
+       unsigned i, h;
+       struct fortune *foo;
+
+//     printf("Adding %s:%d (%d)\n", fn, line, len);
+       qsort(fort, len, sizeof(unsigned), (void *) comp);
+       h = len;
+       for(i=0; i<len; i++)
+               h = 13*h + fort[i];
+       h &= (FHASH-1);
+       for(foo=forts[h]; foo; foo=foo->next)
+               if (len == foo->count && !memcmp(fort, foo->words, sizeof(unsigned)*len))
+                       {
+                               printf("Possible DUP %s:%d with %s:%d\n", fn, line, foo->fn, foo->line);
+                               return;
+                       }
+       foo = xmalloc(sizeof(struct fortune) + sizeof(unsigned)*len);
+       foo->next = forts[h];
+       forts[h] = foo;
+       foo->fn = fn;
+       foo->line = line;
+       foo->count = len;
+       memcpy(foo->words, fort, len * sizeof(unsigned));
+}
+
+static void
+dofort(char *fn)
+{
+       struct woord *name = findword(fn);
+       struct woord *wo;
+       FILE *f;
+       char line[256];
+       unsigned forty[MFL];
+       unsigned posn, lino, cnt, xxx;
+       char *c, *d, e;
+
+       printf("%s...", fn);
+       fflush(stdout);
+       f = fopen(fn, "r");
+       if (!f)
+               die("open failed!\n");
+       xxx = lino = posn = cnt = 0;
+       for(;;)
+               {
+                       lino++;
+                       fgets(line, 256, f);
+                       if (feof(f))
+                               break;
+                       c = strchr(line, '\n');
+                       if (c)
+                               *c = 0;
+                       if (line[0] == '%' && !line[1])
+                               {
+                                       if (cnt)
+                                               {
+                                                       addfort(name->w, posn, forty, cnt);
+                                                       xxx++;
+                                               }
+                                       cnt = 0;
+                               }
+                       else
+                               {
+                                       if (!cnt)
+                                               posn = lino;
+                                       c = line;
+                                       for(;;)
+                                               {
+                                                       while (*c && (*c < 'A' || *c > 'Z') && (*c < 'a' || *c > 'z') && (*c < '0' || *c > '9'))
+                                                               c++;
+                                                       if (!*c)
+                                                               break;
+                                                       d = c;
+                                                       while ((*c >= 'a' && *c <= 'z') || (*c >= 'A' && *c <= 'Z') || (*c >= '0' && *c <= '9'))
+                                                               {
+                                                                       *c = toupper(*c);
+                                                                       c++;
+                                                               }
+                                                       e = *c;
+                                                       *c = 0;
+                                                       wo = findword(d);
+                                                       *c = e;
+                                                       if (cnt >= MFL)
+                                                               die("Too long!\n");
+                                                       forty[cnt++] = wo->id;
+                                               }
+                               }
+               }
+       fclose(f);
+       printf("%d lines, %d fortunes\n", lino, xxx);
+}
+
+int
+main(int argc, char **argv)
+{
+       if (argc < 2)
+               die("Nothing to do.\n");
+       while (argc > 1)
+               {
+                       dofort(argv[1]);
+                       argc--;
+                       argv++;
+               }
+       return 0;
+}
diff --git a/guesstrans.c b/guesstrans.c
new file mode 100644 (file)
index 0000000..9af2284
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+Text Conversion With Guessing
+(c) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+typedef unsigned char uchar;
+
+uchar dest[256],flag[256],line[4096],ans[256];
+int changed;
+
+FILE *ii,*oo;
+#define UNPRINTABLE(c) (c<32 && c != 10 && c != 9 || c >= 0x80 && c < 0xa0)
+
+void putxc(uchar c,int flg)
+{
+       if (!flg && flag[c] || flg && UNPRINTABLE(c)) printf("[%d]",c);
+       else putchar(flg ? c : dest[c]);
+}
+
+void halfcontext(uchar *c,uchar *stop,int flg)
+{
+       while (*c && c != stop)
+               putxc(*c++,flg);
+}
+
+void context(uchar *c)
+{
+       halfcontext(line,c,1);
+       printf("<%d>",*c);
+       halfcontext(c+1,NULL,0);
+}
+
+void main(int ac,char **av)
+{
+       if (ac != 3 && ac != 4)
+               {
+               printf("Syntax: guesstrans <from> <to> [<table>]\n");
+               exit(0);
+               }
+       {
+       int c;
+               for (c=0;c<256;c++) dest[c]=c;
+               for (c=0;c<32;c++) flag[c]=1;
+               for (c=128;c<256;c++) flag[c]=1;
+               flag[13]=0; flag[10]=0; flag[9]=0;
+       }
+       if (ac == 4)
+               {
+               FILE *f;
+                       if (f=fopen(av[3],"r"))
+                               {
+                               if (fread(dest,1,256,f) != 256)
+                                       {
+                                       failed:
+                                               fprintf(stderr,"Error reading translation table!\n");
+                                               exit(1);
+                                       }
+                               if (fread(flag,1,256,f) != 256) goto failed;
+                               fclose(f);
+                               }
+               }
+       if (!(ii=fopen(av[1],"r")))
+               {
+               fprintf(stderr,"Unable to read %s\n",av[1]);
+               exit(1);
+               }
+       if (!(oo=fopen(av[2],"w")))
+               {
+               fprintf(stderr,"Unable to write %s\n",av[2]);
+               exit(1);
+               }
+       while (fgets(line,4096,ii))
+               {
+               uchar *c;
+               if (c = strchr(line, '\r'))
+                       *c = 0;
+               if (!strchr(line, '\n'))
+                       strcat(line, "\n");
+               for(c=line;*c;c++)
+                       {
+                       if (flag[*c])
+                               {
+                               context(c);
+                               gets(ans);
+                               if (*ans && *ans != '\n')
+                                       {
+                                       flag[*c]=0;
+                                       if (*ans == '\\') dest[*c]=atol(ans+1);
+                                       else dest[*c]=*ans;
+                                       changed=1;
+                                       }
+                               }
+                       *c=dest[*c];
+                       }
+               fputs(line,oo);
+               }
+       if (changed && ac == 4)
+               {
+               FILE *f;
+                       if (f=fopen(av[3],"w"))
+                               {
+                               if (fwrite(dest,1,256,f) != 256) goto wrfail;
+                               if (fwrite(flag,1,256,f) != 256) goto wrfail;
+                               }
+                       else
+                               {
+                               wrfail:
+                               fprintf(stderr,"Error writing conversion table!\n");
+                               exit(1);
+                               }
+               }
+}
diff --git a/heapsort.p b/heapsort.p
new file mode 100644 (file)
index 0000000..edf9c2e
--- /dev/null
@@ -0,0 +1,39 @@
+const max=100;
+
+var A:array [1..max] of integer;
+    i,N:integer;
+
+procedure bubbledown(n,i:integer);
+var j,x:integer;
+begin
+   while 2*i <= n do begin
+      j := 2*i;
+      if (j<n) and (A[j+1] > A[j]) then inc(j);
+      if A[i] >= A[j] then break;
+      x := A[i];
+      A[i] := A[j];
+      A[j] := x;
+      i := j;
+   end;
+end;
+
+procedure heapsort;
+var i,x:integer;
+begin
+   for i:=N div 2 downto 1 do
+      bubbledown(N,i);
+   for i:=N downto 2 do begin
+      x := A[1];
+      A[1] := A[i];
+      A[i] := x;
+      bubbledown(i-1,1);
+   end;
+end;
+
+begin
+   read(N);
+   for i:=1 to N do read(A[i]);
+   heapsort;
+   for i:=1 to N do write(A[i], ' ');
+   writeln;
+end.
diff --git a/hidtest b/hidtest
new file mode 100755 (executable)
index 0000000..3f21a82
Binary files /dev/null and b/hidtest differ
diff --git a/hidtest.c b/hidtest.c
new file mode 100644 (file)
index 0000000..0e51a0b
--- /dev/null
+++ b/hidtest.c
@@ -0,0 +1,92 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <asm/types.h>
+#include "/home/mj/linux/linux-2.6.20-rc3/include/linux/hiddev.h"
+
+void die(char *x)
+{
+       fprintf(stderr, "hidtest: %s: %m\n", x);
+       exit(1);
+}
+
+int main(void)
+{
+       int i, j;
+       int fd = open("/dev/usb/hid/hiddev0", O_RDWR);
+       if (fd < 0) die("open");
+
+       int ver;
+       if (ioctl(fd, HIDIOCGVERSION, &ver) < 0)
+               die("getversion");
+       printf("hiddev version %x\n", ver);
+
+       struct hiddev_devinfo di;
+       if (ioctl(fd, HIDIOCGDEVINFO, &di) < 0)
+               die("gdevinfo");
+       printf("%d:%d:%d vendor %04x, product %04x, version %04x, num_appl %d\n",
+               di.busnum, di.devnum, di.ifnum, di.vendor, di.product, di.version, di.num_applications);
+
+#if 0
+       for (i=0; i<100; i++) {
+               struct hiddev_string_descriptor ss;
+               ss.index = 0;
+               if (ioctl(fd, HIDIOCGSTRING, &ss) < 0)
+                       printf("S%d: ???\n", i);
+               else
+                       printf("S%d: %s\n", i, ss.value);
+       }
+#endif
+
+       for (i=0; i<di.num_applications; i++) {
+               int appl = ioctl(fd, HIDIOCAPPLICATION, i);
+               if (appl < 0) die("application");
+               printf("Appl %d: %x\n", i, appl);
+       }
+
+       //ioctl(fd, HIDIOCINITREPORT, 0);
+
+       struct hiddev_report_info rinfo;
+       struct hiddev_field_info finfo;
+       struct hiddev_usage_ref uref;
+       rinfo.report_type = HID_REPORT_TYPE_INPUT;
+       rinfo.report_id = HID_REPORT_ID_FIRST;
+       int ret = ioctl(fd, HIDIOCGREPORTINFO, &rinfo);
+       while (ret >= 0) {
+               printf("rinfo: type=%d, id=%d, fields=%d\n", rinfo.report_type, rinfo.report_id, rinfo.num_fields);
+               for (i = 0; i < rinfo.num_fields; i++) { 
+                       finfo.report_type = rinfo.report_type;
+                       finfo.report_id = rinfo.report_id;
+                       finfo.field_index = i;
+                       ioctl(fd, HIDIOCGFIELDINFO, &finfo);
+                       printf("\tField %d:\n", i);
+                       printf("\t\tflags: %04x, phys: %d, log: %d, appl: %x, log=<%d,%d>, phys=<%d,%d>, unit=%d E%d\n",
+                               finfo.flags, finfo.physical, finfo.logical, finfo.application,
+                               finfo.logical_minimum, finfo.logical_maximum,
+                               finfo.physical_minimum, finfo.physical_maximum,
+                               finfo.unit, finfo.unit_exponent);
+                       for (j = 0; j < finfo.maxusage; j++) {
+                               uref.report_type = finfo.report_type;
+                               uref.report_id = finfo.report_id;
+                               uref.field_index = i;
+                               uref.usage_index = j;
+                               ioctl(fd, HIDIOCGUCODE, &uref);
+                               ioctl(fd, HIDIOCGUSAGE, &uref);
+                               printf("\t\tUsage %d: code=%x, value=%d\n", j, uref.usage_code, uref.value);
+                       }
+               }
+               rinfo.report_id |= HID_REPORT_ID_NEXT;          /* FIXME: bug in hiddev.h, beware */
+               ret = ioctl(fd, HIDIOCGREPORTINFO, &rinfo);
+       }
+
+       int f = HIDDEV_FLAG_UREF;
+       if (ioctl(fd, HIDIOCSFLAG, &f) < 0) die("sflag");
+       struct hiddev_usage_ref ev;
+       while (read(fd, &ev, sizeof(ev))) {
+               printf("EV: %x = %d\n", ev.usage_code, ev.value);
+       }
+
+       return 0;
+}
diff --git a/hobble.c b/hobble.c
new file mode 100644 (file)
index 0000000..c233ba5
--- /dev/null
+++ b/hobble.c
@@ -0,0 +1,248 @@
+/*
+ *             The Hobbling Horse Problem
+ *
+ *             (c) 1996 Martin Mares, <mj@atrey.karlin.mff.cuni.cz>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+
+#define MAX 35
+
+signed char dist[MAX][MAX][2];
+
+signed char queue[15*MAX*MAX];
+
+int M, N, x0, y0, x1, y1;
+
+struct delta { int dx, dy; };
+
+struct delta king[] = { {-1,-1}, {0,-1}, {1,-1}, {-1,0}, {1,0}, {-1,1}, {0,1}, {1,1} };
+struct delta horse[] = { {-1,-2}, {-1,2}, {-2,-1}, {2,-1}, {-2,1}, {2,1}, {1,-2}, {1,2} };
+
+void
+fill(void)
+{
+  int qr, qw, x, y, z, k, xx, yy, rho;
+  struct delta *d;
+
+  memset(dist, 99, sizeof(dist));
+  queue[0] = x0;
+  queue[1] = y0;
+  queue[2] = 0;
+  dist[x0][y0][0] = 0;
+  qr = 0;
+  qw = 3;
+  while (qr < qw)
+       {
+         x = queue[qr++];
+         y = queue[qr++];
+         z = queue[qr++];
+         if (z)
+               {
+                 d = king;
+                 k = sizeof(king) / sizeof(struct delta);
+               }
+         else
+               {
+                 d = horse;
+                 k = sizeof(horse) / sizeof(struct delta);
+               }
+         rho = dist[x][y][z] + 1;
+         z = !z;
+         while (k--)
+               {
+                 xx = x + d->dx;
+                 yy = y + d->dy;
+                 if (xx >= 0 && xx < M && yy >= 0 && yy < N && dist[xx][yy][z] > rho)
+                       {
+                         dist[xx][yy][z] = rho;
+                         queue[qw++] = xx;
+                         queue[qw++] = yy;
+                         queue[qw++] = z;
+                       }
+                 d++;
+               }
+       }
+}
+
+void
+bug1(void)
+{
+  int qr, qw, x, y, z, k, xx, yy, rho;
+  struct delta *d;
+
+  memset(dist, 99, sizeof(dist));
+  queue[0] = x0;
+  queue[1] = y0;
+  dist[x0][y0][0] = 0;
+  qr = 0;
+  qw = 2;
+  while (qr < qw)
+       {
+         x = queue[qr++];
+         y = queue[qr++];
+         rho = dist[x][y][0] + 1;
+         z = rho & 1;
+         if (!z)
+               {
+                 d = king;
+                 k = sizeof(king) / sizeof(struct delta);
+               }
+         else
+               {
+                 d = horse;
+                 k = sizeof(horse) / sizeof(struct delta);
+               }
+         while (k--)
+               {
+                 xx = x + d->dx;
+                 yy = y + d->dy;
+                 if (xx >= 0 && xx < M && yy >= 0 && yy < N && dist[xx][yy][0] > rho)
+                       {
+                         dist[xx][yy][0] = rho;
+                         queue[qw++] = xx;
+                         queue[qw++] = yy;
+                       }
+                 d++;
+               }
+       }
+}
+
+void
+draw(void)
+{
+  int i,j,k,l;
+
+  for(i=0; i<N; i++)
+       {
+         for(j=0; j<M; j++)
+               {
+                 k = dist[j][i][0];
+                 l = dist[j][i][1];
+                 if (k > l)
+                       k = l;
+                 printf("%3d", k);
+               }
+         putchar('\n');
+       }
+}
+
+int
+dlt(int a, int b)
+{
+  if (a < b)
+       return b-a;
+  else
+       return a-b;
+}
+
+void
+checkpath(int lim)
+{
+  int x,y,d;
+
+  x = x0;
+  y = y0;
+  d = 0;
+  for(;;)
+       {
+//       printf("%d %d\n", x, y);
+         if (dist[x][y][0] > d++)
+               {
+                 printf("BUG: %dx%d: %d.%d->%d.%d\n", M, N, x0, y0, x1, y1);
+                 exit(1);
+               }
+         if (dlt(x, x1) <= lim && dlt(y, y1) <= lim)
+               break;
+         if (dlt(x, x1) > dlt(y, y1))
+               {
+                 if (x < x1)
+                       x += 2;
+                 else if (x > x1)
+                       x -= 2;
+                 else if (x >= M/2)
+                       x -= 2;
+                 else
+                       x += 2;
+                 if (y < y1)
+                       y++;
+                 else if (y > y1)
+                       y--;
+                 else if (y >= N/2)
+                       y--;
+                 else
+                       y++;
+               }
+         else
+               {
+                 if (y < y1)
+                       y += 2;
+                 else if (y > y1)
+                       y -= 2;
+                 else if (y >= N/2)
+                       y -= 2;
+                 else
+                       y += 2;
+                 if (x < x1)
+                       x++;
+                 else if (x > x1)
+                       x--;
+                 else if (x >= M/2)
+                       x--;
+                 else
+                       x++;
+               }
+//       printf("%d %d\n", x, y);
+         if (dist[x][y][1] > d++)
+               {
+                 printf("BUG: %dx%d: %d.%d->%d.%d\n", M, N, x0, y0, x1, y1);
+                 exit(1);
+               }
+         if (dlt(x, x1) <= lim && dlt(y, y1) <= lim)
+               break;
+         if (x < x1)
+               x++;
+         else if (x > x1)
+               x--;
+         if (y < y1)
+               y++;
+         else if (y > y1)
+               y--;
+       }
+}
+
+int
+main(void)
+{
+  int i;
+
+  srand(time(NULL));
+
+#if 1
+  for(i=0; i<100000; i++)
+       {
+         M = 2 + rand() % 5;
+         N = 3 + rand() % 5;
+         x0 = rand() % M;
+         y0 = rand() % N;
+         x1 = rand() % M;
+         y1 = rand() % N;
+         printf("\n %dx%d: %d.%d->%d.%d\n", M, N, x0, y0, x1, y1);
+         fill();
+         draw();
+         checkpath(2);
+       }
+#else
+  M = 30;
+  N = 30;
+  x0 = 13;
+  y0 = 14;
+  fill();
+  draw();
+#endif
+
+  return 0;
+}
diff --git a/hull b/hull
new file mode 100755 (executable)
index 0000000..79467f9
Binary files /dev/null and b/hull differ
diff --git a/hull.c b/hull.c
new file mode 100644 (file)
index 0000000..f9679a0
--- /dev/null
+++ b/hull.c
@@ -0,0 +1,62 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#define MAX 20000
+
+struct pt { int x, y; char c; };
+
+struct pt pt[MAX];
+int N;
+typedef long long int ll;
+struct pt up[MAX], down[MAX];
+int Nu, Nd;
+
+int cmp(const void *X, const void *Y)
+{
+       const struct pt *x = X, *y = Y;
+       if (x->x < y->x)
+               return -1;
+       if (x->x > y->x)
+               return 1;
+       return 0;
+}
+
+ll sign(ll ax, ll ay, ll bx, ll by)
+{
+       return ax*by - ay*bx;
+}
+
+int main(void)
+{
+       N=0;
+       while (scanf("%d %d '%c'", &pt[N].x, &pt[N].y, &pt[N].c) == 3) {
+               //pt[N].y -= 4000000; pt[N].x -= 4000000;
+               N++;
+       }
+       qsort(pt, N, sizeof(pt[0]), cmp);
+       //for (int i=0; i<N; i++) printf("%d %d %c\n", pt[i].x, pt[i].y, pt[i].c);
+       //printf("%d\n", (int) sign(-2,1,2,0));
+       //printf("%d\n", (int) sign(-2,-1,2,0));
+
+       Nu = Nd = 1;
+       up[0] = down[0] = pt[0];
+       for (int i=1; i<N; i++) {
+               while (Nu > 1 && sign(up[Nu-2].x - up[Nu-1].x, up[Nu-2].y - up[Nu-1].y,
+                             pt[i].x    - up[Nu-1].x, pt[i].y    - up[Nu-1].y) < 0)
+               Nu--;
+               up[Nu++] = pt[i];
+               while (Nd > 1 && sign(down[Nd-2].x - down[Nd-1].x, down[Nd-2].y - down[Nd-1].y,
+                                     pt[i].x      - down[Nd-1].x, pt[i].y      - down[Nd-1].y) > 0)
+                       Nd--;
+               down[Nd++] = pt[i];
+       }
+
+       printf("### Upper hull:\n");
+       for (int i=0; i<Nu; i++)
+               printf("%7d %7d '%c'\n", up[i].x, up[i].y, up[i].c);
+       printf("### Lower hull:\n");
+       for (int i=0; i<Nd; i++)
+               printf("%7d %7d '%c'\n", down[i].x, down[i].y, down[i].c);
+       
+       return 0;
+}
diff --git a/ictest.i b/ictest.i
new file mode 100644 (file)
index 0000000..7dd0e25
--- /dev/null
+++ b/ictest.i
@@ -0,0 +1,12 @@
+       DO .1 <- #1
+       DO (1) NEXT
+       PLEASE GIVE UP
+(1)    DO COME FROM (3)
+       PLEASE READ OUT .1
+       DO (1020) NEXT
+       DO .3 <- 'V\b-.1$#65434'~'#0$#65535'
+       DO .3 <- '.3~.3'~#32768
+       DO (2) NEXT
+(3)    PLEASE NOTE THIS LINE DOES ALMOST NOTHING
+(2)    PLEASE FORGET .3
+       DO RESUME #1
diff --git a/jukebox.c b/jukebox.c
new file mode 100644 (file)
index 0000000..679b968
--- /dev/null
+++ b/jukebox.c
@@ -0,0 +1,154 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <glib.h>
+#include <xmms/xmmsctrl.h>
+
+#define session 0
+
+struct pl {
+       struct pl *next;
+       int id;
+       char *name;
+       int tstart, tstop, fstart, fstop;
+};
+
+static struct pl *
+load_pl(char *name)
+{
+       struct pl *pl = NULL, *p, **l = &pl;
+       int cnt = 0;
+       char buf[1024], b2[1024];
+       FILE *f = fopen(name, "r");
+       if (!f) {
+               fprintf(stderr, "Unable to open %s: %m\n", name);
+               exit(1);
+       }
+       while (fgets(buf, sizeof(buf), f)) {
+               p = malloc(sizeof(struct pl));
+               p->id = cnt++;
+               if (sscanf(buf, "%d%d %[^\n]", &p->tstart, &p->tstop, b2) != 3) {
+                       fprintf(stderr, "Syntax error in %s, line %d\n", name, cnt);
+                       exit(1);
+               }
+               p->name = g_strdup(b2);
+               p->fstart = p->tstart + 1000;
+               p->fstop = p->tstop - 1000;
+               printf("%02d: <%s> %d %d %d %d\n", p->id, p->name, p->tstart, p->fstart, p->fstop, p->tstop);
+               *l = p;
+               l = &p->next;
+       }
+       *l = NULL;
+       fclose(f);
+       if (!pl) {
+               fprintf(stderr, "The track list is empty!\n");
+               exit(1);
+       }
+       return pl;
+}
+
+static void
+feed_pl(struct pl *pl)
+{
+       GList *l;
+       xmms_remote_stop(session);
+       xmms_remote_set_main_volume(session, 0);
+       xmms_remote_playlist_clear(session);
+       l = NULL;
+       while (pl) {
+               l = g_list_append(l, pl->name);
+               pl = pl->next;
+       }
+       xmms_remote_playlist_add(session, l);
+       g_list_free(l);
+}
+
+void fade_in(int l)
+{
+       int t0 = xmms_remote_get_output_time(session);
+       for(;;) {
+               int t = xmms_remote_get_output_time(session) - t0;
+               printf("%d %d\n",t,t0 );
+               if (t >= l || t < 0) {
+                       xmms_remote_set_main_volume(session, 100);
+                       return;
+               }
+               xmms_remote_set_main_volume(session, t*100/l);
+//             usleep(10000);
+       }
+}
+
+static void
+vol(int n)
+{
+       static int lv = -1;
+       if (lv != n) {
+               lv = n;
+               xmms_remote_set_main_volume(session, n);
+       }
+}
+
+int main(int argc, char **argv)
+{
+       struct pl *pl, *this = NULL;
+       int state = -1, st, t;
+
+       if (argc != 2) {
+               fprintf(stderr, "Usage: jukebox <file-with-track-list>\n");
+               return 1;
+       }
+       pl = load_pl(argv[1]);
+
+       if (!xmms_remote_is_running(session)) {
+               fprintf(stderr, "No XMMS session found.\n");
+               return 1;
+       }
+       feed_pl(pl);
+       for(;;) {
+               if (!xmms_remote_is_running(session)) {
+                       fprintf(stderr, "XMMS exited.\n");
+                       return 0;
+               }
+               if (!xmms_remote_is_playing(session)) {
+                       if (state >= 0) {
+                               state = -1;
+                               puts("### Stop");
+                               vol(0);
+                       }
+               } else {
+                       st = xmms_remote_get_playlist_pos(session);
+                       if (state != st) {
+                               state = st;
+                               printf("### Start %d\n", state);
+                               for (this=pl; this && this->id != state; this = this->next)
+                                       ;
+                               if (!this) {
+                                       fprintf(stderr, "Internal error: unknown song ID\n");
+                                       return 1;
+                               }
+                               vol(0);
+                               xmms_remote_jump_to_time(session, this->tstart);
+                       }
+                       t = xmms_remote_get_output_time(session);
+                       //printf(" %d %d\n", st, t);
+                       if (t < this->tstart)
+                               ;
+                       else if (t < this->fstart)
+                               vol(100 * ((t - this->tstart) / (float)(this->fstart - this->tstart)));
+                       else if (t < this->fstop)
+                               vol(100);
+                       else if (t < this->tstop)
+                               vol(100 * (1-((t - this->fstop) / (float)(this->tstop - this->fstop))));
+                       else {
+                               vol(0);
+                               if (this->next)
+                                       xmms_remote_playlist_next(session);
+                               else
+                                       xmms_remote_stop(session);
+                       }
+               }
+               usleep(10);
+       }
+       return 0;
+}
diff --git a/jukebox.mk b/jukebox.mk
new file mode 100644 (file)
index 0000000..d24773b
--- /dev/null
@@ -0,0 +1,10 @@
+
+GLIB_CFLAGS:=$(shell glib-config --cflags)
+GLIB_LDFLAGS:=$(shell glib-config --libs)
+
+CFLAGS=-O2 -Wall -W $(GLIB_CFLAGS)
+LDFLAGS=$(GLIB_LDFLAGS) -lxmms
+
+all: jukebox
+
+jukebox: jukebox.c
diff --git a/logik1.c b/logik1.c
new file mode 100644 (file)
index 0000000..09c5d40
--- /dev/null
+++ b/logik1.c
@@ -0,0 +1,138 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define BITS 10
+#define NUM (1 << BITS)
+
+static char state[NUM];
+static int question;
+
+static void
+calc_answer(int secret, int guess, int *black, int *white)
+{
+  int b = 0, w = 0, i;
+  int s0=0, s1=0, g0=0, g1=0;
+
+  for(i=0; i<BITS; i++)
+    if (!((secret^guess) & (1 << i)))
+      b++;
+    else
+      {
+       if (secret & (1 << i))
+         s1++;
+       else
+         s0++;
+       if (guess & (1 << i))
+         g1++;
+       else
+         g0++;
+      }
+
+  w = ((s0 < g0) ? s0 : g0) + ((s1 < g1) ? s1 : g1);
+
+  *black = b;
+  *white = w;
+}
+
+static void
+find_best(void)
+{
+  int i, j, x, y, best, besti, total, black, white, answer[BITS+1][BITS+1];
+
+  total = 0;
+  best = -1;
+  for(i=0; i<NUM; i++)
+    {
+      if (!state[i])
+       {
+         best = i;
+         total++;
+       }
+    }
+  if (total == 1)
+    {
+      printf("Final decision: %02x\n", best);
+      question = best;
+      return;
+    }
+  best = -1;
+  besti = NUM+1;
+  for(i=0; i<NUM; i++)
+    {
+      bzero(answer, sizeof(answer));
+      for(j=0; j<NUM; j++)
+       if (!state[j])
+         {
+           calc_answer(i, j, &black, &white);
+           answer[black][white]++;
+         }
+      j = 0;
+      for(x=0; x<=BITS; x++)
+       for(y=0; y<=BITS; y++)
+         if (answer[x][y] > j)
+           j = answer[x][y];
+      if (j <= besti)
+       {
+         besti = j;
+         best = i;
+       }
+    }
+  question = best;
+  printf("Selected %04x, %d of %d\n", best, besti, total);
+}
+
+static void
+recalc(int b, int w)
+{
+  int bl, wh, i, red = 0;
+
+  for(i=0; i<NUM; i++)
+    if (!state[i])
+      {
+       calc_answer(i, question, &bl, &wh);
+       if (b != bl || w != wh)
+         {
+//         printf("Throwing out %02x (%d,%d) != (%d,%d)\n", i, b, w, bl, wh);
+           state[i] = 1;
+         }
+       else
+         red++;
+      }
+  printf("Reduced to %d\n", red);
+  if (!red)
+    {
+      puts("ERROR");
+      exit(1);
+    }
+}
+
+int
+main(void)
+{
+  int b, w;
+  int secr, round, maxr=0;
+
+  for(secr=0; secr<NUM; secr++)
+    {
+      printf("SECRET=%02x\n", secr);
+      bzero(state, sizeof(state));
+      round=0;
+      for(;;)
+       {
+         round++;
+         find_best();
+         calc_answer(secr, question, &b, &w);
+         printf("%d: Answer is %d/%d\n", round, b, w);
+         if (b == BITS)
+           break;
+         recalc(b, w);
+       }
+      if (round > maxr)
+       maxr = round;
+      puts("------------------------------------------");
+    }
+  printf("MAX=%d rounds\n", maxr);
+
+  return 0;
+}
diff --git a/logik2.c b/logik2.c
new file mode 100644 (file)
index 0000000..48d300d
--- /dev/null
+++ b/logik2.c
@@ -0,0 +1,277 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define ORDER 5
+#define COLORS 8
+#define SHOTS 4
+
+int states;
+char *flags;
+int secret;
+
+int
+pack(int *z)
+{
+  int k = 0;
+  int i;
+
+  for(i=0; i<ORDER; i++)
+    k = k*COLORS + *z++;
+  return k;
+}
+
+void
+unpack(int k, int *z)
+{
+  int i;
+
+  for(i=ORDER-1; i >= 0; i--)
+    {
+      z[i] = k % COLORS;
+      k /= COLORS;
+    }
+}
+
+void
+eval(int *sec, int *guess, int *black, int *white)
+{
+  int b, w, i, sc[COLORS], gc[COLORS];
+
+  b = 0;
+  bzero(sc, sizeof(sc));
+  bzero(gc, sizeof(gc));
+  for(i=0; i<ORDER; i++)
+    if (sec[i] == guess[i])
+      b++;
+    else
+      {
+       sc[sec[i]]++;
+       gc[guess[i]]++;
+      }
+  w = 0;
+  for(i=0; i<COLORS; i++)
+    if (gc[i] <= sc[i])
+      w += gc[i];
+    else
+      w += sc[i];
+  *black = b;
+  *white = w;
+}
+
+void
+show(int i)
+{
+  int j, z[ORDER];
+
+  unpack(i, z);
+  for(j=0; j<ORDER; j++)
+    printf(" %d", z[j]);
+}
+
+int
+xrand(int sz)
+{
+  unsigned int i, ramax, RMX;
+
+  RMX = RAND_MAX + 1U;
+  ramax = RMX - (RMX % sz);
+  do
+    i = random();
+  while (i >= ramax);
+  i %= sz;
+  return i;
+}
+
+#if 1
+
+int sec[ORDER];
+
+#if 0
+
+void
+pl_init(void)
+{
+  int i;
+
+  printf("Secret: ");
+  for(i=0; i<ORDER; i++)
+    scanf("%d", &sec[i]);
+  secret = pack(sec);
+  printf("Check:");
+  show(secret);
+  putchar('\n');
+}
+
+#else
+
+void
+pl_init(void)
+{
+  secret = xrand(states);
+  printf("Secret: ");
+  unpack(secret, sec);
+  show(secret);
+  putchar('\n');
+}
+
+#endif
+
+void
+pl_eval(int *guess, int *b, int *w)
+{
+  eval(sec, guess, b, w);
+}
+
+#else
+
+void
+pl_init(void)
+{
+}
+
+void
+pl_eval(int *guess, int *b, int *w)
+{
+  printf(" ...? ");
+  fflush(stdout);
+  scanf("%d%d", b, w);
+}
+
+#endif
+
+int
+reduce(int *gue, int b0, int w0)
+{
+  int i,b,w,z[ORDER],c=0;
+
+  for(i=0; i<states; i++)
+    if (!flags[i])
+      {
+       unpack(i, z);
+       eval(z, gue, &b, &w);
+       if (b != b0 || w != w0)
+         flags[i] = 1;
+       else
+         c++;
+      }
+  if (!c)
+    {
+      puts("THIS CANNOT HAPPEN!");
+      exit(1);
+    }
+  return c;
+}
+
+int
+gen(int sz)
+{
+  int i,j;
+
+  i = xrand(sz);
+  for(j=0;;j++)
+    if (!flags[j])
+      if (!i--)
+       return j;
+}
+
+int
+howbad(int *z)
+{
+  int G = 0;
+  int i,b,w;
+  int cc[ORDER+1][ORDER+1], g[ORDER];
+
+  bzero(cc, sizeof(cc));
+  for(i=0; i<states; i++)
+    if (!flags[i])
+      {
+       unpack(i, g);
+       eval(g, z, &b, &w);
+       cc[b][w]++;
+      }
+  for(b=0; b<=ORDER; b++)
+    for(w=0; w<=ORDER; w++)
+      if (cc[b][w] > G)
+       G = cc[b][w];
+  return G;
+}
+
+int
+find_best(void)
+{
+  int shot[SHOTS], badness[SHOTS], i, z[ORDER], sz, whe, besti, best, worsti;
+
+  sz = 0; whe = 0;
+  for(i=0; i<states; i++)
+    if (!flags[i])
+      {
+       sz++;
+       whe = i;
+      }
+  if (sz == 1)
+    {
+      printf("SAFE ");
+      return whe;
+    }
+  best = 0;
+  besti = sz+1;
+  worsti = 0;
+  for(i=0; i<SHOTS; i++)
+    {
+      shot[i] = gen(sz);
+      unpack(shot[i], z);
+      badness[i] = howbad(z);
+//      printf("Try:");
+//      show(shot[i]);
+//     printf(" (%d/%d)\n", badness[i], sz);
+      if (badness[i] < besti)
+       {
+         best = i;
+         besti = badness[i];
+       }
+      if (badness[i] > worsti)
+       worsti = badness[i];
+    }
+//  printf("Best: %d (%d)\n", best, besti);
+  printf("(%7d-%7d/%7d) ", worsti, besti, sz);
+  return shot[best];
+}
+
+int
+main(void)
+{
+  int i,gue[ORDER],round,b,w,wc=0,N=0,sum=0;
+
+  states = 1;
+  for(i=0; i<ORDER; i++)
+    states *= COLORS;
+  printf("%d positions, %d colors, %d states\n", ORDER, COLORS, states);
+  flags = malloc(sizeof(char) * states);
+
+  for(;;)
+    {
+      N++;
+      bzero(flags, sizeof(char) * states);
+      pl_init();
+      round = 0;
+      for(;;)
+       {
+         i = find_best();
+         printf("Q%d:", ++round);
+         show(i);
+         unpack(i,gue);
+         pl_eval(gue, &b, &w);
+         printf(" -> %d/%d -> %d states\n", b, w, reduce(gue,b,w));
+         if (b == ORDER)
+           break;
+       }
+      if (round > wc)
+       wc = round;
+      sum += round;
+      printf("--- DONE --- (try=%d, worst case=%d, avg=%d) ---\n", N, wc, (sum+N-1)/N);
+    }
+
+  return 0;
+}
+
diff --git a/math.c b/math.c
new file mode 100644 (file)
index 0000000..f563e41
--- /dev/null
+++ b/math.c
@@ -0,0 +1,400 @@
+/*
+Simple Numeric Operations
+(c) 1995 Martin Mares, MJSoft System Software
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define MAXSTEPS 9
+#define MAXNUM 5001
+
+#define FIRSTUNARY 10
+#define NUMOPS 15
+
+int able[MAXSTEPS+1][MAXNUM];
+int func[MAXSTEPS+1][MAXNUM];
+int op1[MAXSTEPS+1][MAXNUM];
+int op2[MAXSTEPS+1][MAXNUM];
+int op1l[MAXSTEPS+1][MAXNUM];
+int op2l[MAXSTEPS+1][MAXNUM];
+int max[MAXSTEPS+1];
+int penalty[MAXSTEPS+1][MAXNUM];
+
+int maxdisp,digit,maxsteps,maxnum;
+
+/*            0 1 2 3 4 5 6  7  8  9 10 1112  13  */
+#if 0
+int pen[] = { 1,1,2,2,6,3,60,30,60,6,4,20,3,150,150 };
+#else
+int pen[] = { 1,1,2,2,5,3,8 ,6 ,8 ,5,4,6 ,3,13 ,13  };
+#endif
+/*            + - * / % ^ @  C  $  \ ! S  R r   t   */
+int pri[] = { 2,2,3,3,4,5,3, 7, 3, 3,9,7, 7,7,  7   };
+
+/* PRI == 7 <=> left-associative function with no priority */
+
+int op(int code,int a,int b,int src1,int src2)
+{
+int i,j,k,l;
+   switch(code)
+          {
+               case 0: return a+b;
+               case 1: return a-b;
+               case 2: return a*b;
+               case 3: if (b && !(a%b)) return a/b; else return -1; /* DIV */
+               case 4: if (b) return a%b; else return -1;                        /* MODULO */
+               case 5: i=1;                                                                                                      /* POWER */
+                                 while (b--)
+                                    {
+                                         i *= a;
+                                         if (i >= maxnum) return -1;
+                                         }
+                                 return i;
+               case 6: if (!b || a%b || able[src2][b] != 2) return -1; /* A/.(B) */
+                                 i=0;
+                                 a/=b;
+                                 while (b)
+                                    {
+                                         i=i*10+9;
+                                         b/=10;
+                                         }
+                                 return a*i;
+               case 7: if (a < b) return -1;                                                                   /* COMBINATION */
+                                 i=1; j=a; k=2; l=b;
+                                 while (l || k<=b)
+                                    {
+                                         while (k<=b && !(i%k))
+                                            {
+                                                 i/=k;
+                                                 k++;
+                                                 }
+                                         if (l)
+                                            {
+                                                 i*=j;
+                                                 l--;
+                                                 j--;
+                                                 }
+                                         if (i>100000) return -1;
+                                         }
+                                 return i;
+               case 8: if (!b || a%b || able[src2][b] != 2) return -1; /* A/.B */
+                                 i=1;
+                                 a/=b;
+                                 while (b)
+                                    {
+                                         i=i*10;
+                                         b/=10;
+                                         }
+                                 return a*i;
+               case 9: if (b) return a/b; else return -1;                              /* DIV */
+               case FIRSTUNARY: i=1;                                                                                   /* FACT */
+                                 while (a)
+                                    {
+                                         i*=a;
+                                         if (i >= maxnum) return -1;
+                                         a--;
+                                         }
+                                 return i;
+               case FIRSTUNARY+1: if (a) return 1; else return 0;                      /* SIGNUM */
+               case FIRSTUNARY+2: for(i=0;i<maxnum;i++)                                                /* ROOT */
+                          {
+                                         j=i*i;
+                                         if (j == a) return i;
+                                         if (j > a) return -1;
+                                         }
+                                       return -1;
+               case FIRSTUNARY+3: for(i=0;i<maxnum;i++)                                                /* UPPER ROOT */
+                          {
+                                         j=i*i;
+                                         if (j >= a) return i;
+                                         }
+                                 return -1;
+               case FIRSTUNARY+4: for(i=0;i<maxnum;i++)                                                /* LOWER ROOT */
+                          {
+                                         j=i*i;
+                                         if (j == a) return i;
+                                         if (j > a) return i-1;
+                                         }
+                                 return -1;
+               }
+       return -1;
+}
+
+int doop(int dest,int k,int i,int j,int src1,int src2,int p)
+{
+int l = op(k,i,j,src1,src2);
+       if (l>=0 && l<maxnum)
+          if (!able[dest][l] || penalty[dest][l] > p+pen[k])
+          {
+               able[dest][l] = 1;
+          func[dest][l] = k;
+               op1[dest][l] = i;
+               op1l[dest][l] = src1;
+               op2[dest][l] = j;
+               op2l[dest][l] = src2;
+               penalty[dest][l] = p+pen[k];
+               if (l > max[dest]) max[dest] = l;
+               return 1;
+               }
+       return 0;
+}
+
+void try(int dest,int src1,int src2)
+{
+int i,j,k,l;
+       fprintf(stderr,"Trying %d %d -> %d\n",src1+1,src2+1,dest+1);
+       l=0;
+   for(i=0;i<=max[src1];i++)
+          if (able[src1][i])
+                       {
+                       if (i-l>=10 || i<15) { fprintf(stderr,"%d\r",i); l=i; }
+                  for(j=0;j<=max[src2];j++)
+                          if (able[src2][j])
+                                  for(k=0;k<FIRSTUNARY;k++)
+                                               doop(dest,k,i,j,src1,src2,penalty[src1][i]+penalty[src2][j]);
+                       }
+}
+
+void tryuna(int dest)
+{
+int i,j,k;
+       fprintf(stderr,"Trying unary ops for level %d\n",dest+1);
+       do
+          {
+       j=0;
+          for(i=0;i<=max[dest];i++)
+                  if (able[dest][i])
+                               for(k=FIRSTUNARY;k<NUMOPS;k++)
+                                  if (doop(dest,k,i,0,dest,0,penalty[dest][i]))
+                                          j=1;
+               }
+       while (j);
+}
+
+#ifdef SIMPLE_DUMP
+
+void dump(int level,int i)
+{
+   if (able[level][i] == 2) printf("%d",i);
+       else if (func[level][i] < FIRSTUNARY)
+          {
+               putchar('(');
+               dump(op1l[level][i],op1[level][i]);
+               putchar("+-*/%^@C$\\"[func[level][i]]);
+               dump(op2l[level][i],op2[level][i]);
+               putchar(')');
+               }
+       else
+          {
+               putchar("!SRrt"[func[level][i]-FIRSTUNARY]);
+               putchar('(');
+               dump(op1l[level][i],op1[level][i]);
+               putchar(')');
+               }
+}
+
+#else
+
+union par {
+       int value;
+       struct node *p;
+       };
+
+struct node {
+       unsigned char op;
+       union par a[2];
+       };
+
+#define OP_CONST 0xff
+
+char *unam[] = {"sgn","sqr","ceil sqr","int sqr"};
+
+struct node *firstfree;
+
+struct node *obtain_node(void)
+{
+struct node *p;
+       if (firstfree)
+               {
+               p=firstfree;
+               firstfree=p->a[0].p;
+               }
+       else p=malloc(sizeof(struct node));
+       return p;
+}
+
+void free_node(struct node *p)
+{
+       p->a[0].p = firstfree;
+       firstfree=p;
+}
+
+void free_tree(struct node *p)
+{
+       if (p->op != OP_CONST)
+               {
+               free_tree(p->a[0].p);
+               if (p->op < FIRSTUNARY) free_tree(p->a[1].p);
+               }
+       free_node(p);
+}
+
+struct node *build_tree(int level,int i)
+{
+struct node *p = obtain_node();
+       if (able[level][i] == 2)
+               {
+               p->op = OP_CONST;
+               p->a[0].value = i;
+               }
+       else
+               {
+               p->op = func[level][i];
+               p->a[0].p = build_tree(op1l[level][i],op1[level][i]);
+               if (p->op < FIRSTUNARY)
+                       p->a[1].p = build_tree(op2l[level][i],op2[level][i]);
+               }
+       return p;
+}
+
+void print_tree(struct node *n,int p,int orop)
+{
+int g,r;
+       if (n->op == OP_CONST) printf("%d",n->a[0].value);
+       else
+               {
+               g = (pri[n->op] < p
+                   || (pri[n->op] == p &&
+                                 (orop == 1 || orop == 3 || orop == 4 || orop == 6
+                                            || orop == 8))
+                       );
+               if (g) putchar('(');
+               r=pri[n->op];
+               if (r==7) r=0;
+               if (n->op <= 5)         /* standard binary */
+                       {
+                       print_tree(n->a[0].p,r,n->op);
+                       putchar("+-*/%^"[n->op]);
+                       print_tree(n->a[1].p,r,n->op);
+                       }
+               else if (n->op == 6)            /* /.() */
+                       {
+                       print_tree(n->a[0].p,r,n->op);
+                       printf("/.(");
+                       print_tree(n->a[1].p,r,n->op);
+                       putchar(')');
+                       }
+               else if (n->op == 7)            /* COMB */
+                       {
+                       printf("C(");
+                       print_tree(n->a[0].p,r,n->op);
+                       putchar(',');
+                       print_tree(n->a[1].p,r,n->op);
+                       putchar(')');
+                       }
+               else if (n->op == 8)            /* /. */
+                       {
+                       print_tree(n->a[0].p,r,n->op);
+                       printf("/.");
+                       print_tree(n->a[1].p,r,n->op);
+                       }
+               else if (n->op == 9)            /* DIV */
+                       {
+                       print_tree(n->a[0].p,r,n->op);
+                       putchar('\\');
+                       print_tree(n->a[1].p,r,n->op);
+                       }
+               else if (n->op == FIRSTUNARY)           /* FACT */
+                       {
+                       print_tree(n->a[0].p,r,n->op);
+                       putchar('!');
+                       }
+               else                                                                            /* classical prefix unary */
+                       {
+                       printf(unam[n->op-FIRSTUNARY-1]);
+                       print_tree(n->a[0].p,255,255);
+                       }
+               if (g) putchar(')');
+               }
+}
+
+void dump(int level,int i)
+{
+struct node *root;
+       root = build_tree(level,i);
+       print_tree(root,0,-1);
+       free_tree(root);
+}
+
+#endif
+
+void fillin(void)
+{
+int i,j;
+       i=0;
+       for(j=0;j<=maxsteps;j++)
+               {
+               i=i*10+digit;
+               if (i>=maxnum) return;
+               able[j][i]=2;
+               max[j]=i;
+               }
+}
+
+void findall(void)
+{
+int steps,i;
+       tryuna(0);
+       for(steps=1;steps<=maxsteps;steps++)
+          {
+               for(i=0;i<steps;i++)
+                  try(steps,i,steps-i-1);
+               tryuna(steps);
+               }
+}
+
+void prtall(void)
+{
+int steps,totb,i;
+       putchar('\n');
+       steps=0; totb=0;
+       for(i=0;i<maxdisp;i++)
+          if (able[maxsteps][i])
+                  {
+                       printf("%d = ",i);
+                  dump(maxsteps,i);
+                       printf("  {%d}\n",penalty[maxsteps][i]);
+                       totb += penalty[maxsteps][i];
+                       steps++;
+                       }
+               else printf("%d : MISSING\n",i);
+       printf("%d of %d. {%d}\n",steps,maxdisp,totb);
+}
+
+void err(char *e)
+{
+       fprintf(stderr,e);
+       exit(1);
+}
+
+int main(int argc,char **argv)
+{
+       if (argc != 5)
+               {
+               printf("Usage: math <digit> <count> <limit> <calclimit>\n");
+               return 0;
+               }
+       digit = atol(argv[1]);
+       if (digit<0 || digit>9) err("Invalid digit!");
+       maxsteps = atol(argv[2])-1;
+       if (maxsteps<0 || maxsteps>MAXSTEPS) err("Invalid digit count!");
+       maxdisp = atol(argv[3])+1;
+       maxnum = atol(argv[4])+1;
+       if (maxnum<1 || maxnum>MAXNUM) err("Invalid internal maximum!");
+       if (maxdisp<1 || maxdisp>maxnum) err("Invalid limit!");
+       fillin();
+       findall();
+       prtall();
+       return 0;
+}
diff --git a/merge.c b/merge.c
new file mode 100644 (file)
index 0000000..6df6ff1
--- /dev/null
+++ b/merge.c
@@ -0,0 +1,138 @@
+/* In-place merging of integer sequences */
+
+#define MIN(x,y) ((x)<(y) ? (x) : (y))
+#define SWAP(x,y) do { int _=(x); (x)=(y); (y)=_; } while(0)
+#define BLEN(x) ((x) == p1pos ? p1len : (x) == p2pos ? p2len : B)
+
+static void reverse(int *A, int n)     // reverse a sequence
+{
+       int x = 0;
+       n--;
+       while (x < n) {
+               SWAP(A[x], A[n]);
+               x++, n--;
+       }
+}
+
+static void rotate(int *A, int p, int q) // rotate a sequence
+{
+       reverse(A, p);
+       reverse(A+p, q);
+       reverse(A, p+q);
+}
+
+static void merge(int *A, int M, int N)
+{
+       int T = M+N;                    // total length of the buffer
+       int B = 1;                      // block size = ceil(sqrt(N))
+       while (B*B < T)
+               B++;
+
+       int Z = MIN(B+T%B,T);           // aux buffer size
+       int Mz=0, Nz=0;                 // find Z largest items
+       while (Mz+Nz < Z) {
+               if (Mz == M || A[M-Mz-1] > A[T-Nz-1])
+                       Mz++;
+               else
+                       Nz++;
+       }
+       M -= Mz;                        // fix up lengths
+       N -= Nz;
+       rotate(A, M, Mz);               // and move the items to the beginning
+       rotate(A, T-Nz, Nz);
+
+       // select-sort all blocks & track the mixed block
+       int mixed_block = M%B ? Z+M-M%B : -1;
+       for (int i=Z; i<T; i+=B) {
+               int best=i;
+               for (int j=i; j<T; j+=B)
+                       if (A[j+B-1] < A[best+B-1])
+                               best=j;
+               for (int j=0; j<B; j++)
+                       SWAP(A[i+j], A[best+j]);
+               if (mixed_block == i)
+                       mixed_block = best;
+               else if (mixed_block == best)
+                       mixed_block = i;
+       }
+
+       // convert the mixed block to two partial ones
+       int p1pos=-1, p1len=-1, p2pos=-1, p2len=-1;
+       if (mixed_block >= 0) {
+               p1len = M%B;
+               p2len = B-p1len;
+               p1pos = Z;
+               while (p1pos<T && A[p1pos+B-1] <= A[mixed_block+p1len-1])
+                       p1pos += B;
+               if (p1pos <= mixed_block) {
+                       rotate(A+p1pos, mixed_block-p1pos, p1len);
+                       p2pos = mixed_block+p1len;
+               } else {
+                       rotate(A+mixed_block, p1len, p1pos-mixed_block-p1len);
+                       p1pos -= p1len;
+                       p2pos = mixed_block;
+               }
+       }
+
+       // main merging pass
+       int dest = 0;
+       int s1 = Z;
+       int es1 = s1;
+       for(;;) {
+               while (es1 < T && (s1 == es1 || A[es1-1] <= A[es1]))
+                       es1 += BLEN(es1);
+               if (es1 >= T)
+                       break;
+               int s2 = es1;
+               int es2 = s2 + BLEN(s2);
+               while (s1 < es1) {
+                       if (A[s1] <= A[s2]) {
+                               SWAP(A[dest], A[s1]);
+                               s1++;
+                       } else {
+                               SWAP(A[dest], A[s2]);
+                               s2++;
+                       }
+                       dest++;
+               }
+               s1 = s2;
+               es1 = es2;
+       }
+       rotate(A+dest, Z, T-s1);
+
+       // sort the rest
+       for (int i=T-Z; i<T; i++) {
+               int best=i;
+               for (int j=i+1; j<T; j++)
+                       if (A[j] < A[best])
+                               best=j;
+               SWAP(A[i], A[best]);
+       }
+}
+
+#include <stdio.h>
+#include <time.h>
+#include <stdlib.h>
+
+int main(void)
+{
+#if 0
+       int A[] = { 2, 4, 8, 9, 10, 11, 13, 14, 16, 1, 5, 6, 11, 12, 15, 17, 18 };
+       int i;
+       merge(A, 9, 8);
+       for (i=0; i<sizeof(A)/sizeof(A[0]); i++) printf("%d ", A[i]);
+       putchar('\n');
+#else
+       srand(time(NULL));
+       int M = 1+random()%1000;
+       int N = 1+random()%1000;
+       int A[M+N];
+       for (int i=0; i<M; i++) A[i] = (i?A[i-1]:0) + random()%100;
+       for (int i=0; i<N; i++) A[M+i] = (i?A[M+i-1]:0) + random()%100;
+       merge(A, M, N);
+       for (int i=1; i<M+N; i++)
+               if (A[i] < A[i-1]) { puts("BUG"); return 1; }
+       puts("OK");
+#endif
+       return 0;
+}
diff --git a/netrq.c b/netrq.c
new file mode 100644 (file)
index 0000000..c8b4316
--- /dev/null
+++ b/netrq.c
@@ -0,0 +1,67 @@
+/*
+ *     Send Network SysRq Packet
+ *
+ *     (c) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <unistd.h>
+
+struct sysrq_pkt {
+       __u8 password[16];
+       __u8 command;
+};
+
+int main(int argc, char **argv)
+{
+       char *p;
+       struct sysrq_pkt sp;
+       struct hostent *h;
+       int s;
+       struct sockaddr_in sa;
+
+       bzero(&sp, sizeof(sp));
+
+       if (argc != 3 && argc != 4) {
+               fprintf(stderr, "Usage: netrq <machine> <cmd> [<passwd>]\n");
+               return 1;
+       }
+
+       if (! (h = gethostbyname(argv[1]))) {
+               fprintf(stderr, "Unable to resolve machine name: %m\n");
+               return 1;
+       }
+       if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
+               fprintf(stderr, "socket: %m\n");
+               return 1;
+       }
+       sa.sin_family = AF_INET;
+       memcpy(&sa.sin_addr.s_addr, h->h_addr, sizeof(struct in_addr));
+       sa.sin_port = htons(555);
+       if (connect(s, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
+               fprintf(stderr, "connect: %m\n");
+               return 1;
+       }
+
+       if (argc > 3)
+               p = argv[3];
+       else
+               p = getpass("Enter password: ");
+       if (strlen(p) > 15) {
+               fprintf(stderr, "Password is too long!\n");
+               return 1;
+       }
+       strcpy(sp.password, p);
+       sp.command = argv[2][0];
+
+       if (write(s, &sp, sizeof(sp)) != sizeof(sp)) {
+               fprintf(stderr, "write: %m\n");
+               return 1;
+       }
+
+       return 0;
+}
diff --git a/oggtest.c b/oggtest.c
new file mode 100644 (file)
index 0000000..98e3b23
--- /dev/null
+++ b/oggtest.c
@@ -0,0 +1,45 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <ogg/ogg.h>
+
+int main(void)
+{
+  ogg_sync_state osy;
+
+  ogg_sync_init(&osy);
+  for (;;)
+    {
+      char *buf = ogg_sync_buffer(&osy, 4096);
+      int len = read(0, buf, 4096);
+      if (len < 0)
+       {
+         fprintf(stderr, "read error: %m\n");
+         return 1;
+       }
+      if (!len)
+       break;
+      ogg_sync_wrote(&osy, len);
+
+      int ok;
+      ogg_page opg;
+      while (ok = ogg_sync_pageout(&osy, &opg))
+       {
+         if (ok < 0)
+           fprintf(stderr, "Skipping...\n");
+         else
+           {
+             fprintf(stderr, "Page (v=%d, stream=%x, bos=%d, eos=%d, pos=%Ld, pgno=%d)\n",
+                     ogg_page_version(&opg),
+                     ogg_page_serialno(&opg),
+                     ogg_page_bos(&opg),
+                     ogg_page_eos(&opg),
+                     (unsigned long long) ogg_page_granulepos(&opg),
+                     (unsigned int) ogg_page_pageno(&opg));
+           }
+       }
+    }
+  fprintf(stderr, "Done.\n");
+
+  return 0;
+}
diff --git a/parens.c b/parens.c
new file mode 100644 (file)
index 0000000..022e27e
--- /dev/null
+++ b/parens.c
@@ -0,0 +1,65 @@
+#include <stdio.h>
+
+int isprime(int i)
+{
+       int j=2;
+       while (j*j <= i) {
+               if (!(i%j)) return 0;
+               j++;
+       }
+       return 1;
+}
+
+int nextprime(int i)
+{
+       while (!isprime(++i))
+               ;
+       return i;
+}
+
+void enc(int i)
+{
+       if (!i) putchar('.');
+       else {
+               putchar('(');
+               int j=1;
+               while (i > 1) {
+                       j = nextprime(j);
+                       int k=0;
+                       while (!(i%j))
+                               i/=j, k++;
+                       enc(k);
+               }
+               putchar(')');
+       }
+}
+
+int dec(void)
+{
+       int j=1, k=1;
+       int c=getchar();
+       if (c == '.') return 0;
+       if (c != '(') exit(1);
+       while ((c = getchar()) != ')') {
+               ungetc(c, stdin);
+               j = nextprime(j);
+               int l = dec();
+               while (l--)
+                       k *= j;
+       }
+       return k;
+}
+
+int main(int argc, char **argv)
+{
+       if (argc > 1 && !strcmp(argv[1], "-e")) {
+               int i;
+               scanf("%d", &i);
+               enc(i);
+               putchar('\n');
+       } else {
+               int i = dec();
+               printf("%d\n", i);
+       }
+       return 0;
+}
diff --git a/parrot.c b/parrot.c
new file mode 100644 (file)
index 0000000..f105c1c
--- /dev/null
+++ b/parrot.c
@@ -0,0 +1,270 @@
+/*
+ *     Parrot Picking Fortune Cookies aka Simple Text Associator
+ *
+ *     (c) 2001 Martin Mares <mj@ucw.cz>
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define TEXTLEN 1024
+#define WORDLEN 64
+#define HASHSIZE 32768
+#define MAXFUZZ 3
+#define SKIP_PTS -10
+#define MATCH_PTS_LOW 20
+#define MATCH_PTS_HIGH 1000
+
+struct wd {
+  struct wd *next;
+  int cnt;
+  int ref;
+  char w[1];
+};
+static struct wd *hash[HASHSIZE];
+static int wcnt;
+
+static int n;
+static struct wd *input[TEXTLEN];
+static int next[TEXTLEN];
+
+static struct wd *
+findword(char *x)
+{
+  struct wd *w;
+  unsigned h=0;
+  char *y;
+
+  for (y=x; *y; y++)
+    h = h*13 + *y;
+  h %= HASHSIZE;
+  for (w=hash[h]; w; w=w->next)
+    if (!strcmp(w->w, x))
+      return w;
+  w = malloc(sizeof(struct wd) + strlen(x));
+  w->next = hash[h];
+  hash[h] = w;
+  w->cnt = 0;
+  w->ref = -1;
+  strcpy(w->w, x);
+  wcnt++;
+  return w;
+}
+
+static int
+getword(FILE *f, char *buf)
+{
+  int c, l;
+
+  do
+    {
+      c = fgetc(f);
+      if (c == '\n' &&
+         (c = fgetc(f)) == '%' &&
+         (c = fgetc(f)) == '\n')
+       {
+         *buf = 0;
+         return -1;
+       }
+    }
+  while (c != EOF && !isalnum(c));
+  if (c == EOF)
+    return 0;
+  l = WORDLEN-1;
+  do
+    {
+      *buf++ = tolower(c);
+      c = fgetc(f);
+    }
+  while (c != EOF && isalnum(c) && --l);
+  if (c != EOF)
+    ungetc(c, f);
+  *buf = 0;
+  return 1;
+}
+
+static void
+voc_build(FILE *f)
+{
+  char buf[WORDLEN];
+
+  while (getword(f, buf))
+    if (buf[0])
+      {
+       struct wd *w = findword(buf);
+       w->cnt++;
+      }
+  printf("Found %d words.\n", wcnt);
+}
+
+static void
+scan_in(FILE *f)
+{
+  char buf[WORDLEN];
+
+  while (getword(f, buf))
+    if (buf[0])
+      {
+       struct wd *w = findword(buf);
+       input[n] = w;
+       if (w->ref < 0)
+         w->ref = n;
+       else
+         {
+           int i = w->ref;
+           while (next[i] >= 0)
+             i = next[i];
+           next[i] = n;
+         }
+       next[n] = -1;
+       n++;
+       if (n >= TEXTLEN)
+         {
+           fprintf(stderr, "Input too long!\n");
+           exit(1);
+         }
+      }
+  printf("Scanned input of %d words.\n", n);
+}
+
+static void
+associate(FILE *f)
+{
+  off_t start = 0, best_start = 0;
+  char buf[WORDLEN];
+  int cost[TEXTLEN];
+  int pos[TEXTLEN];
+  int pts, xpos, p, pp, i, j;
+  int best_pts = 0;
+
+ newfort:
+  if (start)
+    {
+      pp = 0;
+      for (i=0; i<n; i++)
+       if (cost[i] > pp)
+         pp = cost[i];
+      // printf("%d pts\n", pp);
+      if (pp > best_pts)
+       {
+         best_pts = pp;
+         best_start = start;
+       }
+    }
+  start = ftell(f);
+  bzero(cost, n*sizeof(int));
+  memset(pos, -1, n*sizeof(int));
+  pts = 0;
+  xpos = 0;
+
+  while (getword(f, buf))
+    if (!buf[0])
+      goto newfort;
+    else
+      {
+       struct wd *w = findword(buf);
+       for (i=w->ref; i >= 0; i=next[i])
+         {
+           j = i - MAXFUZZ;
+           if (j < 0)
+             j = 0;
+           pp = cost[i];
+           if (pp < w->cnt)
+             pp = w->cnt;
+           while (j < i)
+             {
+               if (pos[j] >= 0)
+                 {
+                   p = xpos - pos[j];
+                   if (p < i-j)
+                     p = i-j;
+                   p = SKIP_PTS*p + cost[j] + w->cnt;
+                   if (p > pp)
+                     pp = p;
+                 }
+               j++;
+             }
+           if (pp > cost[i])
+             {
+               cost[i] = pp;
+               pos[i] = xpos;
+             }
+         }
+       xpos++;
+      }
+
+  printf("Best: %d points at %d\n", best_pts, best_start);
+  puts("---");
+  fseek(f, best_start, SEEK_SET);
+  while (getword(f, buf) > 0)
+    {
+      struct wd *w = findword(buf);
+      if (w->ref >= 0)
+       printf("<%s> ", buf);
+      else
+       printf("%s ", buf);
+    }
+  puts("\n---");
+  i = ftell(f) - best_start;
+  fseek(f, best_start, SEEK_SET);
+  while (i--)
+    putchar(fgetc(f));
+}
+
+static int
+cmp(const void *a, const void *b)
+{
+  struct wd *x = *(struct wd **)a;
+  struct wd *y = *(struct wd **)b;
+  return (x->cnt < y->cnt) - (x->cnt > y->cnt);
+}
+
+static void
+voc_val(void)
+{
+  int i, j;
+  struct wd *w, *wa[wcnt];
+
+  j = 0;
+  for (i=0; i<HASHSIZE; i++)
+    for (w=hash[i]; w; w=w->next)
+      wa[j++] = w;
+  qsort(wa, wcnt, sizeof(struct wd *), cmp);
+#if 0
+  for (i=0; i<wcnt; i++)
+    {
+      w = wa[i];
+      printf("%5d %s\n", w->cnt, w->w);
+    }
+#endif
+  for (i=0; i<wcnt/600; i++)
+    wa[i]->cnt = MATCH_PTS_LOW;
+  for (; i<wcnt; i++)
+    wa[i]->cnt = MATCH_PTS_HIGH;
+}
+
+int
+main(int argc, char **argv)
+{
+  FILE *fort;
+
+  if (argc != 2)
+    {
+      fprintf(stderr, "Usage: parrot <fortune-file>\n");
+      return 1;
+    }
+  fort = fopen(argv[1], "r");
+  if (!fort)
+    {
+      fprintf(stderr, "%s: %m\n", argv[1]);
+      return 1;
+    }
+
+  voc_build(fort);
+  voc_val();
+  scan_in(stdin);
+  rewind(fort);
+  associate(fort);
+}
diff --git a/phone.c b/phone.c
new file mode 100644 (file)
index 0000000..20f4cca
--- /dev/null
+++ b/phone.c
@@ -0,0 +1,169 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+FILE *f;
+
+#define HASH_SIZE 16384
+
+typedef unsigned char byte;
+
+struct word {
+  struct word *next;
+  int len;
+  byte w[1];
+};
+
+struct word *htab[HASH_SIZE];
+
+byte c2n[256];
+/*                  0      1     2      3      4     5     6     7      8      9   */
+byte *n2c[10] = { "OQZ", "IJ", "ABC", "DEF", "GH", "KL", "MN", "PRS", "TUV", "WXY" };
+
+void init(void)
+{
+  int i;
+  byte *c;
+
+  for(i=0; i<10; i++)
+    {
+      for(c=n2c[i]; *c; c++)
+       {
+         c2n[*c] = '0'+i;
+         c2n[tolower(*c)] = '0'+i;
+       }
+      c2n['0'+i] = '0'+i;
+    }
+}
+
+unsigned int hash(byte *x, int len)
+{
+  int h = len;
+
+  while (*x && len--)
+    h = h * 13337 + c2n[*x++];
+  return h & (HASH_SIZE - 1);
+}
+
+void read_it(void)
+{
+  byte l[256];
+  int h, s, c=0;
+  struct word *w;
+
+  while (fgets(l, sizeof(l)-1, f))
+    {
+      byte *z = strchr(l, '\n');
+      if (z)
+       *z = 0;
+      s = strlen(l);
+      h = hash(l, s);
+      w = malloc(sizeof(struct word) + s);
+      if (!w)
+       {
+         perror("malloc");
+         exit(1);
+       }
+      w->next = htab[h];
+      htab[h] = w;
+      w->len = s;
+      strcpy(w->w, l);
+      c++;
+    }
+  printf("Scanned %d words.\n", c);
+}
+
+struct word *find(byte *x, int l)
+{
+  int h = hash(x, l);
+  struct word *w = htab[h];
+  byte *p, *q;
+  while (w)
+    {
+      if (w->len == l)
+       {
+         int ll = l;
+         p = x;
+         q = w->w;
+         while (ll && *p++ == c2n[*q++])
+           ll--;
+         if (!ll)
+           return w;
+       }
+      w = w->next;
+    }
+  return NULL;
+}
+
+#define MAXL 128
+
+struct word *last[MAXL];
+int best[MAXL];
+
+void print(int z)
+{
+  struct word *w;
+
+  if (!z)
+    return;
+  w = last[z];
+  if (!w)
+    {
+      printf("!!!BUG!!!");
+      return;
+    }
+  print(z - w->len);
+  printf("%s ", w->w);
+}
+
+void sentence(byte *z)
+{
+  int l = strlen(z);
+  int i, j;
+  struct word *w;
+
+  if (l >= MAXL-1)
+    {
+      printf("TOO LONG.\n");
+      return;
+    }
+  best[0] = 0;
+  for(i=1; i<=l; i++)
+    {
+      last[i] = NULL;
+      best[i] = -1;
+      for(j=0; j<i; j++)
+       if (best[j] >= 0 && (w = find(z+j, i-j)) && (best[i] < 0 || best[i] > best[j] + 1))
+         {
+           last[i] = w;
+           best[i] = best[j] + 1;
+         }
+    }
+  if (best[l] <= 0)
+    printf("NO SOLUTION.");
+  else
+    print(l);
+  putchar('\n');
+}
+
+int main(int argc, char **argv)
+{
+  byte l[256];
+  byte *k;
+
+  if (!(f = fopen("voc", "r")))
+    {
+      perror("Unable to open vocabulary");
+      return 1;
+    }
+  init();
+  read_it();
+
+  while (fgets(l, sizeof(l), stdin) && (k = strchr(l, '\n')))
+    {
+      *k = 0;
+      sentence(l);
+    }
+  return 0;
+}
diff --git a/prime.c b/prime.c
new file mode 100644 (file)
index 0000000..c363ad3
--- /dev/null
+++ b/prime.c
@@ -0,0 +1,46 @@
+/*
+Generate Prime Number
+*/
+
+int isprime(unsigned x)
+{
+unsigned z,y;
+       z = x%6U;
+       if (z!=1 && z!=5) return 0;
+       z = 5;
+       for (;;)
+               {
+               y = x / z;
+               if (y < z || z == x) return 1;
+               if (!(x % z)) return 0;
+               z += 2;
+               }
+}
+
+void calcprim(unsigned c)
+{
+       while (c >= 2)
+               {
+               if (isprime(c))
+                       {
+                       printf("Found prime number %u.\n",c);
+                       exit(0);
+                       }
+               c--;
+               }
+       printf("Prime number not found!\n");
+       exit(1);
+}
+
+void main(int argc,char **argv)
+{
+int c;
+char *k;
+       if (argc != 2)
+               {
+               printf("Usage: prime <number>\n");
+               exit(1);
+               }
+       c = strtoul(argv[1], &k, 0);
+       calcprim(c);
+}
diff --git a/proof.c b/proof.c
new file mode 100644 (file)
index 0000000..ca3601c
--- /dev/null
+++ b/proof.c
@@ -0,0 +1,217 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+typedef struct formula fmla;
+
+struct formula {
+       fmla *next;
+       int op;
+       int key;
+       fmla *arg[2];
+};
+
+#define OP_X 0
+#define OP_Y 1
+#define OP_NOT 2
+#define OP_IMP 3
+
+static void putf(fmla *a)
+{
+       switch (a->op)
+       {
+       case OP_X:
+               putchar('X');
+               break;
+       case OP_Y:
+               putchar('Y');
+               break;
+       case OP_NOT:
+               putchar('^');
+               putf(a->arg[0]);
+               break;
+       default:
+               putchar('(');
+               putf(a->arg[0]);
+               putchar('>');
+               putf(a->arg[1]);
+               putchar(')');
+       }
+}
+
+static void duf(fmla *f)
+{
+       putf(f);
+       putchar('\n');
+}
+
+static inline fmla *newf(int op, fmla *l, fmla *r)
+{
+       fmla *f = malloc(sizeof(fmla));
+       f->op = op;
+       f->arg[0] = l;
+       f->arg[1] = r;
+       f->next = NULL;
+       switch (op) {
+       case OP_IMP:
+               f->key = 313*l->key + 17*r->key + 2;
+               break;
+       case OP_NOT:
+               f->key = 1733*l->key + 5;
+               break;
+       default:
+               f->key = op + 1;
+       }
+       return f;
+}
+
+static inline int match(fmla *a, fmla *b)
+{
+       int i;
+
+       if (a->op != b->op || a->key != b->key)
+               return 0;
+       switch (a->op)
+       {
+       case OP_IMP:
+               if (!match(a->arg[1], b->arg[1]))
+                       return 0;
+       case OP_NOT:
+               if (!match(a->arg[0], b->arg[0]))
+                       return 0;
+       }
+       return 1;
+}
+
+#define G_DEPTH 3
+
+fmla *head_depth[G_DEPTH+1];
+
+void gen(void)
+{
+       int i, j, k;
+       fmla *x, *y, *z, **h;
+
+       puts("Generator...");
+       duf(head_depth[1] = newf(OP_X, NULL, NULL));
+       duf(head_depth[1]->next = newf(OP_Y, NULL, NULL));
+       for(i=2; i<=G_DEPTH; i++) {
+               printf("### depth %d\n", i);
+               h = head_depth + i;
+               x = head_depth[i-1];
+               while (x) {
+                       z = newf(OP_NOT, x, NULL);
+                       duf(z);
+                       z->next = *h;
+                       *h = z;
+                       x = x->next;
+               }
+               for(j=1; j<i; j++) {
+                       x = head_depth[j];
+                       while (x) {
+                               y = head_depth[i-j];
+                               while (y) {
+                                       z = newf(OP_IMP, x, y);
+                                       duf(z);
+                                       z->next = *h;
+                                       *h = z;
+                                       y = y->next;
+                               }
+                               x = x->next;
+                       }
+               }
+       }
+}
+
+fmla *flist;
+
+#define A_DEPTH 20
+
+void axi(void)
+{
+       int i,j,k;
+       fmla *x, *y, *z, *w;
+
+       puts("Axiom #1...");
+       /* A->(B->A) */
+       for(i=1; i<=G_DEPTH; i++)
+               for(j=1; j<=G_DEPTH; j++)
+                       if (2*i+j+2 <= A_DEPTH)
+                               for(x = head_depth[i]; x; x=x->next)
+                                       for(y = head_depth[j]; y; y=y->next) {
+                                               z = newf(OP_IMP, x, newf(OP_IMP, y, x));
+                                               duf(z);
+                                               z->next = flist;
+                                               flist = z;
+                                       }
+
+       puts("Axiom #2...");
+       /* (A->(B->C)) -> ((A->B) -> (A->C)) */
+       for(i=1; i<=G_DEPTH; i++)
+               for(j=1; j<=G_DEPTH; j++)
+                       for(k=1; k<=G_DEPTH; k++)
+                               if (3*i+2*j+2*k+6 <= A_DEPTH)
+                                       for(x=head_depth[i]; x; x=x->next)
+                                               for(y=head_depth[j]; y; y=y->next)
+                                                       for(z=head_depth[k]; z; z=z->next) {
+                                                               w = newf(OP_IMP,
+                                                                       newf(OP_IMP, x, newf(OP_IMP, y, z)),
+                                                                       newf(OP_IMP,
+                                                                               newf(OP_IMP, x, y),
+                                                                               newf(OP_IMP, x, z)));
+                                                               duf(w);
+                                                               w->next = flist;
+                                                               flist = w;
+                                                       }
+
+       puts("Axiom #3...");
+       /* (^A->^B)->(B->A) */
+       for(i=1; i<=G_DEPTH; i++)
+               for(j=1; j<=G_DEPTH; j++)
+                       if (2*i+2*j+5 <= A_DEPTH)
+                               for(x = head_depth[i]; x; x=x->next)
+                                       for(y = head_depth[j]; y; y=y->next) {
+                                               z = newf(OP_IMP,
+                                                       newf(OP_IMP, newf(OP_NOT, x, NULL), newf(OP_NOT, y, NULL)),
+                                                       newf(OP_IMP, y, x));
+                                               duf(z);
+                                               z->next = flist;
+                                               flist = z;
+                                       }
+}
+
+void derive(void)
+{
+       fmla *x, *y, *last, *z;
+       int flag;
+
+       puts("Derived:");
+       for(last=flist; last->next; last=last->next)
+               ;
+       do {
+               puts("PASS");
+               flag = 0;
+               /* Modus Ponens: A, A->B =] B */
+               for(x=flist; x; x=x->next)
+                       for(y=flist; y; y=y->next) {
+                               if (x->op == OP_IMP &&
+                                   match(x->arg[0], y)) {
+                                       z = x->arg[1];
+                                       if (!z->next && z != last) {
+                                               duf(z);
+                                               last->next = z;
+                                               last = z;
+                                               flag = 1;
+                                       }
+                               }
+                       }
+       } while (flag);
+}
+
+int main(void)
+{
+       gen();
+       axi();
+       derive();
+       return 0;
+}
diff --git a/puzzle.c b/puzzle.c
new file mode 100644 (file)
index 0000000..10b059c
--- /dev/null
+++ b/puzzle.c
@@ -0,0 +1,166 @@
+#include <stdio.h>
+
+struct {
+  int id;
+  char x[4];
+} list[] = {
+  {  0, {0,0,0,0} },
+  { 11, {0,0,0,1} },
+  { 13, {0,0,0,2} },
+  { 11, {0,0,1,0} },
+  {  3, {0,0,1,1} },
+  { 15, {0,0,1,2} },
+  { 13, {0,0,2,0} },
+  { 16, {0,0,2,1} },
+  {  4, {0,0,2,2} },
+  { 11, {0,1,0,0} },
+  {  6, {0,1,0,1} },
+  { 21, {0,1,0,2} },
+  {  3, {0,1,1,0} },
+  {  9, {0,1,1,1} },
+  { 18, {0,1,1,2} },
+  { 15, {0,1,2,0} },
+  { 22, {0,1,2,1} },
+  { 19, {0,1,2,2} },
+  { 13, {0,2,0,0} },
+  { 21, {0,2,0,1} },
+  {  7, {0,2,0,2} },
+  { 16, {0,2,1,0} },
+  { 17, {0,2,1,1} },
+  { 23, {0,2,1,2} },
+  {  4, {0,2,2,0} },
+  { 20, {0,2,2,1} },
+  { 10, {0,2,2,2} },
+  { 11, {1,0,0,0} },
+  {  3, {1,0,0,1} },
+  { 16, {1,0,0,2} },
+  {  6, {1,0,1,0} },
+  {  9, {1,0,1,1} },
+  { 22, {1,0,1,2} },
+  { 21, {1,0,2,0} },
+  { 17, {1,0,2,1} },
+  { 20, {1,0,2,2} },
+  {  3, {1,1,0,0} },
+  {  9, {1,1,0,1} },
+  { 17, {1,1,0,2} },
+  {  9, {1,1,1,0} },
+  {  1, {1,1,1,1} },
+  { 14, {1,1,1,2} },
+  { 18, {1,1,2,0} },
+  { 14, {1,1,2,1} },
+  {  5, {1,1,2,2} },
+  { 15, {1,2,0,0} },
+  { 18, {1,2,0,1} },
+  { 23, {1,2,0,2} },
+  { 22, {1,2,1,0} },
+  { 14, {1,2,1,1} },
+  {  8, {1,2,1,2} },
+  { 19, {1,2,2,0} },
+  {  5, {1,2,2,1} },
+  { 12, {1,2,2,2} },
+  { 13, {2,0,0,0} },
+  { 15, {2,0,0,1} },
+  {  4, {2,0,0,2} },
+  { 21, {2,0,1,0} },
+  { 18, {2,0,1,1} },
+  { 19, {2,0,1,2} },
+  {  7, {2,0,2,0} },
+  { 23, {2,0,2,1} },
+  { 10, {2,0,2,2} },
+  { 16, {2,1,0,0} },
+  { 22, {2,1,0,1} },
+  { 20, {2,1,0,2} },
+  { 17, {2,1,1,0} },
+  { 14, {2,1,1,1} },
+  {  5, {2,1,1,2} },
+  { 23, {2,1,2,0} },
+  {  8, {2,1,2,1} },
+  { 12, {2,1,2,2} },
+  {  4, {2,2,0,0} },
+  { 19, {2,2,0,1} },
+  { 10, {2,2,0,2} },
+  { 20, {2,2,1,0} },
+  {  5, {2,2,1,1} },
+  { 12, {2,2,1,2} },
+  { 10, {2,2,2,0} },
+  { 12, {2,2,2,1} },
+  {  2, {2,2,2,2} }
+};
+
+int rect[8][8], hbound[8][8], vbound[8][8];
+
+static void
+dump(void)
+{
+  int x,y;
+
+  for (x=1; x<=6; x++)
+    {
+      for (y=1; y<=4; y++)
+       printf(".%d. ", list[rect[x][y]].x[1]);
+      putchar('\n');
+      for (y=1; y<=4; y++)
+       printf("%d.%d ", list[rect[x][y]].x[0], list[rect[x][y]].x[2]);
+      putchar('\n');
+      for (y=1; y<=4; y++)
+       printf(".%d. ", list[rect[x][y]].x[3]);
+      putchar('\n');
+      putchar('\n');
+    }
+}
+
+static void
+fill(int x, int y, unsigned int mask)
+{
+  int i,j;
+
+  i = 9*(3*hbound[x][y]+vbound[x][y]);
+  for (j=0; j<9; i++, j++)
+    if (!(mask & (1 << list[i].id)))
+      {
+       //      printf("place <%d,%d> %d\n", x, y, list[i].id);
+       rect[x][y] = i;
+       //      if (hbound[x][y] != list[i].x[0] ||
+       //          vbound[x][y] != list[i].x[1]) puts("BUG!!!");
+       hbound[x][y+1] = list[i].x[2];
+       vbound[x+1][y] = list[i].x[3];
+       if (x == 6)
+         {
+           if (vbound[x+1][y])
+             continue;
+           if (y == 4)
+             {
+               if (hbound[x][y+1] != 2)
+                 continue;
+               else
+                 {
+                   puts("Gotcha!!!");
+                   dump();
+                   fflush(stdout);
+                   //    exit(0);
+                   return;
+                 }
+             }
+           fill(x,y+1,mask | (1 << list[i].id));
+         }
+       else if (y == 4)
+         {
+           if (hbound[x][y+1])
+             continue;
+           fill(x+1,1,mask | (1 << list[i].id));
+         }
+       else
+         fill(x,y+1,mask | (1 << list[i].id));
+      }
+}
+
+int
+main(int argc, char **argv)
+{
+  int x;
+  for (x=1; x<=4; x++)
+    vbound[1][x] = 1;
+  fill(1,1,0);
+  puts("No chance");
+  return 0;
+}
diff --git a/randomize.c b/randomize.c
new file mode 100644 (file)
index 0000000..adc4992
--- /dev/null
@@ -0,0 +1,72 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/time.h>
+
+struct line {
+  struct line *next;
+  char x[1];
+};
+
+unsigned int
+r(unsigned int max)
+{
+  unsigned int r, l;
+
+  l = (RAND_MAX + 1U) - ((RAND_MAX + 1U) % max);
+  do
+    r = random();
+  while (r >= l);
+  return r % max;
+}
+
+int
+main(int argc, char **argv)
+{
+  char buf[4096];
+  struct line *f = NULL, *n, **b, **w;
+  int cnt = 0, i, j, k;
+
+  while (fgets(buf, sizeof(buf)-1, stdin))
+    {
+      if (!strchr(buf, '\n'))
+       {
+         fprintf(stderr, "Line too long\n");
+         return 1;
+       }
+      n = malloc(sizeof(struct line) + strlen(buf));
+      if (!n)
+       {
+         fprintf(stderr, "Out of memory\n");
+         return 1;
+       }
+      n->next = f;
+      f = n;
+      strcpy(n->x, buf);
+      cnt++;
+    }
+  if (!cnt)
+    return 0;
+  w = b = malloc(sizeof(struct line *) * cnt);
+  if (!b)
+    {
+      fprintf(stderr, "Out of memory\n");
+      return 1;
+    }
+  while (f)
+    {
+      *b++ = f;
+      f = f->next;
+    }
+  srandom(time(NULL));
+  for(i=0; i<cnt; i++)
+    {
+      j = r(cnt);
+      k = r(cnt);
+      n = w[j];
+      w[j] = w[k];
+      w[k] = n;
+    }
+  for(i=0; i<cnt; i++)
+    fputs(w[i]->x, stdout);
+  return 0;
+}
diff --git a/seek.c b/seek.c
new file mode 100644 (file)
index 0000000..274d475
--- /dev/null
+++ b/seek.c
@@ -0,0 +1,24 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <unistd.h>
+
+int main(int argc, char **argv)
+{
+       unsigned long off;
+       char *ep;
+       if (argc != 2) {
+               fprintf(stderr, "Usage: seek <offset>\n");
+               return 1;
+       }
+       off = strtoul(argv[1], &ep, 0);
+       if (!argv[1][0] || *ep || off == ULONG_MAX) {
+               fprintf(stderr, "seek: Invalid offset\n");
+               return 1;
+       }
+       if (lseek(0, off, SEEK_SET) == (off_t)-1) {
+               fprintf(stderr, "seek: %m\n");
+               return 1;
+       }
+       return 0;
+}
diff --git a/sig.c b/sig.c
new file mode 100644 (file)
index 0000000..63dbdbe
--- /dev/null
+++ b/sig.c
@@ -0,0 +1,45 @@
+#include <stdio.h>
+#include <pwd.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <time.h>
+
+int main(int argc, char **argv)
+{
+       struct passwd *p;
+       int n, len, f;
+       char buf[256], *z, *i;
+
+       p = getpwuid(getuid());
+       if (!p) { puts("You don't exist and thus you don't have a signature!"); return 1; }
+       chdir(p->pw_dir);
+       f = open((argc > 1) ? argv[1] : ".sigbase", O_RDONLY);
+       if (f < 0) { puts("No file, no signature!"); return 1; }
+       while ((n = read(f, buf, sizeof(buf))) > 0) write(1, buf, n);
+       close(f);
+       f = open(".misfortune", O_RDONLY);
+       if (!f || (len = lseek(f, 0, SEEK_END)) <= 0) {
+               puts("No fortune, no luck, no sig!");
+               return 1;
+       }
+       lseek(f, 0, SEEK_SET);
+       z = malloc(len+1);
+       if (!z) { puts("ENOMEM"); return 1; }
+       read(f, z, len);
+       z[len] = 0;
+       n = 0;
+       for(i=z; i<z+len; i++)
+               if (*i == '\n')
+                       n++;
+       if (!n) { puts("Oh no! More lemmings!"); return 1; }
+       srandom(time(NULL));
+       n = random() % n;
+       while (n--) {
+               while (*z && *z != '\n') z++;
+               if (*z) z++;
+       }
+       while (*z && *z != '\n') putchar(*z++);
+       putchar('\n');
+       return 0;
+}
diff --git a/tla b/tla
new file mode 100755 (executable)
index 0000000..c43aa83
--- /dev/null
+++ b/tla
@@ -0,0 +1,11 @@
+#! /bin/sh
+while true ; do
+echo -n "Enter TLA: "
+read xxx
+if grep $xxx tla.db >/dev/null ; then
+   echo Already present.
+else
+   echo Not present
+       echo $xxx >>tla.db
+fi
+done
diff --git a/tla.db b/tla.db
new file mode 100644 (file)
index 0000000..0450d3b
--- /dev/null
+++ b/tla.db
@@ -0,0 +1,481 @@
+abs
+acc
+ack
+acs
+adc
+add
+ads
+afd
+afm
+ale
+alf
+alt
+alu
+amd
+ami
+arj
+arp
+arq
+ash
+asn
+atn
+avg
+awk
+bak
+bbs
+bcc
+bcd
+bcs
+beq
+bge
+bgt
+bhi
+bin
+bit
+ble
+bls
+blt
+bmi
+bmp
+bne
+bpe
+bpl
+brk
+bvc
+bvs
+cad
+cam
+cas
+cat
+cbm
+cbw
+ccd
+cck
+ccp
+ccr
+ced
+cga
+chk
+clc
+cli
+clk
+cmc
+cmd
+cmi
+cmp
+cmr
+cms
+cmu
+cmy
+cnt
+col
+com
+cos
+cpl
+cpr
+crt
+csh
+ctc
+cti
+cts
+cur
+cwd
+dac
+dat
+dbf
+dbm
+dca
+dcb
+dcd
+ddt
+dec
+deg
+del
+des
+dfc
+dft
+dil
+dim
+dip
+dir
+div
+dll
+dma
+dos
+dra
+drv
+dsp
+dsr
+dtl
+dtr
+dvi
+ecc
+ecl
+ega
+emi
+emm
+ems
+ena
+enb
+env
+eps
+erc
+erl
+ern
+err
+esc
+exe
+exg
+exp
+ext
+faq
+fat
+fdc
+fdd
+fet
+ffp
+ffs
+fft
+fiz
+fli
+fmt
+fpr
+fpu
+ftp
+fyi
+gal
+gas
+gcc
+gcd
+gcr
+gdb
+gdt
+gid
+gif
+gnd
+gnu
+gpl
+gpr
+grp
+gsf
+gst
+gus
+hal
+ham
+hdc
+hdd
+hdr
+hex
+hgc
+hlp
+hma
+hsv
+hup
+ibm
+icc
+icr
+ier
+iff
+ifs
+iil
+imo
+imr
+inc
+inp
+ins
+int
+ipl
+ipx
+irc
+irq
+isa
+isp
+jcc
+jcs
+jeq
+jle
+jmi
+jmp
+jne
+jns
+jnz
+jpl
+kms
+ksh
+lan
+ldt
+led
+len
+ler
+lha
+lpq
+lpr
+lpt
+lru
+lsm
+lzh
+lzw
+mam
+man
+mcu
+mda
+mfj
+mfm
+mft
+mkd
+mkf
+mki
+mkl
+mml
+mmu
+mnp
+mnt
+mos
+mrm
+msd
+msw
+mul
+mux
+nak
+ncc
+ncd
+ncr
+ndd
+nfs
+nic
+nmi
+nop
+nsl
+ntp
+nul
+ocr
+oct
+ofs
+oop
+opl
+ovl
+ovr
+pal
+par
+pbm
+pci
+pcl
+pcx
+pfm
+pfs
+pga
+pgm
+pgp
+pha
+pkg
+pla
+pld
+pnm
+ppi
+ppm
+ppp
+psu
+pwd
+pxl
+qed
+qic
+qwk
+rad
+ram
+rar
+ras
+rbf
+rcl
+rcp
+rcr
+rcs
+ref
+rev
+rgb
+rip
+rkm
+rla
+rlc
+rld
+rle
+rll
+rmt
+rol
+rom
+ror
+rot
+rpc
+rra
+rrc
+rrd
+rsa
+rsh
+rsr
+rtd
+rte
+rtg
+rts
+rxd
+sad
+sbb
+sbc
+scc
+sdb
+sec
+sed
+sfc
+sid
+sin
+sla
+sli
+sls
+smd
+snd
+spc
+sql
+sqr
+sra
+srl
+ssp
+stb
+sti
+stk
+sto
+str
+sub
+swp
+sys
+tac
+tan
+tar
+tas
+tbe
+tcl
+tcp
+tee
+tfm
+tic
+tla
+tmp
+tpa
+tpc
+tph
+tpl
+tpu
+trk
+tsr
+tss
+ttl
+ttp
+tts
+tty
+txd
+ucc
+ucw
+udd
+udp
+uid
+ula
+umb
+upp
+ups
+url
+usp
+val
+vbr
+vfs
+vga
+vim
+vlb
+vma
+vms
+vpa
+wan
+wrt
+xbm
+xga
+xms
+xon
+yak
+zif
+png
+pbx
+atm
+ppc
+ggi
+ddr
+mtu
+mru
+cdr
+rpm
+bbn
+bpm
+brt
+lim
+dce
+dte
+dtp
+apm
+arm
+xor
+iso
+itu
+pcm
+pdf
+rtl
+fcc
+mbr
+bgp
+egp
+igp
+ssh
+mib
+rfu
+rpg
+rtt
+lcp
+icp
+ioi
+fel
+lea
+vtm
+zcu
+mff
+etc
+cet
+lst
+cvs
+cpp
+cls
+vip
+ccm
+cpm
+hga
+fwd
+fig
+rtf
+sak
+xdr
+sgp
+dct
+csc
+phd
+yam
+tgv
+tft
+lcd
+lpd
+ean
+elm
+ipc
+rms
+clr
+inn
+nis
+nan
+inf
+gem
+gfx
+igi
+gpm
+std
diff --git a/trains.c b/trains.c
new file mode 100644 (file)
index 0000000..3ae3dab
--- /dev/null
+++ b/trains.c
@@ -0,0 +1,96 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+struct tariff { int kmax, price; };
+
+struct tariff tar[] = {
+  { 10, 6 },
+  { 15, 8 },
+  { 20, 11 },
+  { 25, 13 },
+  { 30, 16 },
+  { 35, 19 },
+  { 40, 22 },
+  { 50, 27 },
+  { 60, 32 },
+  { 70, 38 },
+  { 80, 43 },
+  { 90, 48 },
+  { 100, 53 },
+  { 110, 58 },
+  { 120, 62 },
+  { 140, 72 },
+  { 160, 82 },
+  { 180, 92 },
+  { 200, 101 },
+  { 225, 114 },
+  { 250, 126 },
+  { 275, 138 },
+  { 300, 148 },
+  { 350, 170 },
+  { 400, 192 },
+  { 450, 214 },
+  { 500, 236 },
+  { 550, 258 },
+  { 600, 278 },
+  { 650, 298 },
+  { 700, 318 },
+  { 99999, 342 }
+};
+
+int ftar(int km)
+{
+  int t;
+  for(t=0; tar[t].kmax < km; t++)
+    ;
+  return t;
+}
+
+int lo(int t)
+{
+  return t ? tar[t-1].kmax+1 : 0;
+}
+
+#define hi(t) tar[t].kmax
+#define pri(t) tar[t].price
+
+int main(int argc, char **argv)
+{
+  int km, t, orp, l, h;
+
+  if (argc != 2)
+    {
+      fprintf(stderr, "Usage: %s <km>\n", argv[0]);
+      return 0;
+    }
+  km = atol(argv[1]);
+  if (km > 10000)
+    km = 10000;
+  t = ftar(km);
+  printf("Original: %d-%d %d\n", lo(t), hi(t), pri(t));
+  orp = pri(t);
+  while (--t >= 0)
+    {
+      int l0 = km - hi(t);
+      int h0 = km - lo(t);
+      l = ftar(l0);
+      h = ftar(h0);
+//    printf("Trying %d-%d %d-%d\n", lo(t), hi(t), l0, h0);
+      while (l <= h)
+       {
+         int p = pri(t) + pri(l);
+         int L = lo(l) < l0 ? l0 : lo(l);
+         int H = hi(l) > h0 ? h0 : hi(l);
+//       printf("Combined %d-%d %d-%d: p=%d\n", lo(l), hi(l), L, H, p);
+         if (p < orp)
+           printf("::: %d-%d(%d) + %d-%d(%d) = %d (saved %d)\n",
+                  L, H, pri(l),
+                  lo(t), hi(t), pri(t),
+                  p, orp - p);
+         l++;
+       }
+    }
+
+  return 0;
+}
diff --git a/ukkonen.c b/ukkonen.c
new file mode 100644 (file)
index 0000000..7e597cb
--- /dev/null
+++ b/ukkonen.c
@@ -0,0 +1,114 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define INFTY 1000000
+
+struct node {
+       struct node *first_son;
+       struct node *next_sibling;
+       struct node *backlink;          /* We use them only for internal nodes */
+       char *label;                    /* Label of edge above this node */
+       int lablen;
+};
+
+static void dump_tree(struct node *n, int level, char *strend)
+{
+       for (int i=0; i<level; i++)
+               putchar('.');
+       printf("<%.*s%s> [%p] {%p}\n",
+               (n->lablen >= INFTY/2 ? strend-n->label : n->lablen), n->label,
+               (n->lablen >= INFTY/2 ? "*" : ""), n, n->backlink);
+       for (n=n->first_son; n; n=n->next_sibling)
+               dump_tree(n, level+1, strend);
+}
+
+static struct node *new_node(void)
+{
+       struct node *n = malloc(sizeof(*n));
+       bzero(n, sizeof(*n));
+       return n;
+}
+
+static struct node *lookup_edge(struct node *x, int c)
+{
+       x = x->first_son;
+       while (x && x->label[0] != c)
+               x = x->next_sibling;
+       return x;
+}
+
+static struct node *build_tree(char *string)
+{
+       struct node *root = new_node();
+       struct node *l = root;          /* Currently longest nested suffix as a canonical reference pair (node, label) */
+       char *llabel = string;
+       int llablen = 0;
+       struct node *x, *y, *z, *trash, **blp;
+
+       for (int i=0; string[i]; i++) {
+               blp = &trash;
+               for(;;) {
+                       while (llablen) {                               /* Canonicalize the reference pair */
+                               x = lookup_edge(l, llabel[0]);
+                               if (x->lablen > llablen)
+                                       break;
+                               l = x;
+                               llabel += x->lablen;
+                               llablen -= x->lablen;
+                       }
+                       if (!llablen) {                                 /* LNS is an internal node or root */
+                               *blp = l;
+                               blp = &trash;
+                               if (lookup_edge(l, string[i])) {                /* Found LNS for the new string */
+                                       llabel = string+i;
+                                       llablen = 1;
+                                       break;
+                               }
+                               z = new_node();
+                               z->next_sibling = l->first_son;
+                               l->first_son = z;
+                       } else {                                        /* LNS is in the middle of an edge */
+                               x = lookup_edge(l, llabel[0]);
+                               if (x->label[llablen] == string[i]) {           /* found LNS for the new string */
+                                       llablen++;
+                                       break;
+                               }
+                               y = new_node();                         /* New interior node which gets all sons of x */
+                               z = new_node();                         /* New leaf connected below x */
+                               y->first_son = x->first_son;
+                               y->next_sibling = NULL;
+                               y->backlink = x->backlink;
+                               y->label = x->label + llablen;
+                               y->lablen = x->lablen - llablen;
+                               x->first_son = z;
+                               x->backlink = NULL;
+                               *blp = x;
+                               blp = &x->backlink;                     /* Backlink will be filled in later */
+                               x->lablen = llablen;
+                               z->next_sibling = y;
+                       }
+                       z->label = string+i;
+                       z->lablen = INFTY;
+
+                       if (l == root) {                                /* Cut the first character of the LNS */
+                               if (!llablen)
+                                       break;
+                               llabel++;
+                               llablen--;
+                       } else
+                               l = l->backlink;
+               }
+               *blp = root;
+       }
+       return root;
+}
+
+int main(int argc, char **argv)
+{
+       char *string = argv[1];
+       struct node *root = build_tree(string);
+       puts("Result:");
+       dump_tree(root, 0, string+strlen(string));
+       return 0;
+}
diff --git a/un602.c b/un602.c
new file mode 100644 (file)
index 0000000..34e01d4
--- /dev/null
+++ b/un602.c
@@ -0,0 +1,29 @@
+#include <stdio.h>
+
+int main(void)
+{
+       int i;
+       int bol = 1;
+
+       while ((i = getchar()) != EOF)
+               {
+                       if (i == 10)
+                               {
+                                       bol = 1;
+                                       putchar(10);
+                                       continue;
+                               }
+                       if (i < 32)
+                               continue;
+                       if (i == '@' && bol)
+                               {
+                                       while ((i = getchar()) != EOF && i != 10)
+                                               ;
+                                       continue;
+                               }
+                       bol = 0;
+                       putchar(i);
+               }
+       
+       return 0;
+}
diff --git a/unword.c b/unword.c
new file mode 100644 (file)
index 0000000..12b5ed1
--- /dev/null
+++ b/unword.c
@@ -0,0 +1,333 @@
+/*
+ *     Extract ASCII Text from M$ Word Document
+ *
+ *     (c) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ */
+
+/* FIXME: endianity dependencies! */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+FILE *fi, *fo;
+
+typedef unsigned char byte;
+typedef unsigned short word;
+typedef unsigned int ulg;
+
+byte
+gb(void)
+{
+  return fgetc(fi);
+}
+
+word
+gw(void)
+{
+  word k = fgetc(fi);
+  k = k | (fgetc(fi) << 8);
+  return k;
+}
+
+ulg
+gl(void)
+{
+  ulg l = gw();
+  l = l | (gw() << 16);
+  return l;
+}
+
+void
+ole(void)
+{
+  ulg p, word;
+  byte oh[0x80], pn[0x80];
+  int z, x, y;
+
+  fseek(fi, 0x30, SEEK_SET);
+  p = 0x200 * gl() + 0x200;                            /* Position of central directory */
+  word = 0;
+  printf("Central OLE directory at 0x%x\n", p);
+  fseek(fi, p, SEEK_SET);
+  while (fread(oh, sizeof(oh), 1, fi) == 1)
+       {
+         z = y = 0;
+         if ((!oh[0] && !oh[1]) || (!oh[2] && !oh[3]))
+               break;
+         if (oh[z] < 32 && !oh[z+1])
+               {
+                 z += 2;
+                 pn[y++] = '>';
+                 pn[y++] = ' ';
+               }
+         while (oh[z] || oh[z+1])
+               {
+                 x = oh[z] | (oh[z+1] << 8);
+                 if (x >= 32 && x < 127)
+                       pn[y++] = x;
+                 else
+                       pn[y++] = '?';
+                 z += 2;
+               }
+         pn[y] = 0;
+         p = 0x200 * (oh[0x74] | (oh[0x75] << 8) | (oh[0x76] << 16) | (oh[0x77] << 24)) + 0x200;
+         printf("%08x %s\n", p, pn);
+         if (!strcmp(pn, "WordDocument"))
+               word = p;
+       }
+  if (!word)
+       {
+         fprintf(stderr, "Word doc stream not found!\n");
+         exit(1);
+       }
+  fseek(fi, word, SEEK_SET);
+}
+
+struct fib {
+  word magic;
+  word vers;
+  word product;
+  word lang;
+  word pnnext;
+  byte flags1;
+  byte flags2;
+  word back;
+  ulg cryptkey;
+  byte environ;
+  byte rfu;
+  word textcharset;                                            /* 0=win, 256=mac */
+  word tablecharset;                                   /* 0=win, 256=mac */
+  ulg firsttextchar;
+  ulg xx[6];
+  ulg textlen;
+  ulg footlen;
+  ulg hdrlen;
+  ulg macrolen;
+  ulg annolen;
+  ulg endnotelen;
+  ulg textboxlen;
+  ulg htextboxlen;
+  ulg rfu2;
+  ulg stshorigp, stshorigl;
+  ulg stshp, stshl;
+  ulg footrefp, footrefl;
+  ulg foottxtp, foottxtl;
+  ulg annorefp, annorefl;
+  ulg annotxtp, annotxtl;
+  ulg sedp, sedl;
+  ulg pardp, pardl;
+  ulg pahp, pahl;
+  ulg glossp, glossl;
+  ulg glosp, glosl;
+  ulg hdrp, hdrl;
+  ulg chpbp, chpbl;
+  ulg papbp, papbl;
+  ulg seap, seal;
+  ulg ffnsp, ffnsl;
+  ulg mainfpp, mainfpl;
+  ulg headfpp, headfpl;
+  ulg footfpp, footfpl;
+  ulg annofpp, annofpl;
+  ulg macfpp, macfpl;
+  ulg boosp, boosl;
+  ulg bookop, bookol;
+  ulg booklp, bookll;
+  ulg cmdsp, cmdsl;
+  ulg mcrpp, mcrpl;
+  ulg mcrsp, mcrsl;
+  ulg pdrvp, pdrvl;
+  ulg prenvpp, prenvpl;
+  ulg prenvlp, prenvll;
+  ulg wssp, wssl;
+  ulg dopp, dopl;
+  ulg assosp, assosl;
+  ulg compp, compl;                                            /* Complex file info! */
+  ulg footpgp, footpgl;
+  ulg orignamep, orignamel;
+  ulg annoownp, annoownl;
+  ulg annobnp, annobnl;
+} __attribute__((packed));
+
+ulg txl, lbf;
+
+int
+cc(void)
+{
+  if (txl)
+       {
+         txl--;
+         return gb();
+       }
+  return -1;
+}
+
+char lb[86];
+int lbi;
+
+void
+flb(void)
+{
+  lb[lbi++] = '\n';
+  lb[lbi] = 0;
+  fputs(lb, fo);
+  lbi = 0;
+}
+
+void
+pc(int c)
+{
+  if (lbi >= 80)
+       {
+         int lc = lbi;
+         while (lc > 0 && lb[--lc] != ' ')
+               ;
+         if (!lc)
+               {
+                 lbf++;
+                 flb();
+               }
+         else
+               {
+                 char exb[80];
+                 lb[lbi] = 0;
+                 lb[lc] = 0;
+                 lbi = lc++;
+                 strcpy(exb, lb+lc);
+                 flb();
+                 strcpy(lb, exb);
+                 lbi = strlen(lb);
+               }
+       }
+  lb[lbi++] = c;
+}
+
+void
+text(void)
+{
+  int c;
+
+  for(;;)
+       switch (c = cc())
+         {
+         case -1:
+               flb();
+               if (lbf)
+                 printf("%d line breaks failed\n", lbf);
+               return;
+         case 12:
+               flb();
+               fputc(12, fo);
+               break;
+         case 13:
+               lb[lbi++] = '\n';
+               /* FALL-THRU */
+         case 11:
+               flb();
+               break;
+         case 9:
+         case 14:
+               pc(9);
+               break;
+         case 31:
+               pc('-');
+               break;
+         case 7:
+         case 19:
+         case 20:
+         case 21:
+               break;
+         case 160:
+               pc('~');
+               break;
+         default:
+               pc(c);
+         }
+}
+
+void
+unword(void)
+{
+  struct fib fib;
+  ulg where = ftell(fi);
+
+printf("%d %d\n", (int)&(((struct fib *)0)->compp), where);
+  printf("Reading %d bytes of file header\n", sizeof(fib));
+  if (fread(&fib, sizeof(fib), 1, fi) != 1)
+       {
+         fprintf(stderr, "FIB read error!\n");
+         exit(1);
+       }
+  if (fib.magic != 0xa5db && fib.magic != 0xa5dc)
+       {
+         fprintf(stderr, "Black magic!\n");
+         exit(1);
+       }
+  printf("Lang=%d, charset=[%d,%d]\n", fib.lang, fib.textcharset, fib.tablecharset);
+  if (fib.flags1 & 4)
+        {
+          if (fib.magic == 0xa5db)
+            puts("Complex format, old magic");
+          else
+            {
+                   printf("Complex format, abs start=0x%x, len=%d\n", fib.compp + where, fib.compl);
+              fprintf(stderr, "Fast-saved format not supported yet!\n");
+              exit(1);
+                 }
+       }
+  if (fib.flags2 & 1)
+       {
+         fprintf(stderr, "Encrypted files not supported yet!\n");
+         exit(1);
+       }
+  if (fib.flags2 & 0x1000)
+       puts("Extended charsets detected");
+  printf("First text char at 0x%x, len=%d\n", fib.firsttextchar + where, fib.textlen);
+  fseek(fi, fib.firsttextchar + where, SEEK_SET);
+  txl = fib.textlen;
+  text();
+}
+
+void
+convert(void)
+{
+  word id = gw();
+  if (id == 0xa5db || id == 0xa5dc)
+       {
+         fseek(fi, 0, SEEK_SET);
+         puts("Plain M$-Word file...");
+       }
+  else if (id == 0xcfd0)
+       {
+         puts("OLE file...");
+         ole();
+       }
+  else
+       {
+         fprintf(stderr, "Unknown file format!\n");
+         exit(1);
+       }
+  unword();
+}
+
+int
+main(int argc, char **argv)
+{
+  if (argc != 3)
+       {
+         fprintf(stderr, "Usage: unword <from> <to>\n");
+         return 1;
+       }
+  if (!(fi = fopen(argv[1], "r")))
+       {
+         fprintf(stderr, "Unable to open input file: %m\n");
+         return 1;
+       }
+  if (!(fo = fopen(argv[2], "w")))
+       {
+         fprintf(stderr, "Unable to open output file: %m\n");
+         return 1;
+       }
+  convert();
+  return 0;
+}
diff --git a/whatsit.c b/whatsit.c
new file mode 100644 (file)
index 0000000..a14387e
--- /dev/null
+++ b/whatsit.c
@@ -0,0 +1,12 @@
+int f(int x, int y)
+{
+       return x ? f((x&y) << 1, x^y) : y;
+}
+
+#include <stdio.h>
+#include <stdlib.h>
+int main(int argc, char **argv)
+{
+       printf("%d\n", f(atol(argv[1]), atol(argv[2])));
+       return 0;
+}