Amigo, com algumas modificações o seu código funcionou bem aqui. Primeiramente, seria interessante saber a sua versão do PHP e algumas configurações. Por exemplo, no meu servidor, register_globals não está ativado, logo a parte de cálculo do seu código não funciona. register_globals é uma diretiva da configuração do PHP que registra todas as variáveis recebidas por POST e GET além das super globais do PHP. O seu código assume que essa diretiva esteja ativada. Pois ao pegar os valores de altura e peso você não os recupera dessa maneira: $_POST['peso'], $_POST['altura'] ou ainda $_REQUEST['peso'], $_REQUEST['altura'] (a diferença entre $_POST e $_REQUEST é que, o primeiro apenas recupera dados recebidos via POST e o segundo o faz via POST ou GET, se não houver uma variável com esse nome recebido via POST ele tenta recuperar um valor via GET). Mas recupera simplesmente informando o nome da variável, que é o mesmo nome do campo do formulário: $peso, $altura. Para corrigir, simplesmente atribua às variáveis $peso e $altura o valor recebido via formulário, dessa forma, antes da verificação de dados válidos: $peso = $_POST['peso'];
$altura = $_POST['altura'];
Outro problema está na variável global $PHP_SELF, que possui o mesmo problema: assume que a diretiva register_globals esteja ativada. utilize $_SERVER['PHP_SELF'] ao invés de $PHP_SELF.
Atenção! Mesmo que não esteja com problemas nessa parte de register_globals que eu falei, é interessante você atualizar o código e escrever de acordo com essas regras para maior compatibilidade.
Agora a parte mais importante, que talvez seja o seu problema mesmo, já que é um problema de lógica:
Ao clicar em calcular, você apenas envia os dados para a mesma página que está, e nessa página você verifica se os dados foram enviados da seguinte forma:
if ($calcular != 'S')
A pergunta que eu faço é: Onde eu defino que $calcular é igual a S para que eu possa realizar a operação?
E a resposta: Em lugar nenhum.
Fiz da seguinte forma para resolver o problema, eis o cabeçalho do formulário como ficou:
<form method="POST" action="<?php echo $_SERVER['PHP_SELF']; ?>?calcular=S">
Repare no "?calcular=S" depois do PHP_SELF (que foi alterado de acordo com o que eu falei sobre register_globals), isso indica que quando clicar no botão submit os dados serão enviados via post, mas uma informação será enviada via GET, que é a variável calcular.
Para recuperar o valor dessa variável, utilize ao invés de $calcular, $_GET['calcular'], ou seja, a condição para o início do cálculo ficará assim:
if ($_GET['calcular'] != 'S')
Ou uma forma mais elegante para fazer a comparação seria assim:
if (!$_POST)
E o cabeçalho do formulário continuaria da mesma forma (sem o calcular=S):
<form method="POST" action="<?php echo $_SERVER['PHP_SELF']; ?>"> Essa verificação funciona assim: Se há dados a serem recebidos via POST, a variável global do PHP $_POST conterá um array com pelo menos um elemento, e nesse caso, a comparação retorna verdadeiro. Se não houver dados recebidos via POST, $_POST é um array vazio, logo retorna falso. O !(ponto de exclamação) indica que se Não (!) houver dados no array POST ele faça o que está dentro dos limites da chave, caso contrário (else) faça o cálculo, já que ele tem os dados (do mesmo modo da lógica atual). Qualquer dúvida, estou à disposição.