void copy0 (char *to, char* from, int count)
{
  int n = (count+7)/8;
  switch (count%8) do {
  case 0: *to = *from++;
  case 7: *to = *from++;
  case 6: *to = *from++;
  case 5: *to = *from++;
  case 4: *to = *from++;
  case 3: *to = *from++;
  case 2: *to = *from++;
  case 1: *to = *from++;
  } while (--n>0);
}

void copy1 (char *to, char *from, int count)
{
  int n = (count+7)/8;
  switch (count%8) {
  case 0: do {*to = *from++;
  case 7: *to = *from++;
  case 6: *to = *from++;
  case 5: *to = *from++;
  case 4: *to = *from++;
  case 3: *to = *from++;
  case 2: *to = *from++;
  case 1: *to = *from++;
  } while (--n>0);
  }
}

void copy2 (char *to, char* from, int count)
{
  int n = (count+7)/8;
  switch (count%8) while (n-->0) {
  case 0: *to = *from++;
  case 7: *to = *from++;
  case 6: *to = *from++;
  case 5: *to = *from++;
  case 4: *to = *from++;
  case 3: *to = *from++;
  case 2: *to = *from++;
  case 1: *to = *from++;
  };
}

void copy3 (char *to, char *from, int count)
{
  int n = (count+7)/8;
  switch (count%8) {
  case 0: while (n-->0) {*to = *from++;
  case 7: *to = *from++;
  case 6: *to = *from++;
  case 5: *to = *from++;
  case 4: *to = *from++;
  case 3: *to = *from++;
  case 2: *to = *from++;
  case 1: *to = *from++;
  };
  }
}

void copy4 (char *to, char* from, int count)
{
  int n = (count+7)/8, i;
  switch (count%8) for (i=0; i<n; i++) {
  case 0: *to = *from++;
  case 7: *to = *from++;
  case 6: *to = *from++;
  case 5: *to = *from++;
  case 4: *to = *from++;
  case 3: *to = *from++;
  case 2: *to = *from++;
  case 1: *to = *from++;
  };
}

void copy5 (char *to, char *from, int count)
{
  int n = (count+7)/8, i;
  switch (count%8) {
  case 0: for (i=0; i<n; i++) {*to = *from++;
  case 7: *to = *from++;
  case 6: *to = *from++;
  case 5: *to = *from++;
  case 4: *to = *from++;
  case 3: *to = *from++;
  case 2: *to = *from++;
  case 1: *to = *from++;
  };
  }
}

/* The semantics of func{0,1,2} () are the same:
 *   if (foo%2 == 0), func(foo) returns 2;
 *   if (foo%2 == 1), func(foo) returns 13 -- the initialization of the loop
 * is skipped, thus the loop behaves as if started from -11. */

int func0 (int foo)
{
    int bar = 0, i = -11;
    switch (foo%2)
    {
    case 0:
      i=0;
      for(;i<2;) {
    case 1:
      bar += 1;
      i++;
    }
    }
    return bar;
}

int func1 (int foo)
{
    int bar = 0, i = -11;
    switch (foo%2)
    {
    case 0:
      i=0;
      while(i<2) {
    case 1:
      bar += 1;
      i++;
    }
    }
    return bar;
}

int func2 (int foo)
{
    int bar = 0, i = -11;
    switch (foo%2)
    {
    case 0:
      i=0;
      do {
    case 1:
      bar += 1;
      i++;
    } while (i<2);
    }
    return bar;
}

int
main(void)
{
  if (func0 (7) != func1 (11))
    return 1;
  if (func0 (4) != func2 (8))
    return 1;
  if (func1 (6) != func2 (2))
    return 1;

  return 0;
}

/* The following two routines aren't true Duff's device implementations, but,
 * inspired by it, test the imbrication of switch with if/else block. */
int func3 (int x)
{
  int i = 0;
  switch(x%2) {
    case 0:
      i=x;
      if (i<10) {
    /*@fallthrough@*/
    default:
        i++;
      }
  }

  return i;
}

int func4 (int x)
{
  int i = 0;
  switch(x%2) {
    case 0:
      if (i<10) {
        i=x;
      }
      else {
    /*@fallthrough@*/
    default:
        i++;
      }
  }

  return i;
}

