After much fruitful discussion and evolution, this proposal is now a series of "Bitcoin Improvement Proposals" -- see BIP 11, 12 and 13: https://en.bitcoin.it/wiki/Bitcoin_Improvement_Proposals
Sincere thanks to everybody who contributed improvements, ideas and code.
Putting the pass/fail value on the alt stack should work:
ScriptSig: siga 0 or ScriptSig: sigb 1 or ScriptSig: sigc 2
ScriptPubKey:
0 TOALTSTACK
DUP 0 EQUAL IF DROP pubkeya CHECKSIG TOALTSTACK 0 ENDIF
DUP 1 EQUAL IF DROP pubkeyb CHECKSIG TOALTSTACK 1 ENDIF
DUP 2 EQUAL IF DROP pubkeyc CHECKSIG TOALTSTACK 2 ENDIF
FROMALTSTACK
Not sure if the first line "0 TOALTSTACK" is needed. What happens if we call FROMALTSTACK with nothing on the stack? Does the transaction fail? If so, then we don't need to push the initial 0 onto the alt stack.
We could also generalize it and save a opcode per line by using 1SUB:
ScriptSig: siga 0 or ScriptSig: sigb 1 or ScriptSig: sigc 2
ScriptPubKey:
0 TOALTSTACK
DUP NOTIF DROP pubkeya CHECKSIG TOALTSTACK 0 ENDIF 1SUB
DUP NOTIF DROP pubkeyb CHECKSIG TOALTSTACK 0 ENDIF 1SUB
DUP NOTIF DROP pubkeyc CHECKSIG TOALTSTACK 0 ENDIF 1SUB
FROMALTSTACK