Build a program with one simple GOTO

Your task is to build the largest program you can that uses exactly one GOTO, without which the entire program (or at least a huge chunk of it) must be completely restructured. The score is counted as the number of statements in your code that change places or are newly introduced (removing statements doesn't add to your score) when the code is restructured without the GOTO (others are allowed to challenge your restructuring by presenting a more elegant one). As this is code bowling, highest score wins.

Note: I do not claim any liability for velociraptor attacks by attempting this challenge.

• The one single goto seems problematic. Every C code I can think of that uses a single goto can be trivially changed to use structured constructs. Multiple gotos however... – Pubby Feb 26 '13 at 1:42
• @Pubby's claim seems to hold against the current two solutions. Replacing goto with switch seems possible for both. – ugoren Feb 26 '13 at 7:44
• @Pubby How many goto's would you need to create a workable solution? If the problem as currently stated is impossible, I can create an alternative problem. – Joe Z. Feb 26 '13 at 14:30
• I think you're allowed to embed the cartoon, as long as there's a link too. – luser droog Feb 28 '13 at 4:07
• It doesn't qualify, but I really did this. – luser droog Feb 28 '13 at 4:10

C fizzbuzz

This solution runs around the idea of interrupts and label variables (gcc only, sorry). The program sets up a timer which periodically calls main, where we goto whichever place the last execution of our interrupt handler (main) told us we should.

I've never used timers or label variables before, so I think there is much to bowl here.

#include <sys/time.h>
#include <signal.h>
#include <stdio.h>

int main(int argc)
{
static int run = 1;
static int* gotoloc = &&init;
static int num = 0;
static int limit = 50;

goto *gotoloc;
init:
signal(SIGVTALRM, (void (*)(int)) main);
gotoloc = &&loop;

struct itimerval it_val;

it_val.it_value.tv_sec = 0;
it_val.it_value.tv_usec = 100000;
it_val.it_interval.tv_sec = 0;
it_val.it_interval.tv_usec = 100000;
setitimer(ITIMER_VIRTUAL, &it_val, NULL);

while(run);

loop:
num = num + 1;
run = num < limit;
gotoloc = &&notfizz + (&&fizz - &&notfizz) * !(num % 3);
return 1;

fizz:
printf("fizz");
gotoloc = &&notbuzz + (&&buzz - &&notbuzz) * !(num % 5);
return 1;

notfizz:
gotoloc = &&notfizzbuzz + (&&buzz - &&notfizzbuzz) * !(num % 5);
return 1;

buzz:
printf("buzz\n");
gotoloc = &&loop;
return 1;

notbuzz:
printf("\n");
gotoloc = &&loop;
return 1;

notfizzbuzz:
printf("%d\n", num);
gotoloc = &&loop;
return 1;
}

• run should be declared volatile, otherwise while(run) can be "optimized" to while(1). Or instead, just goto somewhere that calls exit. – ugoren Feb 26 '13 at 7:41
• @ugoren Good point. I turned on optimizations (O1, O2 and Os) and all those broke the program. Unfortunately just adding 'volatile' in front of run, gotoloc and num did not fix it. It might be gcc is not built for optimizing this kind of code. – shiona Feb 26 '13 at 7:55
• Defining volatile int num outside of main should do it. With static, gcc thinks it knows who can mess with it. – ugoren Feb 26 '13 at 12:12
• unfortunately I can't create gotoloc outside the main, or I could, but I would have to set it to zero outside and then only reset in in the beginning of main if it's zero. And the appeal stats to fade. So I think it's best to say that I'm using C a bad way, gcc rightfully doesn't optimize it correctly so don't try. – shiona Feb 26 '13 at 16:26

Perl

I'm not very good at bowling, but I suspect this may interest the OP. This is a Sieve of Eratosthenes using a variable goto. Were this to be 'refactored', I doubt any of it would be reusable, other than perhaps the first few lines. When the sieve ends, all remaining 1s in the @primes array correspond to prime values.

For added fun, no ands, ors, ternaries, conditionals or comparison operators of any kind are used.

@primes[2..1e4]=(1)x9999;
$a=2; Y:$b=$a*~-$a;
X:
$primes[$b+=$a+=$c=$a/100%2+$b/1e4%2]=0;
goto"\$c"^h;
Z:

• In case there's any confusion as to why I'm posting this here, in a separate question (now deleted), the OP stated that, "this was the question he actually wanted to ask", but wasn't sure if it was possible. – primo Mar 15 '13 at 4:20
• In case there's any confusion as to what question I posted, it was a question about building code using only GOTO's, rather than just one. – Joe Z. Mar 15 '13 at 12:47
• @JoeZeng I originally had three, but I reduced it to one so that it would be a valid solution to this problem as well. – primo Mar 15 '13 at 13:24

C

My usage of macros perhaps doesn't make it "one GOTO".
And it's quite short, so "completely restructured" isn't much.
But here's my attempt anyway.

Reads a number from standard input, prints it modulu 3.

int main() {
char s[100], *p, r=0;
void *pl[] = { &&a, &&b, &&c, &&d, &&e, &&f, &&g, &&h, &&i, &&j, &&a, &&b, &&x, &&y, &&z }, *p1;
p = gets(s);
#define N(n) (pl+n)[!*p*60+*p-48];p++;goto *p1
a: p1=N(0);
b: p1=N(1);
c: p1=N(2);
d: p1=N(0);
e: p1=N(1);
f: p1=N(2);
g: p1=N(0);
h: p1=N(1);
i: p1=N(2);
j: p1=N(0);
z: r++;
y: r++;
x: printf("%d\n", r);

return 0;
}

• Yeah, using macros like that isn't "one GOTO". But even then, you'd need to provide the restructuring of the program without using a GOTO. Removing statements doesn't add to your score. – Joe Z. Feb 25 '13 at 20:58
• Printing a number modulo 3 would be easy by just using a printf and scanf. Your solution's score would most likely be about 2 or 3. – Joe Z. Feb 25 '13 at 21:02
• Fair point. I can't think of why anybody would ever want to program something that prints n%3 in that way, though. It should be a program that becomes convoluted when the GOTO is removed, not when it is introduced. – Joe Z. Feb 26 '13 at 1:26
• "Why?" is irrelevant for this site - it's full of stupid ways to do stupid things. If you remove goto, the program won't work. But what did you expect - that the program would become convoluted by the removal alone? – ugoren Feb 26 '13 at 7:33
• By the removal and subsequent restructuring, yes. A simple example might be the use of goto to break out of multiple nested loops. – Joe Z. Feb 26 '13 at 19:17