:TITLE: Modularização - source
;#
;# RCSID: $Header: /home/cvs/TclTutor3/lesson/Tcl_Portuguese/Tcl_Portuguese30.lsn,v 1.1 2008/08/02 12:37:36 clif Exp $
;# Copyright (c) 1995 Clif Flynt
;# 9300 Fleming Rd.
;# Dexter, MI  48130
;# clif@cflynt.com
;# Veja o arquivo "AVISO" com os termos da licença.
;#
;#*********************************************************
;# Portuguese translation: Lucio Agostinho Rocha
;# E-mail: outrosdiasvirao@yahoo.com.br
;# Last update: 16/01/2006
;#*********************************************************
::CMD:: if {([info exists tcl_platform])} {
  switch $tcl_platform(platform) {
    unix        {
                set Tutor(lsn.codeMod) {
                }
        }
    windows     {
                set Tutor(lsn.codeMod) {
		    {regsub {cat} $line {command.com /C type} line}
                {regsub {exec rm \$nomeArquivo} $line {file delete $nomeArquivo} line}

                    {if {[glob -nocomplain C:/temp] != ""} {
                      regsub "/tmp/" $line {C:\\\\temp\\\\} line
		    }
		    }
                    {if {[glob -nocomplain C:/windows/temp] != ""} {
                      regsub "/tmp/" $line {C:\\\\windows\\\\temp\\\\} line
		    }
		    }
                    {if {[glob -nocomplain C:/winnt/temp] != ""} {
                      regsub "/tmp/" $line {C:\\\\winnt\\\\temp\\\\} line
		    }
		    }
                }         
        }
    mac         {
                set Tutor(lsn.codeMod) {
		}
                }
    default     {
                puts "I don't recognize the platform: $tcl_platform(platform)"
                puts "Can't set platform specific parameters"
                }
    } 
  }

:LESSON_TEXT_START_LEVEL 0:
Como outras linguagens modernas, Tcl suporta mecanismos para separar um programa
em múltiplos arquivos.
Esta função é implementada com o comando <CODE>source</CODE>.
<DL>
<B><DT> source</B> <I>nomeArquivo</I>
<DD>Lê o script em <I>nomeArquivo</I> e o executa. Se o script executa com sucesso,
<B>source</B> retorna o valor da última declaração no script.
<P>
Se há um erro no script, <B>source</B> irá retornar um erro.
<P>
Se há um retorno (outro diferente do que esteja dentro da definição do <B>proc</B>) então
<B>source</B> irá retornar imediatamente, sem executar o restante do script.
<P>
Se <I>nomeArquivo</I> inicia com um til (<B>~</B>) então $HOME será
substituído pelo til, como é feito no comando <B>file</B>. Mais
detalhes nesta substituição está disponível na página <B>TildeSubst</B> do manual.
</DL>
:TEXT_END:

:LESSON_TEXT_START_LEVEL 1:
Como Tcl é um interpretador, ele não tem um carregador dinâmico da forma
que linguagens compiladas têm. Todavia, há um mecanismo para carregar e
executar o script em um arquivo. Este comando é o comando <B>source</B>.
<P>
O comando <B>source</B> irá carregar um arquivo e executá-lo.
<P>
Este comando pode ser usado para:
<UL COMPACT>
<LI> separar um programa em múltiplos arquivos;
<LI> criar um arquivo de biblioteca que contém todos os procs para
um conjunto particular de funções;
<LI> configurar programas;
<LI> carregar arquivos de dados.
</UL>
<DL>
<B><DT> source</B> <I>nomeArquivo</I>
<DD>Lê o script em <I>nomeArquivo</I> e o executa. Se o script executa com sucesso,
<B>source</B> retorna o valor da última declaração no script.
<P>
Se há um erro no script, <B>source</B> irá retornar um erro.
<P>
Se há um retorno (outro diferente do que esteja dentro da definição do <B>proc</B>) então
<B>source</B> irá retornar imediatamente, sem executar o restante do script.
<P>
Se <I>nomeArquivo</I> inicia com um til (<B>~</B>) então $HOME será
substituído pelo til, como é feito no comando <B>file</B>. Mais
detalhes nesta substituição está disponível na página <B>TildeSubst</B> do manual.
</DL>
:TEXT_END:

:LESSON_TEXT_START_LEVEL 2:
Como Tcl é um interpretador, ele não tem um carregador dinâmico da forma
que linguagens compiladas têm. Todavia, há um mecanismo para carregar e
executar o script em um arquivo. Este comando é o comando <B>source</B>.
<P>
O comando <B>source</B> irá carregar um arquivo e executá-lo.
<P>
Este comando pode ser usado para:
<UL COMPACT>
<LI> separar um programa em múltiplos arquivos;
<LI> criar um arquivo de biblioteca que contém todos os procs para
um conjunto particular de funções;
<LI> configurar programas;
<LI> carregar arquivos de dados.
</UL>
<P>
Como você pode ver, há muitos usos para o comando <B>source</B>. O uso
principal é que esse comando permite a você separar um conjunto de procs
relacionados em um único arquivo. Você pode então carregar com o comando
<B>source</B> daquele arquivo em diferentes aplicações e ter aqueles procs
disponíveis.
<P>
Por agora, você poderia ter o mesmo efeito colando o código de um
conjunto de procs em cada aplicação que você escreveu que precise
daqueles procs. A razão pela qual você não deveria fazer isso é que
isso é bom até você eventualmente encontrar um bug, ou uma forma melhor
de fazer as coisas, e se o código foi copiado em uma dezena de arquivos,
você terá de modificar todos eles. Se o código existe em um arquivo
que é carregado dentro de outros, então você apenas terá que
corrigir uma vez.
<P>
Execute o exemplo, e examine a saída e o exemplo de código agora.
<P> 
O código do exemplo cria um arquivo com um proc, uma definição, um retorno,
e outra definição de dados.
<P>
As primeiras duas linhas criam um nome de arquivo temporário único usando
o comando <B>pid</B>, e então abre o arquivo para escrita.
<P>
As próximas linhas escrevem o conteúdo do arquivo, e então fecham
o arquivo. Fechar o arquivo o força a ser retirado da memória e passado para
o disco. Sem fechar ou executar o comando <CODE>flush</CODE>, os dados poderiam
ficar retidos em um <I>buffer</I> de entrada/saída, e não estar disponíveis
quando o script tentar carregar aquele arquivo.
<P>
Depois, o arquivo é mostrado utilizando <B>exec</B> para exibir o arquivo
na saída padrão. <B>Exec</B> retorna a saída do programa que ele executa,
que é então exibida pelo comando puts.
<P>
Apenas para checar, as variáveis visíveis são mostradas depois. Depois
que o arquivo temporário foi carregado, as variáveis serão mostradas
novamente.
<P>
A chamada a <CODE>info procs procTeste</CODE> retornará uma string vazia,
uma vez que <B>procTeste</B> não foi definido ainda. O teste terá sucesso e
o arquivo temporário será carregado.
<P>
Uma vez que o arquivo temporário foi carregado, <B>procTeste</B> pode ser
executado. Ele irá mostrar o nome do arquivo de onde ele foi carregado,
como um exemplo do uso do comando <B>info script</B>. Se você apagar a
<B>\</B> antes do colchete na chamada <B>[info script]</B>, a chamada será
avaliada antes de ser escrita, e irá exibir o nome do script de exemplo
que está escrevendo o arquivo temporário. (Isso irá exibir alguma coisa como
/tmp/xmpl.PID.tcl)
<P>
Depois, as variáveis visíveis são mostradas novamente. Note que <B>abc</B> 
está na lista, mas <B>aaaa</B> não está. Isso é porque o comando <B>return</B>
imediatamente antes de <B>aaaa</B> está definido.
<P>
Finalmente, o arquivo temporário é apagado, para manter as coisas elegantes e
limpas.
<DL>
<B><DT> source</B> <I>nomeArquivo</I>
<DD>Lê o script em <I>nomeArquivo</I> e o executa. Se o script executa com
sucesso, <B>source</B> retorna o valor da última declaração no script.
<P>
Se há um erro no script, <B>source</B> irá retornar aquele erro.
<P>
Se há um retorno (outro que o definido dentro do <B>proc</B>) então
<B>source</B> irá retornar imediatamente, sem executar o restante do
script.
<P>
Se <I>nomeArquivo</I> inicia com um (<B>~</B>) então $HOME será substituído
pelo til, como é feito no comando <B>file</B>. Mais detalhes
nesta substituição está disponível na página <B>TildeSubst</B> do manual.
</DL>
:TEXT_END:

:CODE_START:
;# Configura um arquivo temporário com um proc de teste.

set nomeArquivo "/tmp/TT_[pid]"
set arquivoSaida [open $nomeArquivo w]


puts $arquivoSaida {set scr [info script]}
puts $arquivoSaida "proc procTeste {} {"
puts $arquivoSaida "global scr"
puts $arquivoSaida "puts \"procTeste arquivo fonte: \$scr.\""
puts $arquivoSaida "puts \"procTeste executando de \[info script]\n\""
puts $arquivoSaida "}"
puts $arquivoSaida {set abc 1}
puts $arquivoSaida {return}
puts $arquivoSaida {set aaaa 1}

close $arquivoSaida

puts "Este é o conteúdo de $nomeArquivo:"
puts ".............................................................."
puts "[exec cat $nomeArquivo]"
puts ".............................................................."
puts "\n"

puts "Variáveis globais visíveis antes do carregar $nomeArquivo:"
puts "[lsort [info globals]]\n"

;# Verifica que o proc não existe, e carrega o arquivo.

if {[info procs procTeste] == ""} {
 	puts "procTeste não existe. Carregando $nomeArquivo"
	source $nomeArquivo
	}

;# executa o proc.
puts "\nAgora executando procTeste"
procTeste

puts "Variáveis globais visíveis depois de carregar $nomeArquivo:"
puts "[lsort [info globals]]\n"

;# Remove o arquivo extra.
exec rm $nomeArquivo
:TEXT_END:

