An Automata-Theoretic Approach to Software Verification