%% Notas para la creación del fichero .dvi de impresión:
%% He intentado eliminar todas las dependencias con ficheros de formato
%% de TeX que he podido para que se pueda pasar por plain TeX.
%% Utiliza el comando 'itex E_spanish.tex'
%% donde itex es 'virtex &iplain', y iplain se creó utilizando:
%%----inicio fichero
%%\input plain
%%\input amiga
%%\def\fmtname{iplain}
%%\dump
%%----fin fichero
%%  ¡¡¡amiga.tex lo puedes encontrar al final del fichero!!!
%%  Las únicas dependencias que quedan son las dos primeras líneas:
%%\selectlanguage{spanish}
%%  que es necesaria para que TeX incluya el guionado de forma correcta
%%  esto forma parte del paquete 'babel'.  Puedes eliminar esta línea,
%%  con lo que es probable que TeX utilice guionado ingles, y puede que
%%  necesites indicar el punto de ruptura de algunas palabras con '\-'.
%%\input manmac
%%  manmac.tex debería incluirse en tu distribución de TeX, si no,
%%  contacta conmigo, y yo te puedo enviar una versión de ese fichero.
%%  u0868551@oboe.etsiig.uniovi.es

% Este manual tiene copyright (C) 1995 de Antonio J. Gomez Gonzalez.
% !`Reservados todos los derechos!

\selectlanguage{spanish}
\input manmac
%% Mis macros para este libro
\hsize=32pc    \vsize=52pc
\hoffset=1.52cm %3.57pc
\pagewidth=32pc \pageheight=52pc
\parindent=2em
\catcode`@=11 % borrow the private macros of PLAIN (with care)
%% Si quieres obtener unas marcas para ver si las paginas quedan centradas,
%% comenta la siguiente linea (con %).
\def\setcornerrules{}
\outer\def\subsec#1. {\medbreak\advance\subsecno by 1
  \noindent{\it \the\subsecno.\enspace#1.\enspace}}
\outer\def\adver'#1'#2'#3'{\d@nger {\bf #1}\hfil\break #3\hfil\break}
\outer\def\error'#1'#2'#3'{\dd@nger {\bf #1}\hfil\break #3\hfil\break}
\catcode`\@=\other
\def\fadver{\endgraf\endgroup} % omits the \medbreak
\def\ferror{\endgraf\endgroup} % omits the \medbreak
\let\centrada=\centerline
\let\derecha=\rightline
\let\izquierda=\leftline
\def\b/{/\penalty\exhyphenpenalty} % una `/' que actua como un `-'
%% nueva macro para notas a pie de pagina numeradas de forma automatica.
\newcount\numeronota
\def\reinicianotas{\numeronota=0\relax}
\def\nota{\advance\numeronota by 1
  \footnote{$^{\the\numeronota}$}}
%% fin nueva macro
\outer\def\seccion#1. {\bigbreak
  \subsecno=0
  \noindent{\docess #1.\par\nobreak\smallskip\nobreak}\noindent}
%% Yo prefiero los contenidos en tipo slanted
\def\<#1>{\leavevmode\hbox{$\langle${\sl #1}\/$\rangle$}} % syntactic quantity
\def\acerca{\stretch}
\def\noin{\noindent}
\def\bloque{\bull}
\def\finpar{\parbreak}
\def\lineas{\beginlines}
\def\finlineas{\endlines}
\def\finlineasligero{\weakendlines}
\def\finlineasfinal{\finalendlines}
\font\docess=cmss12
\def\pregunta#1{\Espacio\item{$-$} {\sl #1}\par\nobreak\smallskip\nobreak}
\def\ejemplos{\par\nobreak\vbox\bgroup\halign\bgroup ##\hfil&\qquad##\hfil\cr}
\def\Ejemplos{\smallskip  \vbox\bgroup\halign\bgroup ##\hfil&\qquad##\hfil\cr}
\def\fin{\egroup\egroup\noindent\ignorespaces}
\def\finsma{\egroup\egroup\smallskip\noindent\ignorespaces}
\def\finmed{\egroup\egroup\smallskip\noindent\ignorespaces}
\def\proto#1{\medskip\noindent\quad{\tt #1}\par\nobreak\smallskip\nobreak\noindent\ignorespaces}
\def\pproto#1{\vskip-\smallskipamount\noindent\quad{\tt #1}\par\nobreak\smallskip\nobreak\noindent\ignorespaces}
\def\espacio{\smallskip\noindent\ignorespaces}
\def\Espacio{\medskip\noindent\ignorespaces}
\def\Esptab{\noalign{\medskip}}
\def\esptab{\noalign{\smallskip}}
\def\bartab{\noalign{\smallskip\hrule\smallskip}}
\def\E/{Amiga~E}
\def\ASCII/{{\sc ASCII}}
\def\saltacap{\eject\reinicianotas}
\titlepage
\pageno=-1995
\line{\cmman \hfill E\hfill}
\vfill
\line{\sl\hfill Por Antonio J. Gomez Gonzalez\hfill}
\line{\sl\hfill u0868551@oboe.etsiig.uniovi.es\hfill}
\eject
% title
\pageno=-1 % the front matter is numbered with roman numerals
\font\auth=cmssdc10 scaled\magstep4 % used only on the title page
\font\elevenbf=cmbx10 scaled\magstephalf % ditto
\font\elevenit=cmti10 scaled\magstephalf % ditto
\font\elevenrm=cmr10 scaled\magstephalf % ditto
\titlepage
\line{\cmman \hfill E\hfill}
\vskip 1pc
\baselineskip 13pt \elevenbf
\halign to\hsize{#\hfil\tabskip 0pt plus 1fil&#\hfil\tabskip0pt\cr
\kern5.5mm\auth Wouter \kern-1ptvan \kern-1ptOortmerssen&\cr
\noalign{\vskip 12pc}
&\elevenit Traducido por\cr
&Antonio J. \kern-1ptGomez Glez\cr
\noalign{\vfill}
&Gij\'on\enspace$\cdot$\enspace Espa\~na\cr}
\eject
% copyright
\titlepage
\eightpoint
\vbox to 8pc{}
\noindent\strut
Este manual describe la versi\'on 3.1a del compilador de \E/\null{}. Algunas
de las caracter\'{\i}sticas avanzadas que se describen aqu\'{\i} no est\'an
presentes en versiones anteriores.

\Espacio
Este texto est\'a dise\~nado para ser impreso, y difiere en ciertos aspectos
de la gu\'{\i}a de |amigaguide| del compilador, aunque en muy pocos
aspectos.

\Espacio
\E/ tiene copyright $\copyright$ de Wouter van Oortmerssen.
\vfill
\noindent
{\sl \kern-1pt Segunda impresi\'on, revisada, Abril 1995} % hardcover

\espacio
Copyright $\copyright$ 1995 por Antonio Joqu\'{\i}n Gomez Gonzalez

\espacio
Este libro se publica como parte de la distribuci\'on de la versi\'on v3.1a
de \E/\null{}.  Debe quedar claro que el \'unico responsable de la fiabilidad
de esta traducci\'on es Antonio J.~Gomez Gonzalez, aunque por otra
parte, no acepto ninguna responsabilidad sobre da\~nos provocados por su
lectura, es decir, ac\'eptala como es.

\Espacio
ISBN 0-000-00000-0\par % paperback
\eject

\reinicianotas
% the preface
\titlepage
\def\rhead{Introducci\'on}
\vbox to 8pc{
\derecha{\titlefont Introducci\'on}\vss}
{\topskip 9pc % this makes equal sinkage throughout the Preface
\vskip-\parskip
\tenpoint
\noindent\hang\hangafter-2
\smash{\lower12pt\hbox to 0pt{\hskip-\hangindent\cmman G\hfill}}\hskip-4pt
{\sc ENEROSO} L{\sc ECTOR}: \strut Este es un libro sobre \E/\null{}, el cual
es un lenguaje de alto nivel orientado a objetos\b/procedural\b/funcional no  puro,
influenciado en gran medida por lenguajes tales como C++,
Ada,  Lisp, etc.  Es un lenguaje de programaci\'on de prop\'osito general, y
la  implementaci\'on  para  Amiga est\'a dirigida espec\'{\i}ficamente a programar
aplicaciones  de  sistema.   El n\'umero de caracter\'{\i}sticas del lenguaje es
demasiado grande como para resumirlas todas, entre las cuales se incluye:
velocidad  de  compilaci\'on superior a~20000 l\'{\i}neas por minuto en un Amiga
a~7~Mhz,  ensamblador en l\'{\i}nea y enlazador\nota{linker.} integrados dentro del
compilador,  un  gran  conjunto de funciones integradas, buen concepto de
m\'odulos  con  includes  de  v39  como m\'odulos, sistema de tipos flexible,
expresiones {\it entrecomilladas}, listas inmediatas, con tipo, polimorfismo
a  bajo nivel y de objetos, manejo de excepciones, herencia, ocultamiento
de  datos, m\'etodos, valores de retorno m\'ultiples, argumentos por omisi\'on,
reserva de registros, manejo r\'apido de memoria, unificaci\'on, \hbox{Celdas-LISP},
(macro-)preprocesador, depurador a nivel de fuente, y mucho m\'as~\dots

\Espacio
Veamos nuestro primer programa en E, el {\tt HolaMundo} de siempre:
\begintt
/* nominado para ejemplo `mas aburrido' */
 
PROC main()
  WriteF('!`Hola Mundo!\n')
ENDPROC
\endtt

\noin La distribuci\'on incluye:

\vbox{\settabs\+\indent&modules\qquad&\cr
\+&bin/&     compilador |EC| y las utilidades de apoyo.\cr
\+&modules/& m\'odulos E de Amiga v39 y utilidades en m\'odulos enlazables.\cr
\+&docs/&    documentaci\'on de E.\cr
\+&src/&     fuentes de ejemplo en E.\cr
\+&tools/&   herramientas opcionales para usar con E.\cr
}

\noin La distribuci\'on de \E/ v3.0 que incluye la versi\'on de demostraci\'on del
compilador es FreeWare y se puede copiar libremente.  Algunos de vosotros habreis
recibido un archivo con la versi\'on registrada del compilador, el cual {\bf NO} es
FreeWare, y {\bf NADIE} m\'as debe copiarlo.

   No est\'a autorizada la distribuci\'on de \E/ por un importe superior al de
disco+correo (menos de 500~pts), as\'{\i} como tampoco se autoriza ning\'un otro tipo de
distribuci\'on cuyo \'unico prop\'osito sea el de obtener beneficios.

   {\bf Prohibo} a Serge Hamouche o su compa\~nia {\sl France Festival Distribution}
distribuir E de forma alguna\nota{Serge Hamouche ha distribuido~E sin mi permiso,
utilizando mi nombre de forma incorrecta y rob\'andome dinero a expensas de los
programadores de~E franceses.  Si le has pagado dinero, recl\'amaselo y com\'enta esta
situaci\'on a toda la gente que puedas para que no lo sigua haciendo.}.  Por otro
lado, hay una traducci\'on de este documento en franc\'es con mi autorizaci\'on
(realizada por Olivier~Anh) que est\'a disponible en Aminet.

   Esta distribuci\'on debe ofrecerse siempre como un todo, es decir, de la misma
forma que el archivo |.lha| original.  Sin a\~nadidos, modificaciones, traducciones,
distribuciones parciales o cualquier otra cosa que se pueda hacer sin mi permiso.
No hay garant\'{\i}as.  Si consigues ahogar al pez que tienes en la pecera usando~E, o
si~E resulta no ser apropiado para pedir pizzas, ese es t\'u problema (y s\'olo tuyo).
Pase lo que pase no me maldigas por ello.

\medskip
   Fred Fish tiene premiso especial para distribuir~E en sus \hbox{CD-ROMs}.
\medskip

   La distribuci\'on de \E/ es PD\null{}, y contiene la versi\'on demo del compilador.
Los programadores registrados obtienen el compilador completo en un archivo a
parte, en el que s\'olo est\'a |EC|.

   As\'{\i} que, ?`que hay de la versi\'on demo que se incluye?  El compilador s\'olo crear\'a
ejecutables de menos de 8KB, por encima de esos 8KB mostrar\'a el error
|"workspace full"|\nota{espacio de trabajo lleno.} A parte de eso, es totalmente
funcional.  Puedes evaluar la demo durante {\bf dos semanas}, tras las cuales debes
decidir si registrarte o dejar de usarla, incluso si s\'olo escribes programas de
menos de 8KB\nota{Sol\'{\i}an ser 12KB, s\'{\i}, !`adivina porqu\'e lo cambi\'e!}.

   Para ver el coste de una copia, la forma de enviar el dinero, donde enviarlo,~\dots
echa un vistazo a lo documentaci\'on electr\'onica de la distribuci\'on.  Aseg\'urate
de enviar informaci\'on tan completa como puedas con el dinero, por ejemplo,
direcci\'on completa, direcci\'on de correo electr\'onico, incluso puedes a\~nadir la
configuraci\'on de tu Amiga.  Yo no voy a escribir aqu\'{\i} uno de esos tontos impresos
de registro |:-)|

   Las actualizaciones de la distribuci\'on se pueden encontrar en DP como siempre, y
las actualizaciones del EC registrado se distribuyen como parches, tambi\'en en
Dom\'{\i}nio P\'ublico.

   Si ya has recibido el EC registrado, ser\'{\i}a conveniente que lo pusieras en el
directorio |bin/|.  Todo el mundo puede copiar libremente el archivo de
distribuci\'on, pero, por favor, aseg\'urate de que no distribuyes tu copia registrada
de EC a nadie, ni siquiera a los amigos.  No he serializado esas copias por la
confianza que tengo en mis usuarios registrados, por ello, no rompas esa confianza.
La cuota de registro es bastante asequible, y la versi\'on v2.1b sigue estando
disponible, por lo que no hay excusa para que piratees~E.

   El compilador de \E/ ha sido desarrollado a lo largo de m\'as de tres~a\~nos
y~medio, fruto de las ideas del autor sobre un buen lenguaje de programaci\'on, y un
compilador de calidad espec\'{\i}fico del Amiga.  Ha sido programado (como podr\'as haber
apreciado) 100\% en ensamblador, usando el ensamblador AsmOne~v1.02.  Todos los
dem\'as programas de apoyo han sido programados en el propio \E/.

\Espacio
Agradezco especialmente a la siguiente gente:

\vbox{\settabs\+\qquad&Jason Hualance\quad&\cr
\+&Barry Wills&   $-$ por ser el mejor mejor betatester de siempre.\cr
\+&Jason Hulance& $-$ por su trabajo en {\sl The Beginners Guide}, y betatest.\cr
\+&Rob Verver&    $-$ por comentarios/inspiraci\'on.\cr
}

\noin Tambi\'en me gustar\'{\i}a agredecer a los siguientes por varias razones (sin un
orden particular) :

\midinsert\narrower
\noin Raymond Hoving,  Erwin van~Breemen, Michael  Zuchhi, James  Cooper, Jens
Gelhar,  Paolo Silvera,  Sergio  Ruocco, Jeroen Vermeulen,  Jan van den
Baard, Joerg Wach, Norman Kraft, Urban Mueller, Charles McCreary, Olivier
Anh, Lionel Vintenat, Rob Nottage, and many more~\dots
\endinsert

   Este compilador se ha programado poniendo mucho cuidado en lo referente a
fiabilidad, y m\'as cuidado a\'un en el c\'odigo que genera, adem\'as ha sido comprobado y
depurado durante largo tiempo.  Sin embargo, es muy posible que contenga alg\'un
error.  Si llegas a encontrar uno, o tienes otros comentarios\b/preguntas,
escr\'{\i}beme a la direcci\'on de m\'as abajo:  Prefiero {\bf con diferencia} correo
electr\'onico sobre correo convencional.

{\bf Apunta bien}:  debido a la gran popularidad de las versiones anteriores de
\E/, recibo una cantidad casi incontestable de correo electr\'onico, buena parte
del cual (|>90%|) son preguntas que no ser\'{\i}an necesarias si la gente leyera los
documentos con cuidado.  Lo que quiero decir es que me gusta recibir correo
electr\'onico, y no me importa responder preguntas y ayudar a la gente con problemas
de programaci\'on, pero, antes de escribirme, aseg\'urate de comprobar los documentos
que tienes a tu disposici\'on (como los documentos de \E/ o los RKRMs) para ver si la
pregunta es relevante.  M\'as precismente, no debeis enviarme preguntas que no son
espec\'{\i}ficas de E, sino del Amiga.  E~intenta ser amable conmigo con comentarios
como ``{\sl Yo creo que \E/ debe tener la caracter\'{\i}stica X\/}~\dots ''\nota{N.T.:
por supuesto en ingl\'es $;-)$}.  Hecha un vistazo a la FAQ.

\Espacio
Ser\'an bien recibidos registros y donaciones en la siguiente direcci\'on:

\vbox{\settabs\+\indent\qquad&\cr
\+&Wouter van Oortmerssen\cr
\+&Levendaal 87\cr
\+&2311 JG  Leiden\cr
\+&HOLANDA\cr
}

\noin o, mejor, si tienes acceso a correo electr\'onico:

\vbox{\settabs\+\indent\qquad&\cr
\+&wouter@mars.let.uva.nl\cr
\+&wouter@alf.let.uva.nl\qquad (si mars rebota)\cr
}

\bigskip
\line{{\sl Gij\'on, Asturias}\hfil--- A. J. G. G.}
\line{\sl Marzo 1995\hfil}

} % end of the special \topskip



\endchapter\saltacap
\beginchapter Cap\'{\i}tulo 1. Usando el\\compilador

\pageno=1 % Pagina numero 1
Para instalar \E/ en tu sistema, s\'olo tienes que copiar toda la distribuci\'on en
alg\'un lugar de tu sistema, extender tu path al directorio |BIN|, \thinspace y
asignar |EModules:| \negthinspace al directorio |MODULES|.

\espacio
Sintaxis del compilador (2.04+):
\begintt
SOURCE/A,REG=NUMREGALLOC/N/K,LARGE/S,SYM=SYMBOLHUNK/S,NOWARN/S,
QUIET/S,ASM/S,ERRLINE/S,ERRBYTE/S,SHOWBUF/S,ADDBUF/N/K,
IGNORECACHE/S,HOLD/S,WB/S,LINEDEBUG/S,OPTI/S,DEBUG/S:
\endtt
Sintaxis para 1.2 a 2.03:
\begintt
EC [-opcs] <fichero_fuente>
\endtt

   Puedes  ver  las opciones estandard de AmigaDos en cualquier momento
escribiendo  `|EC ?|'.  Las opciones en las versiones \hbox{1.2$-$2.03} del sistema
son  de  tipo Unix (hay que escribirlas todas juntas, precedidas de ``$-$''). La mayor
parte de las veces no necesitar\'as usar estas opciones.  Veamos su significado:

\smallskip

\vbox{\halign{{\tt#}\hfil&\enspace{\tt#}\hfil&
         \enspace\vtop{\parindent=0pt\hsize=24pc\hangindent=0pt\strut#\strut}\cr
2.04+&1.2+&Descripci\'on\cr
\bartab
LARGE&       -l&  Compila con modelo c\'odigo/datos grande. \hfill|OPT LARGE|\cr
ASM&         -a&  Pasa |EC| a modo ensamblador.\hfill|OPT ASM|\cr
NOWARN&      -n&  Suprime advertencias.\hfill|OPT NOWARN|\cr
SYM&         -s&  Inserta un |symbolhunk| al ejecutable,  que utilizar\'an
                  los profilers, depuradores, desensambladores~\dots\cr
LINEDEBUG&   -L&  Inserta bloque de depuraci\'on  |LINE|  al ejecutable,
                  para profilers, depuradores,~\dots \hfill|OPT LINEDEBUG|\cr
REG=N&       -rN& Hace que se reserven  |N|  registros por |PROC|\null{}.  (0~por
                  omisi\'on, !`mira en alg\'un otro sitio sobre esto!)\cr
QUIET&       -q&  Pone |EC| en modo silencioso,  s\'olo escribe cuando hay\
                  errores o advertencias.\cr
WB&          -w&  Pone el WB delante (para scripts).\cr
SHOWBUF&     -b&  Muestra informaci\'on de uso de memoria de buffer.\cr
ADDBUF=X&    -mX& Hace que |EC| reserve m\'as memoria para buffers. |X| est\'a
                  en el intervalo  1--9  ---n\'umero de m\'{\i}nimo de bloques
                  de 100KB reservados. (1~por omisi\'on, casi no se usa)\cr
ERRLINE&     -e&  |EC| retorna el n\'umero de l\'{\i}nea del error.\cr
ERRBYTE&     -E&  |EC| retorna la posici\'on (en bytes) respecto al inicio
                  del fichero en la que se produjo el error.\cr
IGNORECACHE& -c&  Deshabilita el uso del cach\'e de m\'odulos.\cr
HOLD&        -h&  Espera a que se pulse \<|return|> antes de continuar.\cr
OPTI&          &  Activa las optimizaciones (de momento es |REG=5|).\cr
DEBUG&         &  Inserta informaci\'on de depuraci\'on en ejecutable o m\'odulo.\cr
}}

\espacio
Por ejemplo, |ec LARGE blabla| compila |blabla.e| con modelo grande.
\medskip
   El compilador no se puede hacer residente.  Si un programa usa ficheros
m\'odulo para definiciones de biblioteca como:
\ejemplos
&|MODULE 'GadTools', 'Reqtools'|\cr
\fin
el compilador necesita saber donde est\'an.  Hay dos posibles soluciones:\par
1. Realizar la asignaci\'on \hbox{|EModules:|} al directorio de m\'odulos (mejor).\par
2. Indicar en el c\'odigo fuente donde debe buscar los m\'odulos, como:
\ejemplos
&|OPT DIR='dh0:src/e/modules'|\cr
\fin
\medskip
   Veamos como ejemplo la compilaci\'on del programa |HolaMundo.e|.  El compilador producir\'a
un ejecutable |HolaMundo|.
\begintt
E:>  ec holamundo
Amiga E Compiler/Assembler/Linker v2.4f (c) 91/92/93 $#%!
lexical analysing ...
parsing and compiling ...
no errors
E:>  holamundo
!`Hola Mundo!
E:>  list
HolaMundo.e                   89 ----rwed Hoy       17:37:00
HolaMundo                    656 ----rwed Hoy       17:37:00
2 files - 4 blocks used
E:>
\endtt




\endchapter\saltacap
\beginchapter Cap\'{\i}tulo 2. Formato del\\lenguaje

\subsec Tabuladores, cambio de l\'{\i}nea, etc.
El c\'odigo fuente en~E son ficheros en formato \ASCII/ puro, con cambio de l\'{\i}nea
\<|lf|> y punto y coma |;| como separadores de dos sentencias.  Las sentencias que
tengan un n\'umero particularmente grande de elementos se pueden repartir a lo largo
de varias l\'{\i}neas finaliz\'andolas con una coma (o con cualquier otro elemento l\'exico
que normalmente no puede aparecer en el fin de l\'{\i}nea), ignorando de esa forma el
siguiente \<|lf|>.

\noin En un fichero de c\'odigo fuente los elementos l\'exicos pueden estar separados
entre s\'{\i} por cualquier n\'umero de espacios, tabuladores,~\dots

\subsec Comentarios.
En un fichero fuente los comentarios se pueden poner en cualquier lugar en
el que normalmente un espacio ser\'{\i}a correcto.  Empiezan con |/*| y finalizan
con |*/|, y se pueden anidar infinitamente.  Lo mismo se puede decir para
los comentarios de una l\'{\i}nea, los cuales empiezan con un |->| y finalizan en
el primer \<|lf|>.
\begintt
/* esto es un comentario */
-> esto tambi\'en.
\endtt

\subsec Identificadores y tipos.
Los identificadores son cadenas que el programador usa para denotar un
cierto objeto, en la mayor\'{\i}a de los casos variables, o incluso palabras
claves o nombres de funciones predefinidas por el compilador.  Un
identificador est\'a formado por:

{\obeylines
$-$ caracteres en may\'uscula o min\'uscula.
$-$ |0...9| (excepto como primer caracter).
$-$ |_| (el subrayado).
}

\espacio
Todos los caracteres son significativos, aunque el compilador s\'olo
mira los dos primeros para determinar el tipo de identificador con el que
est\'a tratando:
\Ejemplos
\qquad Ambos en may\'uscula:&palabra clave como |IF|, |PROC|,~\dots\cr
                          &constante, como |MAX_LENGTH|,~\dots\cr
                          &mnemot\'ecinico ensamblador, como |MOVE|,~\dots\cr
\qquad Primera min\'uscula  &identificador de variable/etiqueta/objeto,~\dots\cr
\qquad Primera may\'us.\ y seg.\ min\'us.&funci\'on del sistema E como: |WriteF()|,~\dots\cr
                                     &llamada de librer\'{\i}a: |OpenWindow()|,~\dots\cr
\fin
Todos los identificadores verifican esta sintaxis, por
ejemplo:  |WBenchToFront()| se convierte en |WbenchToFront()|.

\Espacio
A nivel sem\'antico, los programas en~E estan formados por expresiones.  Una
expresi\'on es un fragmento de c\'odigo formado por operadores, funciones y
par\'entesis que conforman un valor.  La mayor\'{\i}a est\'an formadas por:

{\obeylines
$-$ valores inmediatos.
$-$ operadores (Matem\'aticos,~\dots)
$-$ llamadas a funciones.
$-$ par\'entesis |()| ---determinando precedencia y agrupamiento.
$-$ variables o expresiones variables.
}
\Ejemplos
Ejemplos de expresiones:&|1                      'hola'|\cr
                        &|$ABCD+(2*6)+Abs(a)   (a<1) OR (b>=100)|\cr
\finsma
Veamos algunos de estos elementos:

\subsec Precedencia y agrupamiento.
El lenguaje E no tiene ning\'un tipo de precedencia.  Esto quiere decir que
las expresiones se eval\'uan de izquierda a derecha.  Puedes cambiar la
precedencia encerrando entre par\'entesis algunas (sub-)expresiones.
\Ejemplos
Ejemplos:&|1+2*3 /* =9 */   1+(2*3) /* =7 */   2*3+1  /* =7 */|\cr
\fin

\subsec Expresiones.
Hay tres tipos de expresiones, y se pueden usar con diferentes prop\'ositos:
\item{$-$} \<var>, formada simplemente por una variable.
\item{$-$} \<expvar>, formada por una variable, posiblemente con operadores
           unarios como ``|++|'' (incremento), ``|.|'' (selecci\'on de
           miembro) o ``|[]|'' (operador de arreglo).  Denota una expresi\'on
           modificable (como los valores-i\nota{l-values.} del~C).  Se\~nalar
           que esos operadores (unarios) no forman parte de ninguna
           precedencia.
\item{$-$} \<exp>. Incluye \<var> y \<expvar>, y cualquier otra expresi\'on.

\subsec Llamadas a funciones.
La llamada a una funci\'on es una suspensi\'on temporal del c\'odigo actual
para {\it saltar} a esa funci\'on, \'esta puede ser una funci\'on escrita por uno
mismo (|PROC|), o una funci\'on proporcionada por el sistema.  El formato de
una llamada a funci\'on es, el nombre de la funci\'on seguido de dos par\'entesis
que encierran argumentos que pueden ser desde~0 hasta un n\'umero ilimitado de
ellos, que van separados por comas ``|,|''.  Se\~nalar que los argumentos de
funciones son expresiones de nuevo.
\Ejemplos
Ejemplos:&|foo( 1, 2 )|\cr
         &|Gadget( buffer, glist, 2, 0, 40, 80+offset, 100, 'Cancela' )|\cr
         &|Close( handle )|\cr
\finsma
Tanto los valores inmediatos como los operadores se detallan en los
pr\'oximos cap\'{\i}tulos.



\endchapter\saltacap
\beginchapter Cap\'{\i}tulo 3. Valores\\inmediatos

Todos los valores inmediatos en~E se eval\'uan a un resultado de 32~bits, la
\'unica diferencia entre todos ellos puede ser su representaci\'on interna, o el
hecho de que retornen un puntero en vez de un valor.

\subsec Decimal (|1|\/).
Un valor decimal es una sequencia de caracteres |0...9|, posiblemente
precedidos de un signo menos ``|-|'' (denotando un valor negativo).
\Ejemplos
Ejemplos:&|1, 100, -12, 1024|\cr
\fin

\subsec Hexadecimal (|\$1|\/).
Un valor hexadecimal usa adem\'as los caracteres |A...F| (o |a...f|) y
van precedidos por el caracter |$|.
\Ejemplos
Ejemplos:&|$FC, $DFF180, -$ABCD|\cr
\fin

\subsec Binario (|\%1|\/).
Los n\'umeros binarios empiezan con un caracter |%| y s\'olo usan los caracteres
|1| y |0| para formar un valor.
\Ejemplos
Ejemplos:&|%111, %1010100001, -%10101|\cr
\fin

\subsec Real (|1.0|\/).
Los n\'umeros reales difieren de los decimales en que tienen un ``|.|'' para
separar sus dos partes.  Se puede prescindir de cualquiera de las partes,
pero nunca las dos.  Se\~nalar que la representaci\'on interna de los n\'umeros
reales es diferente (32 bits {\sc IEEE}).
\Ejemplos
Ejemplos:&|3.14159, .1 (=0.1), 1. (=1.0)|\cr
\fin

\subsec Caracter (|"a"|\/).
El valor de un caracter (entre comillas |""|) es su valor \ASCII/, con esto
tenemos que |"A" = 65|.  En~E los valores caracter inmediatos forman una
peque\~na cadena de hasta cuatro caracteres, por ejemplo |"FORM"|, en la que
el primer caracter (|"F"|) es el MSB (Byte M\'as Significativo) de la
representaci\'on de 32~bits, y |"M"| es el LSB (Byte menos Significativo).

\subsec Cadena (|'bla'|\/).
Una cadena es la represtaci\'on \ASCII/ de una secuencia de caracteres que se
escribe entre comillas simples |''|.  El valor de tales tipos de cadena es
un puntero al primer caracter de la misma.  M\'as espec\'{\i}ficamente:  |'bla'|
representa un puntero de 32~bits a un \'area de memoria en la que
encontraremos los bytes |"b"|, |"l"| y |"a"|.  En~E todas las cadenas
terminan con un byte cero.

\noin Las cadenas pueden contener signos de formato introducidos con una
barra inversa |\|, ya sea para introducir en la cadena caracteres que no
son, por alguna raz\'on, visualizables, o para usarla con funciones de
formateo de cadenas como |WriteF()|, |TextF()| y |StringF()|, o la funci\'on
|Vprintf()| de KickStart~2.
\Ejemplos
\qquad |\n|&        cambio de l\'{\i}nea (\ASCII/ 10)\cr
\qquad |\a| o |''|& ap\'ostrofe: |'| (el usado para encerrar la cadena)\cr
\qquad |\q|&        dobles comillas: |"|\cr
\qquad |\e|&        escape (\ASCII/ 27)\cr
\qquad |\t|&        tabulador (\ASCII/ 9)\cr
\qquad |\\|&        la propia barra inversa\cr
\qquad |\0|&        byte cero. De escaso uso (todas las cadenas acaban en 0)\cr
\qquad |\b|&        retorno de carro (\ASCII/ 13)\cr
\finsma
Adem\'as, cuando se usan con funciones de formateo:
\Ejemplos
\qquad |\d|& escribe un n\'umero decimal\cr
\qquad |\h|& escribe un n\'umero hexadecimal\cr
\qquad |\s|& escribe una cadena\cr
\qquad |\c|& escribe un caracter\cr
\qquad |\z|& fija el byte de relleno al caracter |0|\cr
\qquad |\l|& ajusta a el campo a la izquierda\cr
\qquad |\r|& ajusta a el campo a la derecha (ambos act\'uan como interruptores)\cr
\finsma
A los c\'odigos |\d|, |\h| y |\s| les pueden seguir especificadores de campo:
\Ejemplos
\qquad |[x]|&   indica el ancho exacto del campo, |x|\cr
\qquad |(x,y)|& indica el ancho m\'{\i}nimo (|x|) y m\'aximo (|y|), s\'olo con cadenas\cr
\fin

\Ejemplos
Ejemplo:&escribir un n\'umero hexadecimal con 8 posiciones y ceros delante:\cr
        &|WriteF('\z\h[8]\n',num)|\cr
\finsma
Una cadena se puede extender sobre varias l\'{\i}neas continu\'andolas con un
signo |+| y un \<|lf|>:
\begintt
'esta es una cadena deliberadamente larga que ' +
'esta dividida en dos lineas separadas'
\endtt

\subsec Lista (|[1,2,3]|\/) y lista con tipos.
Una lista inmediata es la forma constante del tipo de datos |LIST|a, de
la misma  forma que una  |'cadena'| es la forma  constante de los  tipos de
datos |STRING| ({\it cadena}\/) o |ARRAY OF CHAR| ({\it arreglo de caracteres}\/).
\Ejemplos
Ejemplo:&|[3,2,1,4]|\cr
\finsma
Es una expresi\'on que tiene como valor un puntero a una lista ya
inicializada.  La representaci\'on en memoria de una lista es compatible
con un |ARRAY OF LONG|, con informaci\'on extra sobre la longitud en un
offset negativo.  Puedes usar estas listas inmediatas en cualquier lugar
en el que una funci\'on espere un |PTR| a un arreglo de valores de 32~bits,
o una lista.
\Ejemplos
Ejemplos:&|['string',1.0,2.1]|\cr
         &|[WA_FLAGS,1,WA_IDCMP,$200,WA_WIDTH,120,WA_HEIGHT,150,TAG_DONE]|\cr
\fin

\subsec Celdas-lisp (|<a|\||b>|\/).
Sobre \'estas es mejor que mires en el apartado sobre {\sl Celdas-Lisp y
funciones de celdas}.



\endchapter\saltacap
\beginchapter Cap\'{\i}tulo 4. Operadores

\subsec Matem\'aticos (|+ - * /|\/).
Estos operadores infijos combinan una expresi\'on con otro valor para
obtener un nuevo valor.  ``|-|'' se puede usar como primera parte de una
expresi\'on, lo cual implica un~0\nota{es decir, |-exp| equivale a |0-exp|.}.
Tambien hay que se\~nalar que por omisi\'on |*| y |/| son operadores de 16~bits.
\Ejemplos
Ejemplos:&|1+2, MAX-1*5, -a , -b+1|\cr
\finsma
Es interesante conocer los procedimientos |Mul()| y |Div()|, que
realizan aritm\'etica de 32~bits, as\'{\i} como la sobrecarga de operadores para poder
utilizarlos con n\'umeros reales.  Todo esto se detallar\'a en pr\'oximos cap\'{\i}tulos.

\subsec Comparaci\'on (|= <> > < >= <=|\/).
Igual que los operadores matem\'aticos, con la diferencia de que los
resultados son, o |TRUE| (cierto, valor de 32~bits |-1|), o |FALSE| (falso).
Tambi\'en se pueden sobrecargar para operar con reales.

\subsec L\'ogica y con bits (|AND OR|\/).
Estos operadores pueden combinar valores de verdad para obtener unos
nuevos, o realizar operaciones |AND| y |OR| con bits.
\Ejemplos
Ejemplos:&|(a>1) AND ((b=2) OR (c>=3))   /* logica   */|\cr
         &|a:=b AND $FF                  /* con bits */|\cr
\fin

\subsec (|SIZEOF \^{} -- ++ ` |$\tt \{\}$).

\item{$-$} |SIZEOF |\<identobjeto>
\item{} Simplemente retorna el tama\~no de cierto objeto o |CHAR/INT/LONG|.
\espacio
\item{} Ejemplo:\quad |SIZEOF newscreen + SIZEOF INT|
\espacio
\item{$-$} $\{$\<var>$\}$
\item{} Retorna la direcci\'on de una variable o etiqueta.  Este es el operador
        que usar\'{\i}as para pasar una variable como argumento de una fucni\'on por
        referencia, en lugar de por valor, que es la forma por omisi\'on en E.
\item{} Ejemplo:\quad |Val(input,{x})|
\espacio
\item{$-$} |^|\<var>
\item{} El compa\~nero de |{}|, escribe o lee variables que se han pasado por
        referencia.  Tambi\'en se puede usar para {\it leer {\rm o} escribir}
        de forma directa valores |LONG| de memoria, si \<var> es un puntero
        a tal valor.
\ejemplos
\qquad Ejemplos:&|^a:=1  b:=^a|\cr
                &|PROC set(var,exp)  -> Funcion propia de asignacion...|\cr
                &|   ^var:=exp       -> Para ser llamada con set({a},1),|\cr
                &|ENDPROC            -> de forma que equivale a :  `a:=1'|\cr
\finsma
\item{$-$} \<varexp>|++|   y  \<varexp>|--|
\item{} Incrementa (|++|) o decrementa (|--|) el puntero que se denota con
        \<varexp> en el tama\~no de los datos a los que apunta.  Esto tiene el
        efecto de que ese puntero apuntar\'a al elemento siguiente o anterior.
        Cuando se usa con variables que no son punteros, esas se modificar\'an
        simplemente en uno.  Se\~nalar que |++| siempre act\'ua despu\'es del
        c\'alculo de \<varexp>, |--|, sin embargo, act\'ua {\it antes}.
\ejemplos
\qquad Ejemplos:&|a++   |, devuelve el valor de |a|, y luego incrementa |a|.\cr
                &|sp[]--|, decrementa puntero |sp| en 4  (|ARRAYs OF LONG|),\cr
                &|      |, y luego lee el valor al que apunta |sp|.\cr
\finsma
\item{$-$} |`|\<exp>
\item{} Se le llama expresi\'on entrecomillada, del {\sc LISP}.  \<exp> no se
        eval\'ua, pero en su lugar devuelve la direcci\'on de la expresi\'on, que
        se puede evaluar m\'as tarde cuando se necesite.

\subsec Triplete (|IF THEN ELSE|\/).
El operador |IF| tiene una funci\'on similar a la sentencia |IF|, la \'unica
diferencia es que selecciona entre dos expresiones en vez de entre dos
sentencias o bloques de sentencias.  Igual que el operador |x?y:z| del~C.
\Ejemplos
&|IF| \<expbool> |THEN| \<exp1> |ELSE| \<exp2>\cr
\fin
retorna \<exp> o \<exp2>, dependiendo de \<expbool>.

\noin Por ejemplo, en vez de:
\ejemplos
&|IF a<1 THEN b:=2 ELSE b:=3|\cr
&|IF x=3 THEN WriteF('x es 3\n') ELSE WriteF('x es otra cosa\n')|\cr
\fin
puedes escribir:
\ejemplos
&|b:=IF a<1 THEN 2 ELSE 3|\cr
&|WriteF(IF x=3 THEN 'x es 3\n' ELSE 'x es otra cosa\n')|\cr
\fin

\subsec Estructura ({|.|}).
\<ptrAobjeto>|.|\<miembrodeobjeto> construye una \<expvar>.  El puntero debe
declararse |PTR TO| \<objeto> o |ARRAY OF| \<objeto> y el miembro debe ser
un identificador legal de objeto.  Fij\'ate que el leer un subobjeto de un
objeto de esta forma resulta en un puntero a ese objeto.
\Ejemplos
Ejemplos:&|estatarea.userdata:=1  rast:=mipantalla.rastport|\cr
\finsma
Si el miembro que selecciona es de tipo |PTR TO| \<tipo>, puedes usar
``|.|'' y |[]| para referirte a nuevos valores.  Si seleccionas un |ARRAY| o
una subestructura en un |OBJECT|, el resultado es de nuevo un |PTR|.

\subsec Arreglos (|[]|).
\<var>|[|\<exp\'{\i}ndice>|]| (es una \<expvar>).  Este operador lee el valor del
arreglo al que apunta \<var>, de \'{\i}ndice\nota{en un arreglo de $n$ elementos,
el \'{\i}ndice var\'{\i}a entre $0\ldots n\!-\!1$} \<exp\'{\i}ndice>.  El \'{\i}ndice puede ser
pr\'acticamente cualquier expresi\'on.  Debemos saber que |[]| es una
abreviatura de |[0]|.
\Ejemplos
Ejemplos:&|a[1]:=10       |, pone el segundo elemento a 10.\cr
         &|x:=table[y*4+1]|, lee del arreglo.\cr
         &|x.y[3]         |, accede al arreglo dentro de un objeto.\cr
\fin

\subsec Operador real (|!|\/).
\<exp>|!|\<exp>.  Convierte una espresi\'on de entero a real y viceversa, y
sobrecarga los operadores |+ - * / = <> < > <= >=| con equivalentes para
reales.

\subsec Expresiones de asignaci\'on (|:=|\/).
La asignaci\'on (dar un valor a una variable) existe como sentencia y como
expresi\'on.  La \'unica diferencia es que la versi\'on como sentencia tiene la
forma \<expvar>|:=|\<exp> y la expresi\'on \<var>|:=|\<exp>.  Esta \'ultima
tiene el valor de \<exp> como resultado.

\noin F\'{\i}jate en que como \<var>|:=| tiene lugar en una expresi\'on, a menudo
tendr\'as que ponerla entre par\'entesis para forzar su correcta interpretaci\'on,
como:
\ejemplos
&|IF mem:=New(100)=NIL THEN error()|\cr
\fin
se interpreta como:
\ejemplos
&|IF mem:=(New(100)=NIL) THEN error()|\cr
\fin
y que no es lo que quieres: |mem| debe ser un puntero, no un booleano.
Lo que se debe escribir es:
\ejemplos
&|IF (mem:=New(100))=NIL THEN error()|\cr
\fin
Es una buena costumbre escribir entre par\'entesis cualquier expresi\'on de
asignaci\'on que forme parte de otra, siempre que otras construcciones
como |bla(a:=1)|, |b:=a:=1|,~\dots, no hayan eliminado la ambig\"uedad.

\subsec Secuenciamiento (|BUT|\/).
El operador de secuenciamiento |BUT| permite la escritura de dos expresiones
en una construcci\'on que s\'olo permite una.  A menudo, al escribir
expresiones\b/llamadas a funciones complejas, a uno le gustar\'{\i}a realizar una
segunda cosa sobre la marcha, como una asignaci\'on.

\Ejemplos
\qquad Sintaxis:&\<exp1> |BUT| \<exp2>\cr
\fin
implica: eval\'ua \<exp1>, pero retorna el valor de \<exp2>.

\Ejemplos
Ejemplo:&|mifunc((x:=2) BUT x*x)|\cr
\finsma
\item{} assigna  el  valor  2  a |x| y luego llama a mifunc con |x*x|.
Los |()| entorno a la asignaci\'on son necesarios para impedir
que el operador |:=| tome |2 BUT x*x| como expresi\'on.

\subsec Reserva Din\'amica de Memoria (|NEW|\/).
El operador |NEW| es un poderoso operador para la reserva din\'amica de
memoria.  Supongamos que tenemos en alguna parte de nuestro c\'odigo
|DEF p:PTR TO| \<cualquierobjeto> y |q:PTR TO INT|, entonces:
\ejemplos
&|NEW p|\cr
\fin
es una expresi\'on que reservar\'a memoria para el tama\~no del objeto al que
apunta |p|, y la inicializa con 0.  El puntero resultante se colocar\'a en
|p|, adem\'as de ser el valor de la expresi\'on.  Si |NEW| no puede obtener la
memoria, \'este lanzar\'a una excepci\'on |"NEW"|.  Por lo tanto, |NEW p| es
practicamente equivalente a:
\ejemplos
&|IF (p:=New(SIZEOF cualquierobjeto))=NIL THEN Raise("MEM")|\cr
\fin
con la diferencia de que |p| nunca recibe un valor si se lanza alguna
excepci\'on, y que lo primero es evidentemente una expresi\'on, y no una
sentencia.

\noin Pero incluso hay m\'as: se pueden reservar arreglos din\'amicamente:
\ejemplos
&|NEW p[10]  -> arreglo de 10 objectos|\cr
&|NEW q[a+1] -> arreglo de INT, con tama\~no calculado en ejecucion|\cr
\fin
(esto no funciona al instanciar clases)

\noin Algunas veces el problema de expresiones de lista |[1,2,3]| es que son
est\'aticas, y al usar \'estas para construir estructuras de datos grandes ser\'{\i}a
conveniente crearlas en tiempo de ejecuci\'on.  Se podr\'{\i}a utilizar el
equivalente din\'amico de las listas:
\ejemplos
&|p:=[1,2,3]:cualquierobj        -> estructura estatica|\cr
&|p:=NEW [1,2,3]:cualquierobj    -> !`reservado dinamicamente!|\cr
\fin
Esto funciona tanto con listas como con listas con tipo, y tambi\'en con arreglos:
\ejemplos
&|NEW [1,2,3]       -> lista const, dinam. (nota: !`no como varlista!)|\cr
&|NEW [1,2,3]:obj   -> objeto|\cr
&|NEW [1,2,3]:INT   -> arrreglo de INTs|\cr
\finsma
La liberaci\'on de memoria reservada con cualquiera de las variaciones de
|NEW| se realiza de forma autom\'atica al final del programa, o a mano con
|END| o |FastDispose()|\nota{a excepci\'on de cuando se hab\'{\i}a utilizado |NEW|\<lista>,
que necesita |FastDisposeList()|}.

\noin Si usas |NEW [...]:|\<obj>, y el n\'umero de campos es menor que el
que tiene el objeto, se a\~nadir\'an campos |0/NIL/"\0"| o lo que sea.  Esto nos
permite extender los objetos sin tener problemas con reservas como estas.
(f\'{\i}jate en que esto es diferente de las |[...]:|\<obj> est\'aticas)

\noin Cuando usas |NEW| como sentencia, le pueden seguir un n\'umero
indeterminado de punteros, por ejemplo, lo siguente es v\'alido:
\ejemplos
&|NEW a,b.create(),c|\cr
\finsma

\subsec Unificaci\'on (|<=>|\/).
La unificaci\'on permite un estilo de programaci\'on totalmente diferente, y que
te ser\'a familiar si estas acostumbrado a la programaci\'on L\'ogica (ProLog),
ecuacional o funcional (Miranda\b/Gofer\b/Haskell).  La mayor\'{\i}a de nosotros,
cuando usamos estructuras\b/arreglos para lo que sea, obtenemos valores de
ellas por selecci\'on (|.| y |[]|), sin embargo, en esos lenguajes se usa un
patr\'on de concordancias.  En~E:

\<exp> |<=>| \<exp\_uni>

\noin\<exp> puede ser cualquier expresi\'on, aunque en~v3 s\'olo es realmente
\'util si es de alguna manera un puntero a una lista.  \<exp\_uni> es el
patr\'on que se usa para hacer que concuerde (o unifique) \<exp>, las
variables toman sus respectivos valores.  Si algo no concuerda, ninguna
variable toma valor y la expresi\'on tiene como resultado |FALSE|\null{}.  En otro
caso |TRUE|.
\Ejemplos
Ejemplo:&|a:=[1,2,3]|\cr
        &| ....|\cr
        &|IF a <=> [1,x,y] THEN ...|\cr
\finsma
Esto tendr\'a \'exito con |x=2| e |y=3|.  Si la lista tuviera otra longitud que
no fuera 2, la unificaci\'on tambi\'en fallar\'{\i}a.  El echo de que |a| sea una lista
es algo de lo que deber\'as asegurarte por t\'{\i} mismo, |EC| simplemente intentar\'a
hacer que \<exp\_uni> encaje con el valor, sea cual sea, que obtenga de \<exp>.
\Ejemplos
Ejemplos |FALSE|:&|a <=> [1,x]     -> longitud de lista erronea|\cr
                 &|a <=> [1,4,x]   -> 4=2 falla|\cr
                 &|'bla' <=> [1,2] -> impredecible (?`caida del sistema?)|\cr
\finsma
Lo divertido de la unificaci\'on en que puedes hacer unificaciones realmente
complejas, y que si tomas el primer campo (u otro) como constante, indicando
el tipo de estructura que representa, tienes una buena forma de tipos
din\'amicos.  !`Y todo el tiempo sin usar punteros!

\noin Un ejemplo m\'as interesante:
\ejemplos
&|[BLA,[1,'burp'],['bla',"bla"]] <=> [BLA,[1,x],y]|\cr
\fin
unifica:
\ejemplos
&|x='burp', y=['bla',"bla"]|\cr
\fin
o incluso:
\ejemplos
&|IF miexp <=> [PLUS,[MUL,a,1],[SUBS,[PLUS,c,d],e]] THEN RETURN a+c+d-e|\cr
\finsma
Puede que sea un ejemplo tonto, pero uno se puede imaginar cosas como esta
en el optimizador de c\'odigo de un compilador.  Es lo mismo que este
fragmento de c\'odigo tradicional:
\begintt
   IF ListLen(miexp)=3
     IF myexp[]=PLUS
       IF ListLen(dummy:=miexp[1])=3
         IF (dummy[]=MUL) AND (dummy[2]=1)
           a:=dummy[1]
           IF ListLen(dummy:=miexp[2])=3
             IF dummy[]=SUBS
               e:=dummy[2]
               IF ListLen(dummy2:=dummy[1])=3
                 IF dummy2[]=PLUS
                   c:=dummy2[1]
                   d:=dummy2[2]
                   RETURN a+c+d-e
                 ENDIF
               ENDIF
             ENDIF
           ENDIF
         ENDIF
       ENDIF
     ENDIF
   ENDIF
\endtt
S\'olo que de una forma un poco m\'as \'optima.  Como ves, hay mucho poder
expresivo entorno a la unificaci\'on comparada con la programaci\'on tradicional
basada en selecci\'on.

\noin De momento, lo \'unico permitido en la unificaci\'on son listas sin tipo,
constantes (enteras), variables y Celdas-LISP\null{}.  En el futuro veremos esto
ampliado a cadenas, listas con tipo\b/objetos, e incluso expresiones.

\subsec Mutaci\'on de punteros (|::|\/).
Cuando escribes una expresi\'on como ``|p|'', donde |p| es un |PTR TO| \<objeto>,
\'este te permite referirte a \'el como tal.  El operador mutador de
punteros te permite cambiar tal tipo en el momento (al vuelo):
\ejemplos
&|DEF p:PTR TO mp      -> puerto de mensajes|\cr
\Esptab
&|p.sigbit             -> accede a el|\cr
&|p::ln.name           -> accede al puntero como si fuera un nodo|\cr
\finsma
Esto es muy \'util para punteros que pueden apuntar a diferentes tipos de
cosas u objetos que forman parte de otros, cuando, por supuesto, s\'olo es
posible una declaraci\'on.

\noin Una segunda forma de uso es en |OBJECT|os que tienen miembros
declarados como |LONG|, que en realidad son punteros.  Puedes darle un tipo
al vuelo para hacer referencia a \'el de todas formas:
\ejemplos
&|miventana.userport::mp.sigbit|\cr
\finsma
Aqu\'{\i} el |OBJECT|o ventana tiene un |userport| definido como |LONG|, por lo que
no podr\'as hacer referencia a \'el normalmente.



\endchapter\saltacap
\beginchapter Cap\'{\i}tulo 5. Sentencias

Como se sugeri\'o en el cap\'{\i}tulo sobre el formato del c\'odigo E, generalmente una
sentencia  se  declara en una l\'{\i}nea propia, aunque se pueden poner varias
sentencias  en  un  misma  l\'{\i}nea  separ\'andolas con un punto y coma, de la
misma  forma que una s\'ola sentencia se puede repartir entre varias l\'{\i}neas
si se finaliza cada una de ellas con una coma ``|,|''.
\Ejemplos
Ejemplos:&|a:=1; WriteF('!`hola!\n')|\cr
         &|DEF a,b,c,d,|\cr
         &|    e,f,g|\cr
\fin
\Ejemplos
Las sentencias pueden ser:&$-$ asignaciones\cr
                          &$-$ condicionales, |FOR| y similares.\cr
                          &$-$ expresiones void\cr
                          &$-$ etiquetas\cr
                          &$-$ instrucciones en ensamblador\cr
\finsma
La coma es el principal caracter para indicar que no quieres finalizar
la sentencia  con el  siguiente cambio  de l\'{\i}nea, aunque  a partir  de la
versi\'on~3, cualquier elemento ({\it token}) que no pueda ir legalmente al final
de una l\'{\i}nea provoca  la continuaci\'on de la sentencia.  Es m\'as, si no han
sido  cerrados  todos  los  |[|  y |(|  de  una sentencia,  \'esta  tambi\'en
continuar\'a en las siguientes l\'{\i}neas.
\Ejemplos
Ejemplos de tales elementos:     &|+ - * / =|\cr
                                 &|< >= <=|\cr
                                 &|:= . <=> ::          -> hay otros, pero|\cr
                                 &|{ [ (                -> estos son los|\cr
                                 &|AND OR BUT THEN IS   -> los mas utiles.|\cr
Ejemplo de c\'odigo entre corchetes:&|a:=[|\cr
                                  &|    [1,2],|\cr
                                  &|    [3,4]|\cr
                                  &|   ]     -> la asignacion finaliza aqui.|\cr
\fin

\subsec Etiquetas y Saltos (|JUMP|\/).
Las  etiquetas son  identificadores de  alcanze global  que incorporan
|:|, como en:\qquad |mietiqueta:|

\noin Se pueden utilizar con instrucciones como |JUMP|,  y para hacer referencia
a  datos  est\'aticos.  Se pueden usar para salir de cualquier tipo de
{\it bucle}\nota{aunque no recomiendo esta t\'ecnica.}, pero no de los procedimientos.
En los programas~E normales se utilizan principalmente con el ensamblador
\hbox{en-l\'{\i}nea}.  Las etiquetas siempre son visibles globalmente.
\Ejemplos
\qquad Sintaxis:&|JUMP |\<etiqueta>\cr
\finsma
Contin\'ua la  ejecuaci\'on en \<etiqueta>.  No es recomendable  usar esta
instrucci\'on, est\'a disponible  para ser utlizada s\'olo en casos  en los que
de otra forma se incrementar\'{\i}a la complejidad del programa.
\Ejemplos
Ejemplo:&|IF seacabo THEN JUMP termina|\cr
        &|/* otras partes del programa */|\cr
\Esptab
        &|termina:|\cr
\fin

\subsec Asiganci\'on (|:=|\/).
La forma b\'asica de asignaci\'on es:
\Ejemplos
\qquad Sintaxis:&\<var>| := |\<exp>\cr
\fin
\Ejemplos
Ejemplos:&|a:=1,  a:=mifunc(),  a:=b*3|\cr
\finsma
En E se pueden asignar varias variables de una vez, cuando \<exp> es
una funci\'on que devuelve varios valores de retorno.

\subsec Mnemot\'ecnicos ensamblador.
El ensamblador en-l\'{\i}nea es una parte real del lenguaje, no necesita
introducirse mediante bloques especiales |"ASM"| o similares, como es normal
en otros lenguajes, y tampoco necesita ensambladores independientes para
ensamblar el c\'odigo.  Esto tambi\'en signifca que obedece las reglas de
sintaxis de~E, etc.

\noin Ejemplo:
\begintt
DEF a,b
b:=2
MOVEQ  #1,D0             /* algunas sentencias de ensamblador */
MOVE.L D0,a              /* a:=1+b  */
ADD.L  b,a
WriteF('a=\d\n',a)       /* y escribira 3 */
\endtt

\subsec Conditionales (|IF|\/).
\Ejemplos
\qquad Sintaxis:&|IF |\<exp>| THEN |\<sentencia>| [ ELSE |\<sentencia>| ]|\cr
\qquad o:       &|IF |\<exp>\cr
         &|  |\<sentencias>\cr
         &|[ ELSEIF |\<exp>|           /* puede haber varios ELSEIF */|\cr
         &|  |\<sentencias>| ]|\cr
         &|[ ELSE ]|\cr
         &|  |\<sentencias>\cr
         &|ENDIF|\cr
\finsma
Construye un bloque condicional.  Se\~nalar que hay dos formas generales
para esta sentencia, una versi\'on de una l\'{\i}nea y la otra de varias.

\subsec Para (|FOR|\/).
\Ejemplos
\qquad Sintaxis:&|FOR |\<var>| := |\<exp>| TO |\<exp>| STEP |\<paso>| DO |\<sentencia>\cr
\qquad o:       &|FOR |\<var>| := |\<exp>| TO |\<exp>| STEP |\<paso>\cr
         &|  |\<sentencias>\cr
         &|ENDFOR|\cr
\finsma
Construye un bloque ``{\sl para}'', f\'{\i}jate en las dos formas generales. \<paso>
puede ser  cualquier constante  positiva o negativa,  excluyendo 0,  y es
opcional.
\Ejemplos
Ejemplo:&|FOR a:=1 TO 10 DO WriteF('\b\n',a)|\cr
\finsma
El cuerpo del |FOR| puede contener sentencias |EXIT|:
\Ejemplos
\qquad Sintaxis:&|EXIT| \<expbool>\cr
\fin
que te permite salir del bucle si \<expbool> es cierta.

\subsec Mientras (|WHILE|\/).
\Ejemplos
\qquad Sintaxis:&|WHILE |\<exp>| DO |\<sentencia>\cr
\qquad o:       &|WHILE |\<exp>\cr
         &|  |\<sentencias>\cr
         &|ENDWHILE|\cr
\finsma
Construye  un  bloque  ``{\sl mientras}'', el cual se repite siempre que \<exp>
sea  |TRUE|\null{}.   F\'{\i}jate en las diferencias entre la versi\'on de una-l\'{\i}nea\b/una-sentencia y la versi\'on
de varias l\'{\i}neas.

\noin |WHILE| tambi\'en puede contener sentencias |EXIT|, como el |FOR|.

\subsec Repite (|REPEAT|\/).
\Ejemplos
\qquad Sintaxis:&|REPEAT|\cr
         &|  |\<sentencias>\cr
         &|UNTIL |\<exp>\cr
\finsma
Construye  un bloque ``{\sl repite-hasta}'' que se ejecutar\'a hasta que
\<exp>|=TRUE|\null{}. (Se\~nalar que el bloque siempre se ejecutar\'a al menos una vez)

\Ejemplos
Ejemplo:&|REPEAT|\cr
        &|  WriteF('?`Estas seguro, seguro de salir del programa?\n')|\cr
        &|  ReadStr(stdout,s)|\cr
        &|UNTIL StrCmp(s,'!`Si, por favor!')|\cr
\finsma

\subsec Bucle (|LOOP|\/).
\Ejemplos
\qquad Sintaxis:&|LOOP|\cr
         &|  |\<sentencias>\cr
         &|ENDLOOP|\cr
\finsma
Construye un bucle infinito.


\subsec Selecci\'on (|SELECT|\/).
\Ejemplos
\qquad Sintaxis:&|SELECT |\<var>\cr
         &|[ CASE |\<exp>\cr
         &|  |\<sentencias>| ]|\cr
         &|[ CASE |\<exp>\cr
         &|  |\<sentencias>| ]   /* cualquier numero de bloques */|\cr
         &|[ DEFAULT|\cr
         &|  |\<sentencias>| ]|\cr
         &|ENDSELECT|\cr
\finsma
Construye  un bloque de selecci\'on.  Se contrastar\'an varias expresiones
con  la  variable, y s\'olo se ejecutar\'a el primer bloque que la satisfaga.
El  bloque por omisi\'on (|DEFAULT|) se ejecutar\'a si la variable no satisface
a ninguna de las expresiones.

\Ejemplos
Ejemplo:&|SELECT caracter|\cr
        &|  CASE 10|\cr
        &|    WriteF('Ejem, he encontrado un cambio de linea\n')|\cr
        &|  CASE 9|\cr
        &|    WriteF('!`Vaya, esto debe ser un tabulador!\n')|\cr
        &|  DEFAULT|\cr
        &|    WriteF('?`Conoces este: "\c" ?\n',caracter)|\cr
        &|ENDSELECT|\cr
\finsma
Adem\'as de el ``|SELECT |\<var>'' de siempre, que trabaja con expresiones en
las sentencias |CASE|, E~tiene un ``|SELECT |\<maxrango>| OF |\<exp>'' que funciona
con  constantes  y/o  rangos  de  constantes  en el |CASE|\null{}.  No s\'olo es m\'as
potente  para  muchas aplicaciones, si no que es mucho m\'as r\'apido para un
n\'umero  de  casos grande (generalmente~|>5|), o si los casos son igualmente
probables.   Sin  embargo  supone  que  todos los |CASE|s caen dentro de un
rango  de  enteros peque\~no desde |0| a $n-1$, donde $n$ es un n\'umero razonable,
por ejemplo |10|, o |255| para caracteres.

\Ejemplos
Ejemplo:&|SELECT 127 OF FgetC(stream)|\cr
        &|  CASE "\n","\b"|\cr
        &|    WriteF('fin de linea\n')|\cr
        &|  CASE "\t"," "|\cr
        &|    WriteF('espacio blanco\n')|\cr
        &|  CASE "0" TO "9"|\cr
        &|    WriteF('Entero\n')|\cr
        &|  CASE "A" TO "Z", "a" TO "z", "_"|\cr
        &|    WriteF('Identificador\n')|\cr
        &|  DEFAULT|\cr
        &|    WriteF('otros caracteres\n')|\cr
        &|ENDSELECT|\cr
\fin
|DEFAULT| se ejecutar\'a no s\'olo para aquellos valores para los que no hay
|CASE|, si no tambi\'en para los que est\'en fuera del rango, (en este ejemplo,
de |128| a |255| y |>255| o |<0|).

\noin Se\~nalar  que la  velocidad tiene  un precio:  ya que  este |SELECT|  usa
una  tabla de  saltos para  acceder  r\'apidamente al |CASE| correcto,  usar\'a
$2*$\<maxrango> bytes, |256| en este ejemplo.


\subsec Incremento (|INC/DEC|\/).
\Ejemplos
\qquad Sintaxis:&|INC |\<var>\cr
         &|DEC |\<var>\cr
\finsma
Es una abreviatura para \<var>|:=|\<var>|+1| y \<var>|:=|\<var>|-1|.  Con la \'unica
diferencia de que las primeras son sentencias y no retornan un valor.


\subsec Expresiones void (|VOID|).
\Ejemplos
\qquad Sintaxis:&|VOID |\<exp>\cr
\finsma
Calcula  la expresi\'on sin poner el resultado en lugar alguno.  S\'olo es
\'util  para  una  sintaxis  m\'as  clara,  ya  que en~E, de todas formas, las
expresiones  se  pueden usar como sentencias sin usar |VOID|\null{}.  Sin embargo,
esto  puede  causar  errores  dif\'{\i}ciles de apreciar, ya que, por ejemplo,
|a:=1|  asigna  el  valor  |1|  a  |a|,  pero |a=1| no resulta en nada como
sentencia.  E~te indicar\'a con una advertencia si eso ocurre.


\subsec Liberaci\'on de memoria (|END|).
|END| es  el complemento de |NEW|\null{}.  Cualquier puntero obtenido con  |NEW| se
debe liberar con ({\bf y s\'olo con}) |END|.
\Ejemplos
\qquad Sintaxis:&|END a|\cr
\qquad o incluso\cr
         &|END a,b,c|\cr
\fin
donde los  argumentos son  |PTR|s a alg\'un  tipo.  |END| libera el
espacio de memoria  al que se est\'a  apuntando, de forma que si  |a| es un
|PTR TO LONG|, s\'olo liberar\'a 4 bytes.  Esto quiere  decir que si reservaste
|a| con |NEW a[NUM]|, lo debes liberar con |END a[NUM]|.

\noin |NEW| acepta de  forma segura  punteros  |NIL|\null{}.  Los punteros tambi\'en  se
vuelven a |NIL| tras su liberaci\'on.

\noin Si |a|  es un |PTR| a  un objeto que es  un instancia de una  clase, |END|
obtendr\'a din\'amicamente  el tama\~no del objeto  que se desea liberar  de la
clase, de forma que si tienes un objeto de clase |b| de 32 bytes, pero el
puntero con el que lo vas a liberar es de una clase base (s\'olo 24 bytes),
|END| liberar\'a correctamente los 32 bytes.  Esto s\'olo funciona con clases.

\noin Puedes imaginar |END p| como una macro de:
\begintt
IF p
  p.end()
  FastDispose(p,p.classobject.virtuallen)
  p:=NIL
ENDIF
\endtt
Se\~nalar que |NEW| y |END| utilizan las funciones |FastNew()| y |FastDispose()|
(descritas en alg\'un otro cap\'{\i}tulo) que trabajan de forma bastante distinta a
como lo hacen |NewR()| y |Dispose()|.



\endchapter\saltacap
\beginchapter Cap\'{\i}tulo 6. Definici\'on\\y declaraci\'on\\de funciones

   Puedes usar |PROC| y |ENDPROC| para agrupar sentencias formando tus
propias funciones.  Tales funciones pueden tener cualquier n\'umero de
argumentos, y varios valores de retorno.
\Ejemplos
\qquad Sintaxis:&|PROC |\<etiqueta>| ( |\<args>|, ... )|\cr
         &|ENDPROC |\<valorretorno>|, ...|\cr
\finsma
Define  un  procedimiento  con  cualquier  n\'umero  de argumentos.  Los
argumentos  son  de tipo |LONG|, u opcionalmente de tipo |PTR TO |\<tipo> y no
necesitan ning\'un tipo de declaraci\'on.  Con |ENDPROC| se denota el final del
procedimiento.  Si no se d\'a un valor de retorno, se retorna 0.

\Ejemplos
Ejemplo:&funci\'on que retorna la suma de dos argumentos:\cr
        &    |  PROC suma(x,y)    /* x e y son variable locales */|\cr
        &    |  ENDPROC x+y       /* retorna el resultado  */|\cr
\esptab
m\'as corto:&|  PROC suma(x,y) IS x+y|\cr
\fin


\seccion Definiciones locales y globales: alcance (|DEF|\/).
Con la sentencia |DEF| puedes definir variables locales adicionales aparte
de aquellas que son argumentos.  La forma m\'as sencilla es con:
\ejemplos
&|DEF a,b,c|\cr
\finsma
que  declara  los  identificadores  |a|,  |b| y |c| como variables de tu funci\'on.
Se\~nalar que tales declaraciones deben estar al pricipio de tu funci\'on.
\Ejemplos
\qquad Sintaxis:&|DEF |\<declaraciones>|, ...|\cr
\fin
declara variables.  Una declaraci\'on tiene una de las siguiente formas:
\item{$-$} \<var> \qquad\qquad (que utilizaremos a partir de ahora.)
\item{$-$} \<var>|:|\<tipo> \qquad\qquad donde \<tipo>|=LONG, |\<identobjeto>,~\dots
\item{$-$} \<var>|[|\<tama\~no>|]:|\<type> \qquad\qquad donde \<tipo>|=ARRAY|, |STRING|, |LIST|

\espacio
Los argumentos de funciones se restringen a tipos b\'asicos.
La declaraci\'on de  un tipo b\'asico  puede tener una inicializaci\'on,  en
la versi\'on actual \'esta debe ser un entero (no una expresi\'on):
\ejemplos
&|DEF a=1,b=2|\cr
\finsma
Un  programa  est\'a  formado  por  un  conjunto  de funciones, llamados
procedimientos, |PROC|s.  Cada procedimiento puede tener variables Locales,
y  el programa como un todo puede tener variables Globales.  Al menos uno
de los procedimientos del programa debe ser el ``|PROC main()|'', ya que \'este
es el m\'odulo en el que comienza la ejecuci\'on.  Un programa sencillo puede
paracerse a:
\begintt
DEF a, b        /* definicion de variables globales */

PROC main()     /* las funciones en orden aleatorio */
  bla(1)
ENDPROC

PROC bla(x)
  DEF y,z       /* posiblemente variables locales propias */
ENDPROC
\endtt

\espacio
Para  resumir,  las  definiciones  locales  son  las  que  se hacen al
comienzo  de  los  procedimientos,  y que s\'olo son visibles dentro de esa
funci\'on.    Las  definiciones  globales  se  realizan  antes  del  primer
procedimiento,  de  tu  c\'odigo fuente, y son visibles globalmente.  Puede
haber variables locales con el mismo nombre que variables globales (y por
supuesto, lo mismo con variables locales de dos funciones diferentes), en
cuyo caso, las variables locales tienen prioridad.


\seccion ENDPROC/RETURN.
Como  se  indic\'o  con  anterioridad,  |ENDPROC| marca  el  final  de la
definici\'on de una funci\'on, y puede retornar un valor.  De forma opcional,
|RETURN|  se  puede  usar  en  cualquier punto de la funci\'on para salir de
ella, y si se usa en |main()| provocar\'a la finalizaci\'on del programa.
\Ejemplos
\qquad Sintaxis:&|RETURN [|\<valorretorno>|]|\cr
\finsma
Ejemplo:
\begintt
PROC obtenrecursos()
  /* ... */
  IF error THEN RETURN FALSE  /* algo fue mal ---> sal y falla */
  /* ... */
ENDPROC TRUE   /* llegamos hasta aqui, entonces retorna TRUE */
\endtt

\espacio
Una versi\'on reducida de la definici\'on de una funci\'on es:
\ejemplos
&|PROC |\<etiqueta>| ( |\<arg>|, ... ) RETURN |\<exp>\qquad (o |IS| en vez de |RETURN|)\cr
\fin
Estas  son  definiciones  de  funciones  que  s\'olo  realizan  peque\~nas
computaciones, como funciones factoriales y parecidas: ({\it one-liners} |:-)|)
\ejemplos
&|PROC fac(n) IS IF n=1 THEN 1 ELSE fac(n-1)*n|\cr
\fin


\seccion Funci\'on |main()|.
El  |PROC| llamado |main| tiene importancia porque es la primera funci\'on
que  se  ejecuta;  se  comporta como las dem\'as funciones, y tambi\'en puede
tener  variables locales.  |main()| no tiene argumentos:  los argumentos de
la  l\'{\i}nea  de  comandos  se  ofrecen  en  la variable de sistema |arg|, y
tambi\'en se pueden analizar con |ReadArgs()|.\nota{funci\'on de |dos.library|.}


\seccion Variables del sistema predefinidas.
Las siguientes variables globales siempre est\'an disponibles en tu programa,
se les llama variables del sistema.
\smallskip
\halign{{\tt#}\hfil&
         \quad\vtop{\parindent=0pt\hsize=24pc\hangindent=0pt\strut#\strut}\cr
arg&Como se dijo antes,  tiene un puntero a un cadena acabada
    en cero, con los argumentos de la l\'{\i}nea de comandos.
    No uses esta variable si prefieres usar |ReadArgs()|.\cr
stdout&Contiene el file-handle  para la salida estandard.  Si tu
       programa fue iniciado desde el Workbench, de forma que no
       hay  salida-de-shell  disponible,   |WriteF()|  abrir\'a  una
       ventana |CON:| para t\'{\i} y pondr\'a su file-handle en esta variable.\cr
stdin&file-handle para la entrada estandard.\cr
conout&Aqu\'{\i}  es  donde se pone el  file-handle,  y la ventana de
       consola se cerrar\'a de forma autom\'atica cuando tu programa
       finalice. (mira en |WriteF()| sobre la utilizaci\'on de estas dos
       variables de forma apropiada.)\cr
execbase,&Estas  cuatro  variables se ofrecen siempre inicializadas con el valor apropiado.\cr
dosbase,\cr
gfxbase,\cr
intuitionbase\cr
stdrast&Puntero al |rastport| standard para usarlo con tu programa,
        o |NIL|\null{}.  La usan las funciones gr\'aficas internas (|Line()|).\cr
wbmessage&Puntero a mensaje recibido si el programa se inici\'o desde
          Wb.  Se puede usar como booleano para detectar si el programa
          se inici\'o desde el Wb,  o para comprobar  cualquier
          argumento  que se seleccion\'o con \<|shift|> junto con el icono
          de la aplicaci\'on.  Mira |WbArgs.e| en directorio  |Src/Args/|
          para ver como utilizar de forma correcta esta variable.\cr
}


\seccion Argumentos por omisi\'on de funciones.
Los  argumentos  por omisi\'on permiten especificar un valor por omisi\'on
para  uno  o  m\'as  argumentos  de una funci\'on,  para el caso en el que la
funci\'on  se  llama  con menos argumentos que par\'ametros.  Por ejemplo, un
procedimiento como:
\ejemplos
&|PROC bla(a,b=1,c=NIL)|\cr
\fin
\ejemplos
se puede llamar con:&  que equivale a:\cr
\qquad| bla(a,b,c)|& |  bla(a,b,c)|\cr
\qquad| bla(a,b)|&   |  bla(a,b,NIL)|\cr
\qquad| bla(a)|&     |  bla(a,1,NIL)|\cr
\finsma
Esto  puede ser  muy  \'util, y  tambi\'en puede  expresar  algo sobre  la
funci\'on del procedimiento, por ejemplo, que la mayor\'{\i}a de las veces se le
llamar\'a  con |NIL|,  as\'{\i} que,  ?`por  qu\'e  no  suprimir ese argumento de  la
llamada por claridad?

\noin Esa tambi\'en es una raz\'on para no sobreutilizar los argumentos por
omisi\'on:  no empieces a dejar fuera valores no esenciales para los
procedimientos por mera pereza, si piensas que un parametro no tiene
realmente un valor por defecto.

\espacio
Para  impedir que  las llamadas  con menos  argumentos sean  amb\'{\i}guas,
s\'olo  pueden declararse  como arguementos  por omisi\'on  los \'ultimos  $0\ldots n$
par\'ametros de un |PROC| de $n$ par\'ametros.  Por ejemplo,\quad|PROC bla(a,b=1,c)| es ilegal
(!`aunque en esos casos siempre puedes reordenar los par\'ametros!).

\espacio
Los  argumentos que  se proporcionan  en  una llamada  se rellenan  de
izquierda a derecha, y los argumentos que falten se a\~naden con argumentos
por omisi\'on seg\'un sea necesario.


\seccion Valores de retorno m\'ultiples.
En E puedes retornar cualquier n\'umero de valores de retorno (m\'ax.~3 en
\E/ por razones de implementaci\'on). ?`C\'omo?
\Ejemplos
\qquad Sintaxis:&|RETURN [|\<exp>|,|\<exp>|,|\<exp>|]|\quad(o |ENDPROC|, por supuesto)\cr
\fin
\Ejemplos
Ejemplo:&|PROC sincos(rad)|\cr
        &|  DEF sin,cos|\cr
        &|  /* cualquier computacion necesaria */|\cr
        &|ENDPROC sin,cos|\cr
\fin
se llama con:
\ejemplos
&|s,c:=sincos(3.14)|\cr
&|s:=sincos(1.00)|\cr
\finsma
Como puedes ver, hay una nueva sentencia de la forma:
\ejemplos
&\<var>|, ... := |\<exp>\cr
\fin
donde \<exp> pr\'acticamente s\'olo tiene sentido como llamada a funci\'on.

\espacio
Se\~nalar dos cosas:
\item{$-$} Tu  decides el  n\'umero de  argumentos que  quieres recibir.  Esto tiene
  sentido  cuando  el primer  valor  de  retorno  es  el pricipal,  y  el
  segundo\b/tercero  representan  informaci\'on   adicional,  que  puede  ser
  importante s\'olo para algunos llamadores.
\item{$-$} Esta forma  es una  {\sl sentencia}.  Esto  significa que  cuando llamas  a
  |sincos()|  como parte  de  otra expresi\'on,  s\'olo se  usa  el primer  (el
  regular) valor de retorno:
\item{} |fun(sincos(1.0))|


\seccion Valores de funci\'on.
Con v3,  tambi\'en  puedes tener  funciones como  valores, y  usar \'estos
l\'{\i}bremente.  Son diferentes de las expresiones entrecomilladas, ya que se
llaman como los procedimientos normales.
\Ejemplos
Ejemplo:&|fun:={miproc}      -> obtener ptr a PROC|\cr
        &|  ....|\cr
        &|fun(1,2,3)         -> aplicar a args, como un PROC normal|\cr
\finsma
Notas:
\item{$-$} Debes  asegurarte de  que el |PROC|  del que tienes  el puntero  tiene el
mismo n\'umero de argumentos que los que le vas a aplicar.  El compilador
no puede comprobar esto por t\'{\i}.
\item{$-$} Peor  tadav\'{\i}a: debes  asegurarte de  que el puntero  es en  realidad un
puntero a |PROC|\null{}.  Hay una advertencia del compilador que te puede ayudar
con esto.



\endchapter\saltacap
\beginchapter Cap\'{\i}tulo 7. Declaraci\'on\\de constantes

\Ejemplos
\qquad Sintaxis:&|CONST |\<declaraciones>|, ...|\cr
\fin
te permite declarar una constante. Una declaraci\'on es como sigue:
\ejemplos
&\<ident>|=|\<valor>\cr
\finsma
Las constantes deben ir en may\'usculas, y el resto del program las trata como \<valor>.

\Ejemplos
Ejemplo:&|CONST MAX_LINEAS=100, ER_NOMEM=1, ER_NOFICHERO=2|\cr
\finsma
No  puedes declarar  constantes  en  t\'erminos de  otras  que se  est\'en
declarando en la misma sentencia |CONST|, debes ponerlas en la siguiente sentencia.

\noin Las declaraciones |CONST|, |ENUM| y |SET| siempre son globales, es decir, no
se pueden declarar constantes locales a un procedimiento.  El mejor lugar
para  poner las declaraciones de constantes es al principio de tu fuente,
aunque |EC| tambi\'en te permite ponerlas entre dos |PROC|s, por ejemplo.


\seccion Enumeraciones (|ENUM|).
Las  enumeraciones  son  un  tipo espec\'{\i}fico de constante al que no es
necesario darle valores, simplemente est\'an en un rango entre $0\ldots n$, siendo
la  primera  $0$.   De  todas  formas,  puedes utilizar |=|\<valor> en
cualquier punto de la enumeraci\'on para cambiar o reiniciar el contador de valores.
\Ejemplos
Ejemplos:&|ENUM CERO, UNO, DOS, TRES, LUNES=1, MARTES, MIERCOLES|\cr
         &|ENUM ER_NOFICHERO=100, ER_NOMEM, ER_NOVENTANA|\cr
\fin


\seccion Conjuntos (|SET|).
Los conjuntos son tambi\'en como  las enumeraciones, con la diferencia de
que en lugar de incrementar el valor ($0,1,2,\ldots$) incrementan el n\'umero de
bit ($0,1,2,\ldots$) resultando  en valores como ($1,2,4,8,\ldots$).  Esto tiene la
ventaja a\~nadida de  que se pueden usar como conjuntos  de banderas, tal y
como dice la palabra clave.

\noin Imag\'{\i}nate un conjunto como el siguiente para describir las propiedades
de una ventana:
\ejemplos
&|SET SIZEGAD,CLOSEGAD,SCROLLBAR,DEPTH|\cr
\fin
entonces, para inicializar una variable con las propiedades |DEPTH| y |SIZEGAD|:
\ejemplos
&|baderasvent:=DEPTH OR SIZEGAD|\cr
\fin
y para incluir una bandera |SCROLLBAR| adicional:
\ejemplos
&|baderasvent:=banderasvent OR SCROLLBAR|\cr
\fin
o para comprobar si alguna o ambas propiedades est\'an activas:
\ejemplos
&|IF banderasvetn AND (SCROLLBAR OR DEPTH) THEN  -> lo que sea|\cr
\fin


\seccion Constantes predefinidas.
Las siguientes son constantes predefinidas que se pueden usar en cualquier momento:
\ejemplos
|TRUE|,|FALSE|     & Representan los valores booleanos (|-1|,|0|).\cr
|NIL|&               (|=0|), el puntero sin incializar.\cr
|ALL|&               Con funciones de cadenas (|StrCopy()|) copia todos los caracteres.\cr
|GADGETSIZE|&        Tama\~no m\'{\i}nimo en bytes de un gadget (|Gadget()|).\cr
|OLDFILE|,|NEWFILE|&Par\'ametros de modo para usar con |Open()|.\cr
|EMPTY|&             Usado con m\'etodos (puede convertirse en palabra clave)\cr
|STRLEN|&            Tiene la longitud de la \'ultima cadena inmediata usada.\cr
&                    Ejemplo:\quad |Write(handle,'!`Hola colegas!',STRLEN)  -> =14|\cr
\fin



\endchapter\saltacap
\beginchapter Cap\'{\i}tulo 8. El Sistema\\de Tipos

   E  no  posee un sistema de tipos (o sistema de tipos de datos) r\'{\i}gido,
como  el  Pascal  o el Modula2, incluso es m\'as flexible que el sistema de
tipos del~C\null{}.  Esto debe tenerse bien en cuenta, junto con la filosof\'{\i}a de
que en~E todos los tipos de datos son iguales:  todos los valores b\'asicos
peque\~nos  como  caracteres,  enteros,~\dots,  tienen el mismo tama\~no de
32~bits,  y  todos los dem\'as tipos de datos, como los arreglos y las cadenas
est\'an  representados  por punteros de 32~bits a ellos.  De esta forma, el
compilador de~E puede generar c\'odigo de una forma muy polim\'orfica.

\espacio
Las (des)ventajas son obvias:
\item{$-$} Menor control por parte del compilador sobre errores tontos.

\espacio
Ventajas:
\item{$-$} Polimorfismo a bajo nivel, crea facilmente potentes funciones gen\'ericas.
\item{$-$} Programaci\'on  flexible :  sin problemas con tipos de valores de retorno
           que no coinciden y sin {\it mutaciones} ni mensajes de error superfluos.
\item{$-$} Sin  errores dif\'{\i}ciles de encontrar al mezclar  tipos de datos de dife
           rentes tama\~nos.

\espacio
Veamos ahora los tipos de datos del lenguaje:

\seccion B\'asico (|LONG/PTR|).
S\'olo  hay  un tipo de variable b\'asico ---no complejo--- en E, el cual es
el tipo |LONG| de 32~bits.  Por ser el tipo por omisi\'on, se declarara con:
\Ejemplos
\qquad Sintaxis:&|DEF a:LONG|\qquad\qquad o simplemente:\quad |DEF a|\cr
\finsma
Este  tipo de  variable puede  contener lo  que se  conoce como  tipos
|CHAR|\b/|INT|\b/|PTR|\b/|LONG| en otros lenguajes.  Una variaci\'on especial de  |LONG| es
el  tipo  |PTR|\null{}.  Este tipo es compatible con |LONG|, con la \'unica diferencia
de que indica a qu\'e tipo apunta el puntero.  Por omisi\'on, el tipo |LONG| se
especifica como |PTR TO CHAR|.

\espacio
\Ejemplos
\qquad Sintaxis:&|DEF |\<var>|:PTR TO |\<tipo>\cr
                &donde \<tipo> es o un tipo simple o uno compuesto.\cr
\fin
\Ejemplos
Ejemplo:&|DEF x:PTR TO INT, mipantalla:PTR TO screen|\cr
\fin
|screen|  es el nombre de un objeto definido en |intuition|\b/|screens.m|.

\espacio
Por ejemplo, si abres tu propia pantalla con:
\ejemplos
&|mipantalla:=OpenS(...) | etc.\cr
\fin
puedes  usar  el puntero |mipantalla| como en |mipantalla.rastport|.  Sin
embargo,  si  no  quieres  hacer  nada  con  la  variable  hasta llamar a
|CloseS(mipantalla)|, puedes declararla simplemente como:
\ejemplos
&|DEF mipantalla|\cr
\finsma
Las   declaraciones   de   variables   pueden  tener  inicializaciones
opcionales, pero s\'olo constantes enteras, no expresiones completas:
\ejemplos
&|DEF a=1, b=NIL:PTR TO textfont|\cr
\fin


\seccion Simple (|CHAR/INT/LONG|).
Los  tipos  simples  |CHAR|  (8bit) e |INT| (16bit) no se pueden usar como
tipos  para  una  variable  b\'asica.\nota{supongo que ya sabes la raz\'on.}  Sin
embargo, se pueden usar como tipo de dato para construir |ARRAY|s de ellos,
definir  punteros  a  ellos,  usarlos  en la definici\'on de |OBJECT|os, etc.
Mira los ejemplos de \'estos \'ultimos.


\seccion Arreglos (|ARRAY|).
Los arreglos de declaran indicando su longitud (en bytes):
\ejemplos
&|DEF b[100]:ARRAY|\cr
\fin
esto  define  un array de 100 bytes.  Internamente |b| es una variable de
tipo |LONG| y un puntero a esa \'area de memoria.

\espacio
El tipo  por omisi\'on de un  elemento de arreglo es  |CHAR|, aunque puede
ser cualquier cosa especificando:
\ejemplos
&|DEF x[100]:ARRAY OF LONG|\cr
&|DEF mismenus[10]:ARRAY OF newmenu|\cr
\fin
donde  |newmenu| es un ejemplo de estructura, llamados |OBJECT|os en~E\null{}.  El
acceso a los arreglos es muy sencillo, con \<var>|[|\<exps>|]|:
\ejemplos
&|b[1]:="a"|\cr
&|z:=mismenus[a+1].mutualexclude|\cr
\finsma
Se\~nalar que el \'{\i}ndice  de un arreglo de tama\~no $n$ se  mueve entre $0$ y
$n-1$, y no  entre $1$ y $n$.  Y tambi\'en que |ARRAY OF |\<tipo> es compatible
con |PTR TO |\<tipo>,  con la \'unica diferencia de que la  variable que es un
|ARRAY| se encuentra inicializada.


\seccion Complejo (|STRING/LIST|).
\item{$-$} Las cadenas (|STRING|), son similares a los arreglos,  aunque se
 diferencian  de  ellos  en  que  s\'olo  se pueden modificar usando funciones de
  cadenas de~E; y en que contienen informaci\'on sobre su longitud, de forma
  que las funciones de cadenas pueden modificarlas de una forma segura, es
  decir:  la cadena nunca puede crecer m\'as all\'a del \'area de memoria en la
  que est\'a.
\itemitem{} Declaraci\'on:\qquad |DEF s[80]:STRING|
\item{} El tipo de datos |STRING| (llamado cadenaE\nota{en realidad {\it estring}.}) es compatible con
  |PTR TO CHAR|, y tambi\'en con |ARRAY OF CHAR|, pero no en sentido opuesto.

\item{$-$} Las |LIST|as se pueden  entender como una mezcla entre |STRING|  y |ARRAY OF LONG|\null{}.
  Es  decir:  esta  estructura  de datos  mantiene  una  lista  de
  variables |LONG| que se puede extender y acortar como los |STRING|s.
\itemitem{} Declaraci\'on:\qquad |DEF x[100]:LIST|
\item{} Una  poderosa incorporaci\'on a este  tipo de  datos es  que tambi\'en  tiene un
  equivalente constante |[]|, de la misma  forma que los |STRING|s tienen |''|.
  Una lista es compatible con |PTR TO LONG|,  y por supuesto |ARRAY TO LONG|,
  aunque no en sentido contrario.


\seccion Compuesto (|OBJECT|).
Los |OBJECT| son como una estructura\b/clase en C/C++ o |RECORD| en Pascal.
\Ejemplos
Ejemplo:&|OBJECT miobj        -> define un estructura de datos|\cr
        &|  a:LONG            -> formada por tres elementos.|\cr
        &|  b:CHAR|\cr
        &|  c:INT|\cr
        &|ENDOBJECT|\cr
\fin
\Ejemplos
\qquad Sintaxis:&|OBJECT |\<nombreobj>\cr
                &|  |\<nombremiembro>| [ : |\<tipo>| ]  -> cualquier numero|\cr
                &|ENDOBJECT|\cr
\fin
donde \<tipo> es uno de los siguientes:
\ejemplos
&|CHAR/INT/LONG/|\<objeto>\cr
&|PTR TO CHAR/INT/LONG/|\<objeto>\cr
&|ARRAY OF CHAR/INT/LONG/|\<objeto>\cr
&(|ARRAY| es abreviatura de |ARRAY OF CHAR|)\cr
\finsma
Al igual que las declaraciones |DEF|, omitir el tipo implica |:LONG|.

\espacio
Destacar  que \<nombremiembro> no necesita ser un identificador \'unico y
puede aparecer en otros objetos.  Hay muchas formas de usar objetos:
\begintt
DEF x:miobj                  -> x es una estrutura
DEF y:PTR TO miobj           -> y es un puntero a la estrutura
DEF z[10]:ARRAY OF miobj

y:=[-1,"a",100]:miobj        -> listas con tipo
IF y.b="a" THEN /* ... */
z[4].c:=z[d+1].b++
\endtt
Los  elementos de los objetos se redondean a tama\~nos pares, y se ponen
en offsets pares:
\ejemplos
&|OBJECT micadena                   -> SIZEOF de micadena es 12|\cr
&|  longitud:CHAR, datos[9]:ARRAY   -> datos empieza con un offset de 2|\cr
&|ENDOBJECT|\cr
\fin
|PTR TO|  es el \'unico  tipo en |OBJECT|os  que puede hacer  referencia a
otros objetos que no hayan sido declarados todav\'{\i}a.

\Espacio
Podr\'{\i}a parecerte interesante echar un vistazo a las caracter\'{\i}sticas
de programaci\'on Orientada a Objetos de los |OBJECT|os.


\seccion Inicializaci\'on.

\item{$1.$} Siempre se inicializan a |NIL|\nota{siempre es mejor escribir  |=NIL|
           en definiciones de variables que se espera que sean |NIL|.}
           \ (u otra cosa si se indica)
\itemitem{$-$}Variables globales
\item{$2.$} Se inicializan a |''| y |[]| respectivamente
\itemitem{$-$} |STRING|s globales y locales
\itemitem{$-$} |LIST|as globales y locales
\item{$3.$} No se inicializan
\itemitem{$-$} variables locales (a no ser que se indique explicitamente)
\itemitem{$-$} |ARRAY|s globales y locales
\itemitem{$-$} |OBJECT|os globales y locales


\seccion Esencia del sistema de tipos de E.
Esta secci\'on intenta  explicar como funciona el sistema de  tipos de~E
desde otra perspectiva.

\Espacio
La  mayor  parte de los problemas que tiene la gente al programar en~E
provienen  de  una  visi\'on  incorrecta  del funcionamiento del sistema de
tipos  de~E\null{}. Por lo general se tiene una idea sobre el funcionamiento de
los   tipos   que   depende   del  lenguaje  de  programaci\'on  usado  con
anterioridad  y se intenta aplicarla a~E, lo que suele ser fatal, ya que~E
es bastante diferente en lo que se refiere a tipos.

\subsec El Sistema de Tipos.
E  es,  en  esencia,  un  lenguaje SIN-TIPOS\null{}.  De hecho, las variables
pueden  tener  un  tipo, aunque s\'olo sirve para indicar la forma de hacer
referencia  a  la  variable cuando se usa como puntero.  En practicamente
todas  las dem\'as construcciones del lenguaje las variables se tratan como
si todas tuvieran el mismo tipo, un valor sin tipo de 32~bits.

\noin En  la  pr\'actica  esto  significa que,  por  ejemplo,  excepto  expresiones
que  con los  operadores  |.|, |[]|  y  |++|,  todos los  operadores
y  funciones  trabajan  con  valores  de  32bits,  independiente  que  si
representan booleanos, enteros, reales o punteros a algo.

\subsec Tipos punteros.
En el sistema de tipos de E s\'olo hay 4 tipos, |PTR TO CHAR|, |PTR TO INT|,
|PTR TO LONG| y |PTR TO |\<objeto>,  donde \<objeto> es el nombre de un |OBJECT|o
definido  con anterioridad.  Cuando una variable (o miembro de un objeto
como  veremos  m\'as  tarde)  se  declara de este tipo, significa que si la
variable contiene un valor que es un puntero legal, esa es la forma de hacer
referencia a ella.

\subsec |LONG|, |ARRAY| etc.
Todos los  dem\'as tipos que podamos  ver en una declaraci\'on  |DEF| no son
tipos reales, ya que  no son m\'as que otras formas de  escribir uno de los
cuatro  anteriores.   Por ejemplo, |ARRAY OF |\<tipo> es otra forma de poner
|PTR TO |\<tipo>,  con la \'unica diferencia de que la primera recibe de forma
autom\'atica  la  direcci\'on  de  un  \'area  de  memoria  en  la  pila que es
suficientemente  grande  como  para  contener los datos para el n\'umero de
elementos especificado entre corchetes.

\noin Esta es una  tabla que muestra todos  los {\sl tipos} de E  en t\'erminos de
los cuatro b\'asicos:
\ejemplos
\qquad |ARRAY OF CHAR|, |ARRAY|, |STRING|, |LONG|&(equivale a)\quad |PTR TO CHAR|\cr
\qquad |ARRAY OF INT|&                            (equivale a)\quad |PTR TO INT|\cr
\qquad |ARRAY OF LONG|, |LIST|&                   (equivale a)\quad |PTR TO LONG|\cr
\qquad |ARRAY OF |\<objeto>, \<objeto>&           (equivale a)\quad |PTR TO |\<objeto>\cr
\finsma
\item{$-$} |LONG | son variables que no est\'an pensadas para ser usadas como puntero,
  por  ejemplo, enteros.  Su equivalencia  con  |PTR TO CHAR|  es  bastante
  l\'ogica,  ya que ambos hablan conceptualemente de cosas que  se miden en
  unidades de 1.  (por ejemplo, |++| tiene el mismo efecto en ambos)
\item{$-$} |LIST| y |STRING|  son lo mismo  que sus equivalentes en  |ARRAY| respecto al
  hecho  de  que  se  incializan  a  un  trozo  de  la  pila,  aunque  su
  representaci\'on  es  algo m\'as compleja para facilitar la comprobaci\'on de
  rango en tiempo de ejecuci\'on (cuando se usan con funciones apropiadas).
\item{$-$} un \<objeto> es equivalente a |[1]:ARRAY OF |\<objeto>.  Ambos  representan
  un |PTR TO |\<objeto> inicializado.

\espacio
Dentro de un |OBJECT| pueden aparecer estas mismas declaraciones, adem\'as
de  |CHAR|  e  |INT|,  y  no se permite declarar |LIST| ni |STRING|, ya que estos
\'ultimos  son  objetos complejos en s\'{\i} mismos, y no pueden formar parte de
un objeto.

\subsec Referencia.
Dado un puntero de alg\'un tipo,
\item{``|[]|''} puede indicar otros elementos  que est\'an ordenados secuencialmente a
     continuaci\'on del  elemento al que  el puntero est\'a apuntando  en ese
     momento.  Se\~nalar  que esto  permite  \'{\i}ndices  tanto positivos  como
     negativos,  y  tampoco se  hacen  suposiciones sobre donde y cuantos
     elementos se han reservado en realidad.
\item{``|++|''} hace que el puntero apunte al siguiente elemento en memoria,  y |--|
     al anterior.  Se\~nalar  que  estos operadores  siempre  act\'uan en  el
     puntero, y nunca sobre el elemento al que apuntan.
\item{``|.|''}  funciona  de  forma  similar a |[]|,  s\'olo que indexa el puntero por
     nombre, es decir, el puntero debe ser un |PTR TO |\<objeto>.

\espacio
|[]| y |.| se pueden concatenar a un puntero |p| en cualquier secuencia,
siempre que se sepa que el valor resultante anterior  es de nuevo de tipo
|PTR TO|.

\noin No  siempre  es  necesario  escribir  una  referencia  como  en  otros
lenguajes.   Por  ejemplo,  si |p| es un |ARRAY OF obj|, en lugar de escribir
|p[indice].miembro|  puedes escribir simplemente |p[indice]|, lo cual resulta
en  la  direcci\'on de ese objeto.  Esto tambi\'en explica porqu\'e |p[].miembro|
equivale  a  |p.miembro|,  ya  que  |p[]| es lo mismo que |p| cuando \'este
apunta a un objeto.


\subsec Sem\'atica de Referencia.
Otro concepto relacionado  con los tipos que hace a~E de alguna forma
diferente  de  otros lenguajes ---y por tanto dificil de entender---  es su
acento  en  la  Sem\'antica  de Referencia en vez de la Sem\'antica de Valor.
Intentar\'e argumentar aqu\'{\i} los benef\'{\i}cios de la primera.

\espacio
Informalmente, Sem\'antica de Referencia significa que los objetos en un
lenguaje  (principalmente  los que  no  son  simples  como los  |LONG|)  se
representan mediante punteros,  mientras que la Sem\'antica de Valor  trata
esos  objetos  como  si  fueran ellos mismos.  Un ejemplo de lenguaje que
s\'olo usa Sem\'antica de Valor es el BASIC, ejemplos de lenguajes que tienen
las  dos  son  lenguajes  del  tipo del C/C++ y del Pascal, y ejemplos de
lenguajes  con  s\'olo  Referencia  son  los  nuevos lenguajes Orientados a
Objetos, lenguajes funcionales como el LISP, y por supuesto~E.

\noin El uso de  Sem\'antica de Referencia no implica estar  ocupado todo el
tiempo con  punteros, es  m\'as, te  preocupar\'as de  ellos con  mucha menos
asiduidad que  en el caso de  lenguajes con sem\'antica mezclada  o el caso
con s\'olo valor,  debido principalmente a que la  mayor\'{\i}a de las estructuras
de datos  no triviales  se reservan  de forma  din\'amica, lo  cual implica
punteros.  El mejor ejemplo  de esto es el LISP,  en  el que  se programa
fuertemente con  punteros sin darse  cuenta.  En~E, uno se puede olvidar
facilmente de que |STRING| es un puntero,  debido a la facilidad con que se
puede pasar entre funciones; en~C son necesarias a veces gran cantidad
de~{\tt \&} cuando en  el equivalente en~E  no se necesitan, y  el equivalente en
Oberon de |bla('hola')|  se parece a |bla(sys.ADR('hola'))| debido  a que las
cadenas no representan un puntero, si no un valor como un todo~\dots



\endchapter\saltacap
\beginchapter Cap\'{\i}tulo 9. Funciones\\Predefinidas

\seccion Entrada/Salida.
\proto{WriteF(cadenaformato,args,...)}
\pproto{PrintF(cadenaformato,args,...)}
Imprime una cadena (que puede contener c\'odigos de formato)  en |stdout|.
Pueden incorporar  un n\'umero ilimitado  de argumentos.  Se\~nalar que, como
las  cadenas de  formato se  pueden  crear din\'amicamente,  no es  posible
cerciorarse de que el n\'umero de argumentos sea correcto.
\Ejemplos
Ejemplos:&|WriteF('!`Hola Mundo!\n') -> cadena con cambio de linea|\cr
         &|WriteF('a = \d \n',a)    -> escribe: "a = 123", si a era 123|\cr
\finsma
NOTA:  si, por ejemplo,  |stdout=NIL|  y tu programa fue iniciado  desde el
Workbench, |WriteF()|  crear\'a una ventana de  salida y pondr\'a el  handle en
|conout| y |stdout|.  Esa ventana se cerrar\'a de forma autom\'atica al salir del
programa despu\'es de que el usuario pulse \<{\rm return}>.  |WriteF()|  es la \'unica
funci\'on  que abre  esta ventana,  de  modo que  si quieres  hacer E/S  en
|stdout|, y  quieres estar seguro  de que |stdout<>NIL|,  haz un |WriteF('')|
como  primera instrucci\'on  de tu  programa  para asegurar  la salida.  Si
quieres  abrir la  ventana  de consola  por t\'{\i}  mismo,  debes hacerlo
poniendo  el handle  de fichero  resultante en  las variables  |stdout| y
|conout|, ya que  de esa forma la ventana se  cerrar\'a de forma autom\'atica
al finalizar el programa.  Si deseas cerrar esa ventana  de forma manual,
aseg\'urate de volver a poner |conout| de nuevo a~|NIL| para indicar a~E que
no hay una ventana de consola para cerrar.

\espacio
|PrintF()| es igual que |Write()|, s\'olo que utiliza E/S con buffers.  Ambas
retornan la longitud de la cadena que se acaba de imprimir.

\proto{Out(handlefich,car)}
\pproto{car:=Inp(handlefich)}
Escriben o  leen un s\'olo byte  a/de alg\'un fichero o |stdout|.  Si |car=-1|
entonces se  alcanz\'o el final del  fichero (|EOF|), o sucedi\'o  alg\'un error.
|Out()| retorna el  n\'umero de bytes que se escribieron  en realidad (si es
distinto de 1 entonces hubo un error).

\proto{long:=FileLength(cadenanombre)}
Determina  la  longitud del fichero que desees leer, y tambi\'en, si tal
fichero existe (retorna |-1| si hubo un error, o el fichero no existe).

\proto{ok:=ReadStr(handlefich,cadenae)}
{\it (mejor mira en el partado sobre ``Cadenas y funciones de cadenas''.)}

\proto{salant:=SetStdOut(nuevostdout)}
\pproto{entant:=SetStdIn(nuevostdin)}
Fija  la   variable  de  salida/entrada   estandard  |stdout|/|stdin|.
Equivale a :
\ejemplos
&|salant:=stdout|\cr
&|stdout:=newstdout|\cr
\fin


\seccion Cadenas y funciones de cadenas.
E tiene el tipo de datos |STRING|\null{}.  Este es una cadena,  que desde ahora
llamaremos  {\sl cadenaE}\nota{Estring.},  que  se puede  modificar  y cambiar  de
tama\~no,  al  contrario  que  las  {\it cadenas} normales,  que  es  como  nos
referiremos aqu\'{\i}  a cualquier secuencia  terminada en cero.  Las cadenasE
son compatibles con  las cadenas, aunque no en sentido  inverso, de forma
que si un argumento necesita una cadena,  podemos pasar cualquiera de las
dos.  Si se necesita una cadenaE,  no uses cadenas normales.
\Ejemplos
Ejemplos:&|DEF s[80]:STRING, n   -> s es una cadenaE de longitud max. 80|\cr
         &|ReadStr(stdout,s)     -> lee entrada desde la consola|\cr
         &|n:=Val(s)             -> recoge un numero de la cadenaE|\cr
         &|-> etc.|\cr
\finsma
Se\~nalar que todas  las funciones de cadenas manejan  de forma correcta
los casos en los que la cadena tiende a ser mayor que su longitud m\'axima:
\ejemplos
&|DEF s[5]:STRING|\cr
&|StrAdd(s,'Esta cadena es mayor de 5 caracteres',ALL)|\cr
&(|s| s\'olo contendr\'a |'Esta '|).\cr
\finsma
Las cadenas tambi\'en\nota{siempre debe comprobarse  si el puntero que retorna
esta funci\'on es |NIL|.} pueden reservarse  din\'amicamente en la memoria del
sistema con  |String()|.

\proto{s:=String(longmax)}
\ejemplos
&|DEF s[80]:STRING|\qquad  equivale a\qquad |DEF s|\qquad seguido de |s:=String(80)|\cr
\fin

\proto{bool:=StrCmp(cadena,cadena,long=ALL)}
Compara dos cadenas.  |long|\nota{|long| es un argumento por omisi\'on.} debe ser el n\'umero de caracteres a comparar,
o  |ALL|  si  queremos comparar la totalidad de la cadena.  Retorna
|TRUE| o |FALSE|.

\proto{StrCopy(cadenaE,cadena,long=ALL)}
Copia  |cadena|  en  |cadenaE|\null{}.  Si |long=ALL| copiar\'a toda la cadena.
Retorna la |cadenaE|

\proto{StrAdd(cadenaE,cadena,long=ALL)}
Igual que |StrCopy()|,  s\'olo que ahora la cadena se  concatena al final.
Retorna la |cadenaE|.

\proto{long:=StrLen(cadena)}
Calcula la longitud de cualquier cadena terminada en cero.

\proto{long:=EstrLen(cadenaE)}
Retorna la longitud de una |cadenaE|.

\proto{max:=StrMax(cadenaE)}
Retorna la longitud m\'axima de una |cadenaE|.

\proto{StringF(cadenaE,cadenafmt,args,...)}
Como  |WriteF()|,  pero  ahora  la salida va a |cadenaE| en vez de |stdout|.
Retorna la |cadenaE|, y su longitud como segundo valor de retorno.
\ejemplos
&|StringF(s,'resultado: \d\n',123)|\qquad en |s| tendremos ``|resultado: 123\n|''\cr
\fin

\proto{RightStr(cadenaE,cadenaE,n)}
Rellena la primera |cadenaE| con los \'ultimos |n| caracteres de la segunda.
Retorna la |cadenaE|.

\proto{MidStr(cadenaE,cadena,pos,long=ALL)}
Copia |long| caracteres (todos si |long=ALL|) desde la posici\'on |pos| de
|cadena| a |cadenaE|\null{}.  Retorna la |cadenaE|.

\Espacio
{\bf Nota importante}: en  todas las funciones relacionadas con cadenas  en las que
se usa una posici\'on de cadena, el primer caracter de la cadena est\'a en la
posici\'on 0, y no 1 como es com\'un en algunos lenguajes como el BASIC.

\proto{valor,leidos:=Val(cadena,leidos=NIL)}
Extrae el valor entero que representa la secuencia de caracteres \ASCII/
de la cadena.  No se tienen en cuenta los espacios\b/tabuladores,~\dots\enspace que le
precedan.  De esta forma  tambi\'en se  pueden  leer  n\'umeros hexadecimales
(|1234567890ABCDEFabcdef|) y binarios (|01|) si van precedidos de  |$| o  |%|
respectivamente.  Un menos  |-| puede indicar un  entero negativo.  |Val()|
tambi\'en retorna el n\'umero de caracteres leidos como segundo argumento, el
cual  debe  pasarse por referencia, o se puede recibir como segundo valor
de retorno.  Si |leidos| es 0 (|valor| ser\'a 0 tambi\'en) entonces la cadena
no conten\'{\i}a un entero, o el valor era muy grande para ponerlo en 32~bits.
|leidos| puede ser |NIL|.

\espacio
Ejemplos de cadenas que se analizan correctamente:
\ejemplos
&|'-12345',  '%10101010',  '  -$ABcd12'|\cr
\fin
Estos otros retornar\'an con |valor| y |leidos| igual a 0:
\ejemplos
&|'', 'hello!'|\cr
\fin

\proto{posbusc:=InStr(cadena1,cadena2,posinicial=0)}
Busca en |cadena1| la aparici\'on de |cadena2|,  probablemente partiendo  de
una posici\'on diferente de~0.  Retorna la posici\'on  en la que se hall\'o la
subcadena, o |-1| en otro caso.

\proto{nuevadircadena:=TrimStr(cadena)}
Retorna la  {\sl direcci\'on} del primer caracter de la cadena que no sea un
espacio, tabulador, etc~\dots

\proto{UpperStr(cadena)}
\pproto{LowerStr(cadena)}
Cambia la cadena de mayusculas o a min\'usculas.  Retorna una cadena.

\espacio
{\bf Nota importante}:  estas funciones cambian el contenido de la |cadena|, por lo
que  s\'olo  pueden  usarse con |cadenasE|, o cadenas que formen parte de los
datos  de  tu programa.  Esto quiere decir concretamente, que si obtienes
la direcci\'on de una cadena con una llamada a una funci\'on del sistema,
primero deber\'as  hacer  |StrCopy()|  a una cadena de tu programa, para
poder usar las funciones.

\proto{ok:=ReadStr(handlefich,cadenaE)}
Lee una cadena (acabada en \ASCII/ 10) de cualquier fichero o de |stdout|.
|ok| contendr\'a |-1| si ocurri\'o un error, o se alcanz\'o el |EOF|.

\noin Es importante que sepas que el contenido de la cadena leida hasta ese
momento sigue siendo v\'alido.  Se\~nalar tambi\'en que, al igual que |Inp()|,
|Out()|,~\dots\enspace esta funci\'on utiliza un estilo de |E/S| sin buffers, y por lo
tanto puede ser lenta.  La funci\'on de la dos.library |FGets()| es una buena
alternativa.

\proto{SetStr(cadenaE,nuevalong)}
Cambia manualmente la  longitud de  la  cadena.  S\'olo  es \'util  cuando
pones  datos  en  una  cadenaE  mediane  una  funci\'on  no  espec\'{\i}fica  de
cadenasE  y  quieres  seguir  utilizandola  como  cadenaE\null{}.  Por  ejemplo,
despu\'es de  usar una  funci\'on que simplemente  pone una  cadena terminada
en  cero   en  la   direcci\'on  de  la   cadenaE,  entonces   puedes  usar
|SetStr(micade,StrLen(micade))| para volverla manipulable  de nuevo.  Si la
cadena  es  demasiado larga,  |SetStr()|  no  har\'a  nada (aunque  eso  debe
evitarse siempre).

\proto{AstrCopy(cadena1,cadena2,tama\~no)}
{\it Array String Copy}  copia |cadena2| en el \'area de  memoria denotado por
|cadena1|.  |cadena1| no suele ser una cadenaE, sino un |ARRAY|\null{}. {\tt tama\~no} es el
n\'umero total de caracteres que puede contener |cadena1|, por ej., si es 5 y
|cadena2='holamundo'|, |cadena1| tendr\'a entonces |'hola'| + terminaci\'on en 0.

\proto{orden:=OstrCmp(cadena1,cadena2,max=ALL)}
{\it Ordered String Compare} retorna  |1|  si  |cadena2>cadena1|, |0|  si  son
iguales y |-1| si es menor.  S\'olo se camparan |max| caracteres.

\espacio
Puede que te sea interesante que heches un vistazo al apartado sobre
``Enlace de cadenas''


\seccion Listas y funciones de listas.
Las listas son como las cadenas,  la \'unica diferencia es que est\'an
formadas por |LONG|s en lugar de |CHAR|s.  Tambi\'en pueden reservarse de forma
global, local o din\'amica.
\begintt
DEF milista[100]:LIST  -> local o global.
DEF a
a:=List(10)            -> dinamica. En este caso, 'a' puede ser NIL.
\endtt
De la misma forma que las cadenas se pueden representar con constantes
en expresiones, las listas tienen equivalentes constantes:
\ejemplos
&|[1,2,3,4]|\cr
\fin
el valor de tales expresiones es un puntero a una lista inicializada.  Una
caracter\'{\i}stica  que  tienen  estas  listas  es  que  pueden  tener partes
din\'amicas, es decir, partes que se completan en tiempo de ejecuci\'on:
\ejemplos
&|a:=3|\cr
&|[1,2,a,4]|\cr
\fin
incluso pueden tener otro tipo que no sea el |LONG| por omisi\'on, como:
\ejemplos
&|[1,2,3]:INT|\cr
&|[65,66,67,0]:CHAR                    -> equivalente a 'ABC'|\cr
&|['topaz.font',8,0,0]:textattr|\cr
&|OpenScreenTagList(NIL,[SA_TITLE,'MiPantalla',TAG_DONE])|\cr
\finsma
Como se ve  en los ejemplos anteriores, las  listas son extremadamente
\'utiles con funciones del sistema:  son compatibles con un |ARRAY OF LONG|,
y las  de objetos  con tipos  se pueden utilizar  en cualquier  lugar que
necesite  una estructura, o arreglo de ellas.  Las funciones de Taglist y
de n\'umero variable de argumentos se pueden utilizar de esta forma.
Sin embargo las funciones de listas  s\'olo funcionan con listas  de |LONG|,
las  listas con  tipos  s\'olo  son convenientes  para  la construcci\'on  de
estructuras de datos complejas y expresiones.

\espacio
Al igual que las cadenas, las listas mantienen cierta jeraqu\'{\i}a:
\ejemplos
&listas var. |->| listas const. |->| arreglos de long/puntero a long\cr
\fin
cuando  una  funci\'on  necesita un arreglo de |LONG|s puedes usar tranquilamente
una  lista  como argumento,  pero si la funci\'on necesita una lista
variable, o una lista constante, entonces no servir\'a un arreglo de LONGs.

\espacio
Es importante  entender el poder  de las listas,  y en  particular las
listas con tipo:  \'estas pueden evitar una buena cantidad  de problemas en
la construcci\'on de pr\'acticamente cualquier estructura  de datos.  Intenta
usar las listas en tus propios programas, y observa la funci\'on que tienen
en los programas de ejemplo.

\espacio
\Ejemplos
Resumen:\cr
\qquad\qquad|[|\<elem>,\<e>,...| ]|        &lista inmediata (|LONG|s, con funcs. de listas)\cr
\qquad\qquad|[|\<elem>,\<e>,...| ]:|\<tipo>&lista con tipos (para crear estruct. de datos)\cr
\fin
Si \<tipo>  en un tipo simple  como |INT| o  |CHAR|, lo que obtienes  es un
equivalente inicializado de un |ARRAY OF |\<tipo>, si \<tipo> es un nombre de
objeto, estar\'as construyendo objetos  inicializados, o |ARRAY OF |\<objeto>,
dependiendo de la longitud de la lista.

\espacio
Si escribes\quad |[1,2,3]:INT|\quad crear\'as una estructura de 6~bytes,  de
3~valores de 16~bits  para ser m\'as preciso.  El valor de esta expresi\'on es,
entonces,  un puntero  a ese  \'area de  memoria.  Lo mismo ocurre  si, por
ejemplo, tienes un objeto como este:
\ejemplos
&|OBJECT miobjeto|\cr
&\qquad|a:LONG, b:CHAR, c:INT|\cr
&|ENDOBJECT|\cr
\fin
escribir\quad |[1,2,3]:miobjeto|\quad implicar\'a  la  creaci\'on  de una estructura de
datos  en memoria de 8~bytes, siendo los cuatro primeros bytes un |LONG| de
valor~1,  el siguiente byte un |CHAR| de valor~2, luego un byte relleno, y
los dos \'ultimos un |INT| (2bytes) de valor~3.  Tambi\'en podr\'{\i}as escribir:
\ejemplos
&|[1,2,3,4,5,6,7,8,9]:myobject|\cr
\fin
y  estar\'{\i}as  creando  un |ARRAY OF miobjeto| de tama\~no~3.  F\'{\i}jate que tales
listas  no tienen porqu\'e ser completas (con 3,6,9,\dots\enspace elementos),  puedes
crear objetos parciales con listas de cualquier tama\~no.

\espacio
Un \'ultimo  apunte sobre  el tama\~no  de los datos:  en el  Amiga puedes
depender del hecho de que una  estructura como |miobjeto| tiene un tama\~no
de 8~bytes,  y que tiene un byte de  relleno para obtener  alineaci\'on de
palabras (16~bit). Sin embargo, es bastante probable que un compilador de~E
para  arquitecturas |80x86| no  usar\'{\i}a el byte  de relleno y  crear\'{\i}a una
estructura de  7~bytes, y  que un compilador  de~E para  una arquitectura
|sun-sparc|,  si no  me equivoco,  intentar\'{\i}a alinear  los datos  a palabras
dobles  (32~bits),  creando  una estructura  de~10  o  12~bytes.  Algunos
microprocesadores  (son raros,  pero existen)  incluso usar\'{\i}an  (|36:18:9|)
como  n\'umero de  bits para  sus tipos  (|LONG:INT:CHAR|), en  lugar de  los
(|32:16:8|) a  los que  estamos habituados.  Con esto  quiero decir  que no
hagas  muchas suposiciones  sobre la  estructura  de los  |OBJECT|os y  las
|LIST|as si  quieres escribir  c\'odigo que tenga  alguna oportunidad  de ser
portable y que no dependa de efectos laterales.

\proto{ListCopy(listavar,lista,num=ALL)}
Copia |num| elementos de |lista| a |listvar|.  Retorna |listavar|.
\Ejemplos
Ejemplo:&|DEF milista[10]:LIST|\cr
        &|ListCopy(milista,[1,2,3,4,5],ALL)|\cr
\fin

\proto{ListAdd(listavar,lista,num=ALL)}
Copia |num| elementos de |lista| en la cola de |listavar|. Retorna |listavar|.

\proto{ListCmp(lista,lista,num=ALL)}
Compara dos listas, o una parte de ellas.

\proto{long:=ListLen(lista)}
Retorna la longitud de |lista|, ej: |ListLen([a,b,c])| retornar\'{\i}a 3.

\proto{max:=ListMax(listavar)}
Retorna la longitud m\'axima posible de |listavar|.

\proto{valor:=ListItem(lista,indice)}
Opera como\quad |value:=list[indice]|\quad con la diferencia de que |lista|
puede ser un valor constante en vez de un puntero.  Esto es bastante \'util
en situaciones  como  la siguiente  en  la que queremos usar una lista de
valores directamente:
\ejemplos
&|WriteF(ListItem(['!`vale!','!`sin mem!','!`no fichero!'],error))|\cr
\fin
que imprime un mensaje de error dependiendo de |error|.  Equivale a:
\ejemplos
&|DEF temp:PTR TO LONG|\cr
&|temp:=['!`vale!','!`sin mem!','!`no fichero!']|\cr
&|WriteF(temp[error])|\cr
\finsma

\proto{SetList(listavar,nuevalong)}
Cambia la longitud de la lista de forma manual.  S\'olo ser\'a \'util cuando
leas informaci\'on en la lista con una  funci\'on  que no sea espec\'{\i}fica para
listas, y quieres seguir utilizandola como una lista de verdad.

\Espacio
Puede que te resulte interesante, mirar las funciones de listas con expresiones
entrecomilladas as\'{\i} como las funciones de enlace de listas.


\seccion Intuition.
\proto{ptrv:=OpenW(x,y,ancho,alto,IDCMP,wflags,tit,pant,sflags,gads,tagl=NIL)}
Crea una ventana  donde |wflags| son los flags de  caracter\'{\i}sticas de la
ventana (como  |BACKDROP|, |SIMPLEREFRESH|,~\dots, generalmente |$F|)  y |sflags| son
los que indican el tipo de pantalla en la que se abrir\'a la ventana (1=wb,
15=propia).  Si |sflags=15| entonces es necesario que  |pant| sea un puntero v\'alido,
en  otro  caso  sirve  |NIL|\null{}.  |gads|  puede  apuntar  a una
estrutura |glist| que  puedes crear f\'acilmente con la  funci\'on |Gadget()|, en
otro caso |NIL|.

\proto{CloseW(ptrv)}
Cierra la ventana de nuevo.  La \'unica diferencia  con |CloseWindow()| es
que acepta punteros |NIL|, y que vuelve a poner |stdrast| a |NIL|.

\proto{ptrp:=OpenS(ancho,alto,planos,sflags,titulo,taglist=NIL)}
Crea una pantalla propia.  |planos|=n\'umero de bitplanes (|1-6|, \'o |1-8| en AGA).

\proto{CloseS(ptrp)}
Igual que |CloseW()|, s\'olo que para pantallas.

\proto{buffersig:=Gadget(buffer,listag,id,flags,x,y,ancho,cadena)}
\pproto{{\it Atenci\'on: esta funci\'on est\'a un poco anticuada.}}
Esta funci\'on  crea una lista  de gadgets,  los cuales se  pueden luego
incluir  en  t\'u  ventana  pas\'andola  como  argumento  a  |OpenW()|,  o
posteriormente con funciones de Intuition como |AddGlist()|.

\noin |buffer| es por lo general un |ARRAY|  de al menos |GADGETSIZE| bytes para
mantener todas  las estructuras asociadas  con un gadget, |id|  es n\'umero
identificador que nos ayudar\'a a  recordar el gadget pulsado cuando llegue
un IntuiMessage.  |flags| puede ser: 0=gadget normal, 1=gadget booleano,
3=gadget booleano seleccionado.  |ancho| es el ancho en  pixels,  y  debe
ser lo  suficientemente grande como para acoger |cadena|, la  cual estar\'a
centrada autom\'aticamente.  |listag| debe ser |NIL| para el primer gadget, y
varlistag para todos los dem\'as, para que~E pueda enlazar los gadgets.

\noin La funci\'on retorna un puntero al siguente buffer (|=buffer+GADGETSIZE|).

\noin Ejemplo para tres gadgets:
\begintt
CONST MAXGADGETS=GADGETSIZE*3
DEF   buf[MAXGADGETS]:ARRAY, sigui, ptrv

sigui:=Gadget(buf,NIL,1,0,10,20,80,'bla')   -> el 1er gadget
sigui:=Gadget(sigui,buf,... )
sigui:=Gadget(sigui,buf,... )               -> enlaza gadgets
ptrv:=OpenW( ...,buf)
\endtt

\proto{codigo:=Mouse()}
Retorna el  estado actual  de los  2 o 3  botones del  rat\'on; izqdo=1,
dcho=2  y  central=4.  Si, por  ejemplo,  codigo=3  querr\'a decir  que  se
pulsaron los botones izquierdo y derecho a la vez.

\espacio
{\bf Importante}: Esta  no es una funci\'on  real de Intuition,  si quieres conocer los
eventos  del  rat\'on de  una  forma  correcta,  tendr\'as que  analizar  los
|IntuiMessage| que  reciba tu ventana.  Esta es la  \'unica funci\'on de~E que
utiliza el  hardware directamente,  y por tanto s\'olo es  aconsejable para
programas  de  tipo demo,  o  para  pruebas.  ({\bf No  uses esta  funcion  en
programas que se supone van a funcionar bajo el SO}).

\proto{bool:=LeftMouse(ven)}
\pproto{WaitLeftMouse(ven)}
Alternativa de Intuition a |Mouse()|, comprueban la pulsaci\'on del rat\'on.

\proto{x:=MouseX(ven)}
\pproto{y:=MouseY(ven)}
Permite leer la posici\'on del rat\'on.  Coordenadas relativas a la ventana |ven|.

\proto{clase:=WaitIMessage(ventana)}
Esta funci\'on hace m\'as f\'acil la espera de un evento de ventana.  Espera
la llegada de un |IntuiMessage| y retorna la clase del evento. Guarda otros
datos como |codigo| y |calificadores| en variables globales privadas, que
pueden leerse con las siguientes funciones.  |WaitIMessage()|  equivale  al
siguiente fragmento de c\'odigo:
\begintt
PROC waitimessage( ven:PTR TO window )
  DEF puerto,mens:PTR TO intuimessage,clase,codigo,calif,diri
  puerto:=ven.userport
  IF (mens:=GetMsg(puerto)) = NIL
    REPEAT
      WaitPort(puerto)
    UNTIL (mens:=GetMsg(puerto)) <> NIL
  ENDIF
  clase:=mens.class
  codigo:=mens.code             /* almacenado internamente */
  calif:=mens.qualifier
  diri:=mens.iaddress
  ReplyMsg(mens)
ENDPROC clase
\endtt
como  puedes  ver,  recoge  exactamente  un  mensage,  y  no se olvida de
m\'ultiples  mensajes que llegan en el mismo evento, si se llama m\'as de una
vez.   Digamos, por ejemplo, que has abierto una ventana que muestra algo
y simplemente espera a que la cierres (s\'olo indicaste |IDCMP_CLOSEWINDOW|):
\ejemplos
&|WaitIMessage(miventana)|\cr
\fin
o  puedes  tener  un  programa  que  espere por m\'as tipos de eventos, que
controlar\'{\i}as en un bucle, y finaliza con un evento |CLOSEWINDOW|:
\ejemplos
&|WHILE (clase:=WaitIMessage(ven))<>IDCMP_CLOSEWINDOW|\cr
&|  /* trata otras clases */|\cr
&|ENDWHILE|\cr
\finsma

\proto{codigo:=MsgCode()}
\pproto{calif:=MsgQualifier()}
\pproto{diri:=MsgIaddr()}
Proporcionan  las  variables globales privadas mencionadas antes.  Los
valores   que   retornan   son   los   definidos  durante  la  llamada  a
|WaitIMessage()| m\'as reciente.
\Ejemplos
Ejemplo:&|IF clase:=IDCMP_GADGETUP|\cr
        &|  migadget:=MsgIaddr()|\cr
        &|  IF migadget.userdata=1 THEN ... -> el usuario pulso gadget 1|\cr
        &|ENDIF|\cr
\fin


\seccion Gr\'aficos.
Todas  las funciones  gr\'aficas de  apoyo que  requieren expl\'{\i}citamente
un  rastport   utilizan  la  variable  de   sistema  |stdrast|,  definida
autom\'aticamente en la  \'ultima llamada a |OpenW()| o |OpenS()|,  y que toma el
valor |NIL|  con |CloseW()| y |CloseS()|.  Se puede llamar a  estas dos \'ultimas
funciones  cuando |stdrast|  a\'un  es |NIL|\null{}.  Se  le puede  dar  un valor  a
|stdrast| manualmente con |SetStdRast()| o |stdrast:=mirastport|.

\proto{Plot(x,y,color=1)}
Dibuja un  s\'olo punto en  tu pantalla/ventana  con uno de  los colores
disponibles.  El n\'umero del color va desde |0...31|, o~|0...255| bajo AGA.

\proto{Line(x1,y1,x2,y2,color=1)}
Dibuja una l\'{\i}nea.

\proto{Box(x1,y1,x2,y2,color=1)}
Dibuja un rect\'angulo o caja.

\proto{Colour(dibujo,fondo=0)}
Fija los  colores\nota{las funciones que necesitan un {\it color} cambian el |Apen| de |stdrast|.}
para todas  las funciones gr\'aficas (de  la librer\'{\i}a)
que necesiten  un color como argumento.  Este es el {\sl registro}  del color
(por ejemplo, de |0...31|) y no el {\sl valor} del color.

\proto{TextF(x,y,cadenaformato,args,...)}
Exactamente igual que |WriteF()|, s\'olo que escribe en alg\'un (x,y)  de tu
|stdrast|,  en lugar de hacerlo a |stdout|.  Retorna la longitud de la cadena
resultante.

\proto{rastant:=SetStdRast(rastnuevo)}
Cambia el rastport de salida de las funciones gr\'aficas de E.

\proto{SetTopaz(tama\~no=8)}
Te permite fijar la fuente del rastport |stdrast| a topaz, simplemente
para  asegurarte  de que alguna fuente propia no desfigure la composici\'on
de la ventana.  Por supuesto, |tama\~no| puede ser 8 o 9.  Est\'a para usarse
como \'ultimo recurso si no permites sensibilidad a fuentes.

\proto{SetColour(pantalla,regcolor,r,g,b)}
Fija el registro de color (|0...255|)  de la pantalla a cierto valor {\sc RGB}.
Cada valor de {\sc RGB} puede oscilar entre |0...255|, es decir, color de 24~bits.
Esta  funci\'on reescalar\'a el color de forma autom\'atica si no se dispone de
un modo AGA, utilizando la funci\'on apropiada.


\seccion Sistema.
\vskip-\medskipamount
\proto{bool:=KickVersion(vers)}
Retornar\'a |TRUE|  si el KickStart de la m\'aquina en que est\'a corriendo tu
programa es igual o superior a |vers|, en otro caso |FALSE|.

\proto{mem:=New(n)}
Esto  crea din\'amicamente un arreglo (\'area de memoria, si lo prefieres)
de |n|~bytes.  Se diferencia de |AllocMem()| en que se llama de forma autom\'atica
con flags |$10000| (es decir, memoria inicializada a zero de cualquier
tipo),  y en que no es necesario llamar a |Dispose()|, ya que est\'a enlazada
a una lista de memoria {\sl liberada autom\'aticamente} al finalizar el programa.

\proto{mem:=NewR(n)}
Igual que  |New()|, solo que ahora  alcanza la excepci\'on |"MEM"|  de forma
autom\'atica en lugar de retornar cuando no hay suficiente memoria.

\proto{mem:=NewM(n,flags)}
Igual que |NewR()|, y adem\'as permite especificar flags (|MEMF_CHIP| etc.)

\proto{Dispose(mem)}
Libera memoria reservada con |New()|.  S\'olo es necesaria cuando quieras liberar memoria
de forma expl\'{\i}cita  {\it durante} el programa, ya que, al final del programa se
libera toda la memoria.

\proto{CleanUp(valorret=0)}
Finaliza el programa en cualquier punto.  Substituye al |Exit()|
de  DOS:  !`nunca uses |Exit()|!,  utiliza |CleanUp()| en su lugar,  ya que
libera la memoria, cierra las librerias correctamente,~\dots \enspace |valorret| se
da  al  DOS  como  c\'odigo  de retorno.  S\'olo se necesita |CleanUp()| cuando
hay que finalizar el programa en un punto diferente al |ENDPROC| de |main()|.

\proto{cantidad:=FreeStack()}
Retorna la cantidad de espacio libre que hay en la pila.  Que debe ser
siempre  1000  o superior.  No debes preocuparte de tal cantidad mientras
no utilice recursiones profundas.

\proto{bool:=CtrlC()}
Retorna |TRUE| si se ha pulsado |Ctrl-C| desde la \'ultima comprobaci\'on,  en
otro caso  |FALSE|\null{}.  S\'olo funciona en programas  que se est\'an ejecutando en
una consola, es decir, programas de |CLI|.

\noin Ejemplo de uso de las tres \'ultimas funciones:
\begintt
-> calcular el factorial de un argumento de la linea de comandos
OPT STACK=100000

PROC main()
  DEF num, r
  num:=Val(arg,{r})
  IF r=0
    WriteF('args erroneos.\n')
  ELSE
    WriteF('resultado: \d\n',fac(num))
  ENDIF
ENDPROC

PROC fac(n)
  DEF r
  IF FreeStack()<1000 OR CtrlC() THEN CleanUp(5) -> test extra
  IF n=1 THEN r:=1 ELSE r:=fac(n-1)*n
ENDPROC r
\endtt
por  supuesto,  es  dif\'{\i}cil que esta recursi\'on acabe con el espacio de la
pila,  y si lo hace, el programa se detiene con |FreStack()| tan r\'apido que
no  te  dar\'a  tiempo a pulsar |Ctrl-C|, pero aqu\'{\i} lo que cuenta es la idea.
Una definici\'on de |fac(n)| menos segura ser\'{\i}a:
\ejemplos
&|PROC fac(n) IS IF n=1 THEN 1 ELSE fac(n-1)*n|\cr
\fin

\proto{mem:=FastNew(tama\~no)}
\pproto{FastDispose(mem,tama\~no)}
\pproto{FastDisposeList(lista)}
|FastNew()| y |FastDispose()| substituyen a |NewR(size)| y |Dispose(ptr)| (|NEW|
y |END| los utilizan).  Esto es lo que tienen en com\'un:
\item{$-$} pueden lanzar excepciones |"NEW"|.
\item{$-$} la memoria siempre se inicializa a cero.
\item{$-$} liberaci\'on autom\'atica al final del programa.

\espacio
aunque deben se\~nalarse las siguientes diferencias positivas\nota{con objetos
|<=256| bytes, con mayores se usa |NewR()| y |Dispose()|} :
\item{$-$} son entre 10 y 50 veces m\'as r\'apidas (!)
\item{$-$} usan algo menos de memoria para objetos peque\~nos.
\item{$-$} no fragmentan la memoria.

\espacio
y negativas :
\item{$-$} no liberan la memoria, la reciclan.
\item{$-$} |FastDispose()| necesita tama\~no exacto de la reserva. |END| tambi\'en.

\espacio
Para liberar listas reservadas con |NEW| se necesita utilizar la funci\'on
|FastDisposeList()|.  Dado que las listas tienen longitud, no hace falta el
par\'ametro de tama\~no.


\seccion Matem\'aticas y otras.
\proto{a:=And(b,c)}
\pproto{a:=Or(b,c)}
\pproto{a:=Not(b)}
\pproto{a:=Eor(b,c)}
Estas  funcionan con  las  operaciones usuales,  tanto booleanas  como
aritm\'eticas.  Se\~nalar que existen operadores para |And()| y |Or()|.

\proto{a:=Mul(b,c)}
\pproto{a:=Div(a,b)}
Realizan  la  misma operaci\'on que los operadores |*| y |/|, aunque con
32~bits  completos.   Por razones de velocidad, las operaciones normales
son |16bit*16bit=32bit| y |32bit/16bit=16bit|.  Suficiente para pr\'acticamente
todos los c\'alculos, y si no lo es, puedes usar |Mul()| y |Div()|\nota{en este
caso, |a| se divide entre |b|, y no |b| entre |a|.}.

\proto{bool:=Odd(x)}
\pproto{bool:=Even(x)}

\espacio
Retorna |TRUE| o |FALSE| si la expresi\'on es impar (|Odd()|) o par (|Even()|).

\proto{Min(a,b)}
\pproto{Max(a,b)}
Computan el m\'{\i}nimo y m\'aximo de dos enteros.

\proto{numaleat:=Rnd(max)}
\pproto{semilla:=RndQ(semilla)}
|Rnd()| computa  un n\'umero  aleatorio a partir  de una  semilla interna,
oscilando entre |0...max-1|.  Por ejemplo, |Rnd(1000)| retorna un entero entre
|0...999|.  Para inicializar la semilla interna, llama a  |Rnd()| con un valor
negativo; el |Abs()| de ese valor ser\'a la semilla inicial.

\noin |RndQ()|  computa  un n\'umero  aleatorio  m\'as  r\'apido que  |Rnd()|,  aunque
retorna n\'umeros en  todo el rango de los 32~bits.  Usa  el resultado como
semilla  para  la  siguiente  llamada,  y  como  semilla inicial  utiliza
cualquier valor grande, como |$A6F87EC1|.

\proto{valorabs:=Abs(valor)}
Computa el valor absoluto.

\proto{s:=Sign(v)}
Computa el signo de |v|, es decir, retorna |-1|, |0| o |1|.

\proto{a,b:=Mod(c,d)}
Divide  |c| (32bit)  entre |d|  (16bit)  y  retorna el  m\'odulo |a| (16bit) y
opcionalmente  el resultado  |b| (16bit)  de la  divisi\'on.  |Mod()| retornar\'a
resultados err\'oneos si se excede el l\'{\i}mite de los 16~bits.

\proto{x:=Shl(y,num)}
\pproto{x:=Shr(y,num)}
Desplaza |y| |num| bits a la izquierda o a la derecha (bits nuevos a 0).

\proto{a:=Long(dir)}
\pproto{a:=Int(dir)}
\pproto{a:=Char(dir)}
Mira en  una direcci\'on determinada  de la  memoria y retorna  el valor
encontrado.  Funcionan con valores  de~32, 16  y~8~bits respectivamente.
Se\~nalar  que el  compilador  {\bf no}  comprueba si  |dir|  es una  direcci\'on
v\'alida.  Estas funciones est\'an disponibles  para que se utilicen  s\'olo en
los  casos  en  los  que  la lectura  y  escritura  de  memoria  mediante
|PTR TO |\<type>  har\'{\i}a  el programa  m\'as complejo  o  menos eficiente.  Es
{\bf desaconsejable} el uso de estas funciones.

\proto{PutLong(dir,a)}
\pproto{PutInt(dir,a)}
\pproto{PutChar(dir,a)}
Escribe el valor |a| en memoria.  Mira |Long()|, |Int()| y |Char()|.

\proto{y:=Bounds(x,a,b)}
Asegura que |x| se encuentre entre |a| y |b|, y lo ajusta de forma acorde si
es necesario.  Equivale a:
\ejemplos
&|y:=IF x<a THEN a ELSE IF x>b THEN b ELSE x|\cr
\fin


\seccion Enlace de cadenas y listas.
   E  proporciona un  conjunto de  funciones\nota{estas funciones de cadenas/listas
no tienen nada que ver con las listas-E o las listas Celdas-Lisp} que
permite la  creaci\'on de
listas enlazadas con los tipos de datos |STRING| y |LIST|, o cadenas y listas
creadas con |String()| y |List()| respectivamente.  Como ya  debes saber, las
cadenas  y las  listas,  tipos de  datos complejos,  son  punteros a  sus
respectivos  datos, y  tienen campos  extra en  offsets negativos  de ese
puntero, que indican su longitud y longitud m\'axima actuales.  Los offsets
de los campos son privados (|PRIVATE|).  Todos los tipos de datos complejos
tienen, adem\'as de esos dos,  un campo |next| (siguiente),  inicializado a
|NIL| por  omisi\'on,  y que se  puede usar para  construir listas  o cadenas
enlazadas, por  ejemplo.  Desde  ahora, usar\'e |complejo| para  denotar un
puntero a |STRING| o |LIST|,  y |cola| para denotar otro puntero de ese tipo,
o que ya tenga otras cadenas enlazadas a \'el.  |cola| tambi\'en puede ser un
puntero |NIL|, indicando el final de una lista enlazada. Se pueden usar
las siguiente funciones:

\proto{complejo:=Link(complejo,cola)}
Pone |cola| en el |next| de |complejo|.  Retorna |complejo| de nuevo.
\Ejemplos
Ejemplo:&|DEF s[10]:STRING, t[10]:STRING|\cr
        &|Link(s,t)|\cr
        &crear\'a una lista enlazada como: \quad |s --> t --> NIL|\cr
\fin

\proto{cola:=Next(complejo)}
Lee el campo |next| de |complejo|.  Puede ser |NIL|, o una lista enlzada
completa.  |Next(NIL)| resultar\'a en  |NIL|,  luego es seguro llamar a  |Next()|
cuando no est\'as seguro si estas al final de la lista enlazada o no.

\proto{cola:=Forward(complejo,num)}
Como |Next()|,  s\'olo que adelanta |num| enlaces en lugar de uno,  es
decir |Forward(c,1)| equivale a |Next(c)|.  Puedes utilizar |Forward()| con un
|num| grande de forma segura, |Forward()| se detendr\'a si encuentra |NIL|
mientras recorre los enlaces, y retornar\'a |NIL| en ese caso.

\proto{DisposeLink(complejo)}
Como |Dispose()|, con dos diferencias:  s\'olo sirve para cadenas y listas
reservadas con |String()| o |List()|,  adem\'as liberar\'a el resto de |complejo|
autom\'aticamente.  Se\~nalar tambi\'en  que se puede usar con listas enlazadas
grandes  que contengan tanto cadenas reservadas con |String()| como algunas
reservadas localmente o globalmente con |STRING|.

\espacio
Puede que te interese mirar\enspace |Src/Utils/D.e|\enspace  para ver un  buen
ejemplo  de como se  puede hacer buen uso de listas o cadenas enlazadas
en programas reales.


\seccion Celdas-Lisp y funciones de celdas.
Vaya. Correcto. Pensabas que el LISP era divertido, entonces prueba E.\nota{o la
historia de por qu\'e E es un LISP mejor que el propio LISP |:-)|}

\espacio
   A  partir de  la versi\'on  v3,  E  tiene el  tipo de datos celda,  casi
id\'entico a las celdas del lenguaje LISP\null{}.  M\'as t\'ecnicamente, E~tiene\nota{
``Celdas-Lisp con recogida de residuos con marcas conservadoras e intercambio''}:
\ejemplos
&``Conservative Mark and Sweep Garbage-Collected Lisp-Cells''\cr
\fin

\espacio
B\'asicamente,  implica el ser capaz de reservar celdas-LISP, las cuales
son pares de valores:
\ejemplos
&|x:=<a|\|{}|b>|\cr
\finsma
Lo  cual  se  parece mucho a |NEW [a,b]:LONG|, s\'olo que ahora~E liberar\'a
los  8~bytes  en  cuesti\'on  por s\'{\i} s\'olo cuando se encuentre que necesita
memoria,  y  no  haya  punteros apuntando a la celda.  En la pr\'actica esto
significa  que  puedes  tener  funciones  que crean celdas temporales sin
preocuparse  de liberarlas.  Y, cualquier\nota{este texto no explica
detenidamente como aprovechar las celdas por completo, ya que se han escrito
docenas de libros a ese respecto.} programador de LISP ser\'{\i}a capaz
de explicarte que con celdas puedes construir cualquier tipo de estrutura
de datos (m\'as notablemente \'arboles y listas).

\espacio
La selecci\'on de los valores se puede realizar usando  |Car(x)| y |Cdr(x)|,
dos funciones  de  LISP  que  seleccionan  los elementos  cabeza  y  cola
(primero, segundo) de la celda.  Si |x| es un |PTR TO LONG|, incluso se puede
utilizar |x[0]| y |x[1]|.

\espacio
Tambi\'en se pueden escribir listas de celdas (atento a las comas):

|<a,b,c>| \qquad  como abreviatura de \qquad |<a|\|{}|<b|\|{}|<c|\|{}|NIL>>>|

\espacio
La unificaci\'on de E sirve de alternativa a la selecci\'on |Car()| y |Cdr()|:
\ejemplos
& |x <=> <a,b|\|{}|c>|\cr
& |a+b+c|\cr
\fin
en vez de:
\ejemplos
&|Car(x)+Car(Cdr(x))+Cdr(Cdr(x))|\cr
\finsma
La unificaci\'on de celdas-LISP se parece a la unificaci\'on con listas-E.
Por ejemplo :
\ejemplos
&|x <=> <1,2|\|{}|a>|\cr
\fin
equivale a:
\ejemplos
&|IF Car(x)=1|\cr
&|  IF Car(Cdr(x))=2|\cr
&|    a:=Cdr(Cdr(x))|\cr
&|    ...|\cr
\finsma
Tambi\'en existe el valor nil de LISP (|<>|), que equivale a |NIL| y |0|.

\espacio
   Veamos  algunas funciones  disponibles (se\~nalar  que |Cons()| {\bf solo} se
puede usar por medio de |<...>|)

\proto{h:=Car(c)}
\pproto{t:=Cdr(c)}
Fija el valor de la cabeza y la cola de la celda |c|.

\proto{bool:=Cell(c)}
Indica si |c| apunta a una celda, de forma que |Cell(<1>)=TRUE|,
y |Cell(3.14)=FALSE|\null{}.  No es una funci\'on r\'apida.

\proto{n:=FreeCells()}
   Determina  el n\'umero  de celdas libres disponibles.  Es muy lenta.  No
hay necesidad alguna de llamar a esta funci\'on, si no es por curiosidad.

\proto{SetChunkSize(k)}
Fija el tama\~no  de los bloques reservados para celdas  en |k|~kilobytes.
Por omisi\'on es 128k. Esta funci\'on s\'olo  se puede llamar una  vez, y s\'olo
antes de que tenga lugar la primera reserva constante (|<..>|). A partir de
ese momento esta funci\'on no tiene ning\'un efecto.

\espacio
   Resumiendo, hazte con  un buen libro sobre LISP para  entender bien la
programaci\'on con celdas.

\espacio
   Se pueden escribir funciones de LISP en E, con exactamente la misma
funcionalidad:
\ejemplos
&|PROC append(x,y) IS IF x THEN <Car(x)||append(Cdr(x),y)> ELSE y|\cr
&|PROC nrev(x) IS IF x THEN append(nrev(Cdr(x)),<Car(x)>) ELSE NIL|\cr
&|PROC sum(x) IS IF x THEN Car(x)+sum(Cdr(x)) ELSE 0|\cr
\finsma
Tambi\'en se permite el uso de implementaci\'on destructiva para funciones
como estas.

\Espacio
\subsec Notas t\'ecnicas.
El recolector de residuos (RR) de E implementa un algoritmo de marca e
intercambio conservativo que se ha comprobado  que es entre~5 y~25 veces m\'as
r\'apido  que  las distintas  implementaciones  l\'ogicas  y funcionales  del
Amiga. Conservativo  significa que en  caso de duda,  el~RR no  libera la
celda. Esto es necesario debido a que en un lenguaje sin tipos como el~E,
el~RR podr\'{\i}a  llegar facilmente a un  valor que no es  un puntero v\'alido,
etc.

\noin El RR reserva bloques grandes (por omisi\'on 128k), en los cuales guarda
las celdas. Si se acaban  las celdas, recolectar\'a los residuos analizando
la pila  y los registros en  busca de punteros  al \'area de celdas,  y los
marcar\'a de forma recursiva. Tras eso,  todas las celdas que no hayan sido
marcadas se volver\'an a utilizar, y si la ganancia tras la recolecci\'on fue
peque\~na, se  reservar\'a un  nuevo bloque  (si eso  falla se  alcanzar\'a una
excepci\'on |"NEW"|).

\subsec Interacci\'on con otros valores de E.
\item{$-$} No representa ning\'un problema almacenar otros valores en las celdas.  Se pueden
poner objetos, cadenas, reales, cualquier cosa en celdas  sin confundir
demasiado al~RR.
\item{$-$} S\'{\i} es problem\'atico el almacenar celdas en otros valores, por ejemplo un
  puntero a una celda en un objeto din\'amico,  ya que  el~RR no ser\'a capaz
  de encontrarlo all\'{\i}.  Sin embargo, pienso  que ese caso aparecer\'a raras
  veces.  Los punteros  a celdas  se pueden  guardar de  forma segura  en
  variables  globales  o  locales,  incluso  registros,  y  en  cualquier
  estructura de datos de la pila. (!`y m\'as importante, en otras celdas!)

\subsec Intr\'{\i}nsecos.
\item{$-$} El RR no puede, de momento, recolectar celdas cuya lista-Car  tenga una
  longitud |>1000| o similar, por ejemplo |<<<NIL:a>:b>:c>|,  pero  con  1000
  entradas en vez de~3.  Esto es muy dif\'{\i}cil que ocurra ya que las listas
  de este tipo se suelen formar con \hbox{listas-Cdr}, que el~RR puede controlar
  hasta de tama\~no infinito. (alcanzar\'a una |"STCK"| si eso falla).
\item{$-$} El c\'odigo ensamblador en l\'{\i}nea  no debe poner cosas  en la pila  que no
  est\'en alineadas a 32~bits.  Esto ya era necesario en v2.1b,  pero ahora
  es m\'as imprescindible.

\subsec Resumiendo.
Hay una relaci\'on entre velocidad y espacio  con respecto al  tama\~no de
los bloques.  La reserva de bloques peque\~nos es, obviamente,  interesante
ya que no desperdicia memoria,  sin embargo,  al recolectar residuos,  el
trabajo de control de los punteros es proporcional al n\'umero de espacios.
Por tanto:
\item{$-$} Si  es m\'as importante la velocidad,  ajusta el tama\~no de los bloques de
  forma que s\'olo se necesite un bloque.  Si  el uso m\'aximo de memoria  de
  celdas en cualquier momento es de~50k, un espacio de bloque de~100k~o
  150k ofrecer\'a un rendimiento \'optimo.
\item{$-$} Si lo m\'as importante es la memoria, en el ejemplo anterior un tama\~no de
  bloque de~20k~o  30k ser\'a  bastante \'optimo en cuanto a uso de memoria.
  En resumen,  temporiza  el uso  del algoritmo de celdas  en situaciones
  complicadas para ver la relaci\'on velocidad\b/memoria m\'as apropiada.



\endchapter\saltacap
\beginchapter Cap\'{\i}tulo 10. Funciones\\de biblioteca\\y m\'odulos

Como habr\'as notado en secciones anteriores el fragmento de c\'odigo enlazado
de forma  autom\'atica antes  de tu  c\'odigo, llamado  {\sl c\'odigo de
inicializaci\'on}, siempre abre las tres librer\'{\i}as\nota{N.T.: a lo que me refiero
con librer\'{\i}a es en realidad una {\it biblioteca}, es decir,  una biblioteca
o colecci\'on de funciones.  Lo que pasa es  que debido a  que en ingl\'es se les
llaman libraries  (como debe ser),  parace ser que a uno se le pega m\'as r\'apido
lo de librer\'{\i}a~\dots\enspace|:-(|} |intuition|, |dos| y |graphics|
(y algunas  veces |mathieeesigbas|), y  debido a esto, el  compilador tiene
todas las llamadas a estas  cuatro librer\'{\i}as (incluyendo |exec|) integradas
en el compilador (hay unos cientos  de ellas).  Estas son  hasta la versi\'on~3.00~(v39)
de AmigaDos.  Para llamar al |Open()| de `dos' s\'olo tienes que escribir:
\ejemplos
&|handle:=Open('mifichero',OLDFILE)|\cr
\fin
o para |AddDisplayInfo()| de la librer\'{\i}a |graphics|:
\ejemplos
&|AddDisplayInfo(midispinfo)|\cr
\finsma
Es tan sencillo como eso.



\seccion Interface con el sistema Amiga con los m\'odulos de v39.
Para usar cualquier  otra librer\'{\i}a, a parte de las cinco de la secci\'on
anterior, debes  recurrir a  los m\'odulos.  Igualmente si  deseas utilizar
alg\'una definici\'on de  |OBJECT|o o |CONST| de los includes  del Amiga, como es
normal en~C o ensamblador, tambi\'en necesitar\'as los  m\'odulos.  Los m\'odulos
son  ficheros binarios  que  pueden incluir  definiciones de  constantes,
objetos librer\'{\i}as  y funciones  (c\'odigo).  El hecho de que  sean binarios
tiene la ventaja sobre  el \ASCII/ (como en~C y en  ensamblador), que no es
necesario  compilarlos  una y  otra  vez,  cada  vez  que se  compila  un
programa.   La desventaja es que no se puede leer con tanta facilidad, se
necesita una utilidad como |ShowModule| para ver su contenido.  Los m\'odulos
que contienen las definiciones de librer\'{\i}as  se encuentran en el directorio
raiz  de |EMODULES:|  (el directorio |modules/| en la distribuci\'on), las
definiciones   de   constantes\b/objetos   est\'an   en  los  subdirectorios,
estructurados de la misma forma que los originales de Commodore.
\Espacio

\ejemplos
\qquad Sintaxis:&|MODULE |\<nombrem\'odulo>|, ...|\cr
\finsma
Lee un m\'odulo.  Un m\'odulo es un fichero binario  con informaci\'on sobre
librer\'{\i}as,  constantes,  y a veces, funciones.  El uso de m\'odulos permite
usar librer\'{\i}as y funciones que eran desconocidas por el compilador.

\espacio
   Veamos  un  ejemplo,  una  versi\'on   reducida  del  ejemplo
|source|\b/|Examples|\b/|asldemo.e|,  que usa m\'odulos para obtener  un requester de
ficheros de la |Asl.library|~2.0.
\begintt
MODULE 'Asl', 'libraries/Asl'

PROC main()
  DEF req:PTR TO filerequester
  IF aslbase:=OpenLibrary('asl.library',37)
    IF req:=AllocFileRequest()
      IF RequestFile(req)
        WriteF('Fichero: "\s" in "\s"\n',req.file,req.drawer)
      ENDIF
      FreeFileRequest(req)
    ENDIF
    CloseLibrary(aslbase)
  ENDIF
ENDPROC
\endtt
el  compilador obtiene del m\'odulo |'asl'| las definiciones de funciones
de  |asl|  como  |RequestFile()|,  y  la  variable  global  |aslbase|, que s\'olo
necesita que el programador la inicialize.  De |'libraries/Asl'| obtiene la
definici\'on  del  objeto  |'filerequester'|,  el  cual  se  usa para leer el
fichero que seleccion\'o el ususario.

\espacio
Bueno, ?`Pensabas que era m\'as dif\'{\i}cil tener un requester de ficheros en~E?


\seccion Compilando m\'odulos propios.
A partir  de la  versi\'on v3  puedes agrupar en un solo fuente todos los  |PROC|s, |CONST|s,
|OBJECT|os  y, hasta  cierto punto tambi\'en  las variables  globales, que  te
parezca esten  relacionados entre s\'{\i} de  alguna forma. Utiliza |OPT MODULE| para
indicar  al compilador~EC que ese  fichero se
supone que es un m\'odulo, y luego comp\'{\i}lalo a  un fichero |.m| que se podr\'a usar en
el programa principal, igual que con los dem\'as m\'odulos.

\espacio
Por omisi\'on todos los elementos de un m\'odulo son |PRIVATE|, es decir, no
son accesibles al c\'odigo que importa el fichero |.m|.  Para hacer  visibles
los elementos que quieras, simplemente escribe |EXPORT| antes de ellos:
\begintt
EXPORT ENUM TESTING,ONE,TWO,THREE,FOUR
EXPORT DEF var_global_importante, bla:PTR TO x
EXPORT OBJECT x
  sig, indice, termino
ENDOBJECT
EXPORT PROC burp()
 /* lo que sea */
ENDPROC
\endtt
|EXPORT| es \'util para hacer la distinci\'on entre privado y p\'ublico,
especialmente, cuando se puede acceder a todas las funciones de un objeto
mediante  |PROC|s, puedes desear mantener un |OBJECT|o privado como una forma
efectiva de {\sl ocultamiento de datos}. |EXPORT| puede aparecer en cualquier
l\'{\i}nea, en cuyo caso no afectar\'a a nada.

\noin Si  es necesario  exportar {\sl todos}  los  elementos de  un m\'odulo  (por
ejemplo,  uno  que  s\'olo  tenga constantes), con |OPT EXPORT| se exportr\'a
todo, sin que haga falta utilizar |EXPORT|s individuales.

\noin Las variables globales necesitan una atenci\'on especial:
\item{$-$} Intenta  eludir  muchas variables globales.  El tener muchas  variables
  globales en los m\'odulos hace los proyectos propensos a errores.
\item{$-$} Las variables globales  de  un m\'odulo  no pueden tener inicializaciones
  directas en la sentencia |DEF| (la raz\'on de esto se aclar\'a m\'as tarde). Por ejemplo:
\itemitem{} |DEF a         |\qquad y no\qquad |DEF a=1|
\itemitem{} |DEF a:PTR TO x|\qquad y no\qquad |DEF a[10]:ARRAY OF x|
\item{$-$} Las variable globales  de  un m\'odulo  que  no  se exportan  operan como
  locales  al m\'odulo,  es decir,  nunca  chocar\'an  con globales  de otros
  m\'odulos.   Aquellas exportadas, se combinan con las dem\'as, es decir, si
  se usa una variable con el mismo nombre, tanto en el programa principal
  como  en  m\'odulos, \'esta ser\'a una s\'ola y la misma para los dos.  Este es
  el motivo  de que se pueda escribir |DEF a[10]:ARRAY OF x| en el programa
  principal,  y |EXPORT DEF a:PTR TO x| en  el m\'odulo,  para  compartir  el
  arreglo.  Adem\'as, si ambos usan, por ejemplo, |gadtools.m|, s\'olo uno de
  los  dos  tiene  que  inicializar  |gadtoolsbase| para que ambos puedan
  hacer llamadas a la librer\'{\i}a.  Si no quieres compartir las bases de las
  librer\'{\i}as (es decir, quieres tener una base de librer\'{\i}a local,privada),
  simplemente redecl\'arala en un  |DEF|  de un m\'odulo que no la |EXPORT|e.  Si
  exportas una variable en un m\'odulo de proprosito general,  aseg\'urate de
  que tenga un nombre \'unico.
\item{$-$} El uso  de variables  en  m\'odulos  que proporcionan  tipos de  datos de
  prop\'osito general necesita  de una atenci\'on especial, ya  que el m\'odulo
  puede ser  usado desde  m\'as de un  m\'odulo, en cuyo  caso no  est\'a claro
  quien es el responsable de los recursos.  Ten esto bien en cuenta.

\Espacio
\subsec Uso de m\'odulos dentro de m\'odulos.
Esto requiere una atenci\'on extra. Si  el m\'odulo (B) que incluyes en tu
propio m\'odulo  (A) es uno  que s\'olo  declara |CONST|s, |LIBRARY|s  y |OBJECT|os
(sin c\'odigo)  no sucede nada especial,  sin embargo, si B  incluye |PROC|s,
entonces es obvio  que ese c\'odigo necesita ser enlazado  m\'as tarde con el
programa principal cuando se enlace A\null{}. Por ello, si un programa principal
usa A,  B debe estar presente en la compilaci\'on.  El hecho de que A necesite
a  B se guarda en A, y se puede ver con |ShowModule|.  Esta cadena de
usos  puede  crecer  creando  un  \'arbol  de  dependencias, que tiene como
resultado que aunque s\'olo utilices un m\'odulo en tu programa, se enlazar\'an
a  \'el  de  forma  autom\'atica  unos  cuantos m\'as.  Por ello, el sistema de
m\'odulos  de~E mantiene de forma autom\'atica las dependencias para las que
otros  lenguajes  necesitan  makefiles.   |EC|~tambi\'en permite dependencias
circulares, y lee/enlaza un m\'odulo a lo sumo una vez (es decir, no enlaza
m\'odulos  que  no  se usaron).  Una cosa que el sistema de m\'odulos de E no
realiza  de  forma  autom\'atica  es  recompilar  m\'odulos dependientes.  Si
cambias  B,  a  menudo  ser\'a necesario recompilar A tambi\'en, ya que puede
hacer  referencia  de  offsets, etc, de la versi\'on antigua de B, lo cual
puede provocar que el c\'odigo rompa.  Si esto se empieza a complicar en tu
proyecto, puedes usar una utilidad como |E-Build|.

\noin Prueba el nuevo |ShowModule| para ver lo que pone |EC| en los m\'odulos.

\Espacio
\subsec Inclusi\'on de m\'odulos de otros directorios.
Por  omisi\'on, al nombre del m\'odulo se le pone como prefijo |EMODULES:|
para  obtener  el  fichero en concreto.  Ahora puedes anteponer un |*| al
m\'odulo  para indicar el directorio en el que encuentra el c\'odigo fuente, de
forma que si en el fuente |WORK:E/burp.e| apareciese:
\ejemplos
&|MODULE 'bla', '*bla'|\cr
\fin
el compilador buscar\'{\i}a los m\'odulos |EModules:bla.m| y |WORK:E/bla.m|.

\espacio
   Esta  es,  naturalmente,  la  forma   de  incluir  componentes  de  tu
aplicaci\'on en otras partes.  Si  escribes m\'odulos  que usas en  muchos de
tus  programas,  ser\'{\i}a  bastante  conveniente  guardarlos  dentro  de  la
jerarqu\'{\i}a de |EModules:|,  y el lugar adecuado para esto es el directorio
|EModules:other/|.



\seccion El cach\'e de m\'odulos.
{\it (Se trata en detalle en la seccion sobre |ShowCache/FlushCache|).}



\endchapter\saltacap
\beginchapter Cap\'{\i}tulo 11. Expresiones\\entrecomilladas

Las expresiones entrecomilladas empiezan  con una comilla inversa ``|`|''.
Su  valor  {\bf no}  es el resultado de la computaci\'on de la expresi\'on, sino la
direcci\'on  del  c\'odigo  que la computa.  Este resultado se puede utilizar
como una variable, o como argumento de ciertas funciones. Por ejemplo,
\ejemplos
&|mifunc:=`x*x*x|\cr
\fin
hace que ahora |mifunc| sea un puntero a una {\it funci\'on} que  computa |x^3|  cuando se
eval\'ua.  Estos punteros a funciones  son bastante diferentes de  los |PROC|s
normales, y nunca  se deben mezclar o confundir.  La principal diferencia
de las expresiones entrecomilladas es que s\'olo son expresiones simples, y
por  tanto no  pueden tener  sus  propias variables locales.  En  nuestro
ejemplo, |x| es o una variable global o una variable local.  Ah\'{\i} es donde
debemos tener  precauci\'on:  si evaluamos |mifunc| en alg\'un otro lugar del
mismo |PROC|, |x| puede ser local,  pero si |mifunc| se pasa como par\'ametro a
otro  |PROC|, y luego se eval\'ua, entonces |x| debe ser global.  El compilador
no realiza esta comprobaci\'on por t\'{\i}.


\proto{Eval(func)}
Simplemente eval\'ua la expresi\'on entrecomillada (|exp = Eval(`exp)|).
Debido a que  E  es, de alguna  forma,  un  lenguaje sin tipos,  el
escribir |Eval(x*x)| de forma accidental  en lugar de |Eval(`x*x)| pasar\'a
desapercibido al compilador,  y propiciar\'a muchos problemas  en tiempo de
ejecuci\'on: el valor del |x*x| se usar\'a como un puntero a c\'odigo.

\espacio
Para entender el  motivo por el que  las expresiones entrecomilladas
representan una caracter\'{\i}stica importante piensa en los siguientes casos:
si  quisieras  realizar  una  serie  de acciones en un grupo de variables
diferentes,  normalmente  escribir\'{\i}as  una  funci\'on  y  la  llamar\'{\i}as con
diferentes  argumentos.  Pero, ?`qu\'e ocurre cuando el elemento que quieres
dar como argumento es un fragmento de c\'odigo?  En lenguajes tradicionales
esto  no  ser\'{\i}a  posible, por lo que necesitar\'{\i}as 'copiar' los bloques de
c\'odigo  que  representan la funci\'on, y poner la expresi\'on en ellos.  En~E
no.   Digamos  que  quieres  escribir  un  programa que mida el tiempo de
ejecuci\'on de diferentes expresiones.  En~E simplemente escribir\'{\i}as:
\begintt
PROC mide(func,titulo)
  -> realizar todo tipo de inicializaciones del tiempo
  Eval(func)
  -> y el resto
  WriteF('\s tardo \d en ejecutarse\n',titulo,t)
ENDPROC
\endtt
y luego lo llamas con:
\ejemplos
&|mide(`x*x*x,'multiplicacion')|\cr
&|mide(`calcenorme(),'calculo grande')|\cr
\finsma
En cualquier otro lenguaje imperativo, necesitar\'{\i}as escribir copias de
|mide()|  para  cada  llamada,  o  poner  cada  expresi\'on  en  una  funci\'on
diferente.  Este es un ejemplo sencillo,  piensa en lo que  podr\'{\i}as hacer
con estructuras de datos (|LIST|as) y c\'odigo sin evaluar:
\ejemplos
&|funcsdibu:=[`Plot(x,y,c),`Line(x,y,x+10,y+10,c),`Box(x,y,x+20,y+20,c)]|\cr
\finsma
La idea de usar funciones como variables normales\b/valores no
es  nuevo de~E, las  expresiones entrecomilladas  vienen del
LISP, que adem\'as  tambi\'en tiene las llamadas funciones {\sl Lambda},  de alguna
forma  m\'as  potentes, y  que  tambi\'en  se  pueden  dar como  argumentos  a
funciones.  Las  expresiones entrecomilladas  de~E  se pueden  ver  como
{\sl lambdas} sin par\'ametros (o s\'olo de par\'ametro global).



\seccion Funciones predefinidas.

\proto{MapList(dirvar,lista,listavar,func)}
Aplica una  funci\'on a todos  los elementos de  la lista y  retorna los
resultados en |listavar|.  |func| debe ser una  expresi\'on entrecomillada,
y |var| (que tomar\'a todos los valores de la lista) se dar\'a por referencia.
Retorna |listavar|.

\Ejemplos
Ejemplo:& |MapList({x},[1,2,3,4,5],r,`x*x)   resulta con r: [1,4,9,16,25]|\cr
\fin

\proto{ForAll(dirvar,lista,func)}
Retorna |TRUE| si la funci\'on (expresi\'on entrecomillada) se eval\'ua a |TRUE|
para todos los  elementos de la lista,  y |FALSE| en otro caso.  Tambi\'en se
usa para aplicar una cierta funci\'on a todos los elementos de la lista:
\ejemplos
|ForAll({x},['uno','dos','tres'],`WriteF('ejemplo: \s\n',x))|\cr
\fin

\proto{Exists(dirvar,lista,func)}
Como  |ForAll()|,  s\'olo  que \'esta retorna |TRUE| si para alg\'un elemento la
funci\'on se  eval\'ua a  |TRUE|  (|<>0|).  |ForAll()|  siempre  eval\'ua  todos  los
elementos, pero |Exists()| probablemente no.

\proto{SelectList(v,lista,listavar,exprentrecom)}
Muy parecida a |MapList()|,  s\'olo  que ahora  no guarda el  resultado de
|exprentrecom|, lo  usa como valor booleano,  y s\'olo los valores para los
cuales es cierta se guardan en |listavar|  ---que  debe  poder  guardar el
mismo n\'umero de elementos que |lista|.  Retorna la longitud de |listavar|.

\Ejemplos
Ejemplo:&|SelectList({x},[1,2,0,3,NIl],r,`x<>0)  resulta con r=[1,2,3]|\cr
\finsma
Ejemplo pr\'actico de utilizaci\'on:

\noin Reservamos diferentes tama\~nos de memoria en una sentencia, los comprobamos
a la vez,  y  los liberamos todos de una vez,  pero s\'olo  los que se
pudieron reservar.  (Este ejemplo necesita v37+)
\begintt
PROC main()
  DEF mem[4]:LIST,x
  MapList({x},[200,80,10,2500],mem,`AllocVec(x,0))       -> reservamos
  WriteF(IF ForAll({x},mem,`x) THEN '!`Si!\n' ELSE '!`No!\n') -> ?`exito?
  ForAll({x},mem,`IF x THEN FreeVec(x) ELSE NIL)  -> solo libera <>NIL
ENDPROC
\endtt
F\'{\i}jate en  la ausencia de  iteraci\'on en este c\'odigo.  Intenta escribir
este ejemplo en cualquier otro lenguaje para ver porqu\'e es especial.



\endchapter\saltacap
\beginchapter Cap\'{\i}tulo 12. Los n\'umeros\\Reales

Los n\'umeros reales en E (o FLOATs, como quieras)  son bastante  diferentes de
los de otros lenguajes.  Esto es debido, sobre todo, al hecho de que~E realmente no
discrimina entre tipos de valores.  Te aviso que debes
entender {\bf bien} esta secci\'on antes de intentar usar reales.

\Espacio
En  E un real no es m\'as que otro valor de 32 bits.  El compilador de~E
los trata como si fueran enteros o punteros,  con la diferencia de que su
representaci\'on  interna  significa algo totalmente diferente.  El formato
de los reales en~E es el estandard |IEEEsingle|.

\noin Un valor real es similar a un  entero, con la salvedad de que tiene un
punto en alg\'un lugar.  Por ejemplo, los siguientes son reales v\'alidos:
\ejemplos
&$3.14159\qquad .1\qquad 1.\qquad -12345.6$\cr
\fin
y estos no lo son:
\ejemplos
&$.\qquad 1234$\cr
\fin
(es decir, debe tener al menos un |.| y un caracter |0-9|).

\espacio
Puedes usar estos valores en pr\'acticamente todos lo lugares en los que
es legal un valor |LONG|,  es decir, si tienes una  funci\'on o estructura de
datos que utiliza valores |LONG| cualesquiera, tambi\'en utilizar\'a reales.
\begintt
DEF f=3.14
myobj.x:=.1
fun(f,2.73)
\endtt


\seccion Computaci\'on con reales.
Debido a que los reales son como |LONG|s para E, \'este utilizar\'a con toda
seguridad  la aritm\'etica  de  enteros con  ellos cuando  se  usan en  una
expresi\'on,  lo cual  seguramente no  es lo  que quieres.  Adem\'as, tambi\'en
ser\'{\i}a interesante poder  convertir de enteros a reales y viceversa.  Con
el operador ``|!|'' se puede hacer todo esto.

\espacio
Supongamos  que  en los siguientes  ejemplos  |a|,|b|,|c|  contienen valores
enteros, y que |x|,|y|,|z| contienen valores reales.

\espacio
Por omisi\'on, una expresi\'on en E se considera una expresi\'on entera.  Lo
que hace |!| cuando apararece en una expresi\'on es:
\item{$-$} Cambia la expresi\'on de  entero  a real.  Cualquier operador que le siga
  (|+ * - / = <> > < >= <=|)  realizar\'a  operaciones  con reales.  |!| puede
  aparecer tantas veces como quieras.
\item{$-$} La expresi\'on que aparece antes de |!|,  si hubo alguna, se convierte al
  tipo apropiado.

\espacio
Ejemplos:
\begintt
x:=a!       -> convierte "a" en real, y pone el resultado en x. "a" es
            -> una expresion entera,  que se cambia por real,  lo cual
            -> implica una conversion.
a:=!x!      -> convierte "x" a entero y guarda el resultado en "a".
x:=y        -> aqui no se necesita "!" ya que no es necesario ningun
x:=Ftan(y)  -> operador matematico ni conversion.
x:=!y*z     -> "*" actua sobre 'y' y 'z' como reales porque "!" denota
            -> el todo como expresion real.  El resultado real va a x.
a:=b!*x+y!  -> un ejemplo mas complejo:  el entero 'b' se convierte en
            -> real, luego se multiplica por 'x' (como reales) y se le
            -> suma 'y' (como reales).  El resultado  se  convierte en
            -> entero y se pone en el entero 'a'".
\endtt
\begintt
x:=!y*z-z*y+(a!)+z/z  -> los operadores (+*-/) se computan como reales,
z:=!x*Fsin(!x*y)      -> y el entero 'a'  se convierte a real en algun
                      -> lugar de la expresion. Como ( y ) denotan una
                      -> nueva expresion, tiene su propio estado de !.
                      -> La misma idea para la segunda funcion.
IF !x<0.1 THEN WriteF('!`Valor real demasiado bajo!\n')
-> Como ves "!" tambien sirve para los seis operadores de comparacion.
\endtt



\seccion Funciones de reales predefinidas.
Se incluyen algunas funciones matem\'aticas de transformaci\'on, es
probable que se incluyan m\'as en el futuro.

\proto{Fsin(y)}
\pproto{Fcos(y)}
\pproto{Ftan(y)}
Las funciones |sin()|,~\dots\enspace de siempre.  Funcionan con radianes.

\proto{Fabs(y)}
Computa el valor absoluto de |y| ($\vert y\vert$).

\proto{Ffloor(y)}
\pproto{Fceil(y)}
Computa el entero m\'as pr\'oximo a |y| (menor y mayor respectivamente).

\proto{Fexp(y)}
\pproto{Flog(y)}
\pproto{Flog10(y)}
\pproto{Fpow(y,z)}
\pproto{Fsqrt(y)}
Computa $e^y$, $\ln y$, $\log_{10} y$, $z^y$ y $\sqrt{y}$.

\proto{x,n:=RealVal(s)}
Analiza la cadena  |s|  para producir el valor real  |x|.  No tiene en
cuenta los espacios o tabuladores que lleve delante.  |n| es el n\'umero de
caracteres analizados desde el comienzo de la cadena, o |0| si la cadena no
representa a un valor real.  |x| valdr\'a en ese caso $0.0$.  Acepta  valores
negativos (e incluso n\'umeros sin |.|).
\Ejemplos
Ejemplos:&|RealVal(' 3.14 ')|\qquad resulta $3.14$, $5$\cr
         &|RealVal('blabla')|\qquad resulta $0.0$, $0$\cr
\fin

\proto{s:=RealF(s,x,n)}
Retorna en |s| el valor real |x| como cadenaE,  con |n| decimales.  El
m\'aximo de |n| es |8|,  incluso menos si la parte entera del n\'umero es grande.
Un valor de |n|  igual a |0|  indicar\'a  que no se quiere fracci\'on.  La
cadena se retorna como resultado,  para poder utilizarla en un |WriteF()|.
\Ejemplos
Ejemplo:&|WriteF('real=\s\n',RealF(s,3.14159),4)|\qquad resulta |real=3.1416|\cr
\finsma
|RealF()| se afana en realizar  redondeos razonables para un cierto |n|,
como  muestra  el ejemplo.  Los n\'umeros negativos tambi\'en son tratados de
forma correcta.
\ejemplos
&|RealF(s,-3.14159,0)|\qquad resulta $-3$\cr
\fin



\seccion Notas sobre la implementaci\'on de los reales.
   Como se  dijo antes,  el formato de reales de~ E es el {\sc IEEE} (simple),
esto significa  que el c\'odigo con  reales anterior, que usaba  el formato
{\sc FFP} con las  funciones |SpXxx| se debe reescribir (como  se indicaba en la
documentaci\'on de la v2.1b del compilador).  |EC|~v3.0 ya no apoya directamente
la librer\'{\i}a |mathffp|, y tendr\'as que abrir esta librer\'{\i}a
directamente si quieres usarla.

\espacio
Se eligi\'o {\sc IEEE} simple porque:
\item{$-$} Los {\sc IEEE} dobles no entran en un |LONG|.
\item{$-$} Las rutinas del formato {\sc FFP} no utilizan el |68881| si est\'a presente,  las
  de {\sc IEEE}  s\'{\i}  lo  hacen.   Adem\'as,  el formato {\sc IEEE} es compatible con el
  |68881|, que tambi\'en utiliza el formato {\sc IEEE}.
\item{$-$} {\sc IEEE}  es el formato  estandard  para reales,  reconocido  en  todos los
  lugares,  lo  cual  permite  compatibildad  de ficheros de datos  entre
  software/plataformas.

\espacio
Las  rutinas de  reales  en  E usan  la  mathieeesingbas.library  y la
mathieeesingtrans.library,  las  cuales no  se  ofrec\'{\i}an  con la  antigua
versi\'on~1.3  del  sistema operativo.\nota{se sabe que la v3.1 (v40) del
sistema operativo del Amiga contiene un error en el c\'odigo de {\sc IEEE}.
Usa un |SetPatch| que lo corrija.}  Esto  quiere decir  que si  quieres
escribir bajo\b/apoyar  la~v1.3  del sitema operativo,  y quieres  usar los
reales {\it internos}, debes asegurarte de que esas librer\'{\i}as est\'an presentes
(paracen estar disponibles, ?`quizas por medio de Commodore?).

\noin Tanto  |EC|  como los  programas  que  genera  no abren  esas  librer\'{\i}as
mientras no se usen reales.

\espacio
Si falla todo lo dem\'as, siempre  puedes usar otras librer\'{\i}as de reales
para usar reales bajo~1.3.  Yo recomendar\'{\i}a el m\'odulo |tools/longreal.m|,
el cual usa dobles.

\espacio
   En  un futuro,  es probable  que  |EC| permita  que las  llamadas de  la
librer\'{\i}a |mathieee|  se substituyan por c\'odigo  de |68881| en l\'{\i}nea  de forma
transparente.



\endchapter\saltacap
\beginchapter Cap\'{\i}tulo 13. Manejo\\de Excepciones

El mecanismo de excepciones\nota{en E el t\'ermino {\sl excepci\'on} tiene poco que
ver con  las excepciones  o interrupciones causadas directamente  por los
procesadores |680x0|.} de E  es b\'asicamente igual al del lenguaje
ADA;  proporciona una reacci\'on a los errores en tu  programa, y un manejo
complejo de  recursos.

\espacio
Un manejador  de excepciones es un  fragmento de c\'odigo que  se invoca
cuando sucede un error en tiempo  de ejecuci\'on.  El sistema  en tiempo de
ejecuci\'on, o t\'u mismo,  puedes {\sl se\~nalar} que algo ha ido mal  (esto es lo
que se  llama {\sl lanzar una  excepci\'on}),  y luego el sistema en  tiempo de
ejecuci\'on probar\'a y  buscar\'a el manejador de excepciones apropiado.  Digo
{\it apropiado}  porque  un programa  puede  tener  m\'as  de un  manejador  de
excepciones, en todos los niveles del programa.  La siguiente  puede  ser
la definici\'on de una funci\'on normal (como ya sabemos):
\ejemplos
&|PROC bla()|\cr
&|  /* ... */|\cr
&|ENDPROC|\cr
\fin
mientras que una funci\'on con un manejador de excepciones puede ser:
\ejemplos
&|PROC bla() HANDLE|\cr
&|  /* ... */|\cr
&|EXCEPT|\cr
&|  /* ... */|\cr
&|ENDPROC|\cr
\fin
donde  el bloque entre |PROC| y |EXCEPT| se ejecuta como siempre, y si no hay
ninguna  excepci\'on se salta el bloque entre |EXCEPT| y |ENDPROC|, abandonando
el  procedimiento  en  |ENDPROC|\null{}.   Si  se alcanza alguna excepci\'on, ya sea
dentro  del  procecimiento,  o  en  cualquier  funci\'on  llamada desde ese
bloque, se invocar\'a un manejador de excepciones.



\seccion Uso de la funci\'on |Raise()|.
Hay muchas  formas de {\sl lanzar} una excepci\'on,  la m\'as sencilla  es por
medio de la funci\'on |Raise()|:
\proto{|Raise(IDexcepcion=0)|}
donde \enspace|IDexcepcion|\enspace es  simplemente una constante que define el tipo de
excepci\'on, y lo usan los controladores para determinar lo que fue m\'al.
\begintt
ENUM NOMEM,NOFILE  /* y otros */

PROC bla() HANDLE
  DEF mem
  IF (mem:=New(10))=NIL THEN Raise(NOMEM)
  mifunc()
EXCEPT
  SELECT exception
    CASE NOMEM
      WriteF('!`Sin memoria!\n')
    /* ... y otras */
  ENDSELECT
ENDPROC

PROC mifunc()
  DEF mem
  IF (mem:=New(10))=NIL THEN Raise(NOMEM)
ENDPROC
\endtt

\Espacio
La variable  |exception|  del manejador siempre contiene el  valor del
argumento de la llamada al |Raise()| que lo invoc\'o.

\noin La funci\'on  |Raise()| invoca al manejador  de la funci\'on |bla()|  en ambos
|New()|,  y retorna correctamente al que hab\'{\i}a llamado a |bla()|.  La llamada
|New()| de  |mifunc()| habr\'{\i}a llamado a  su manejador de excepciones  si \'esta
tuviera alguno.  El alcance de un manejador va desde el comienzo del |PROC|
en que  se define  hasta la  palabra clave  |EXCEPT|,  incluyendo todas las
llamadas que se hagan desde el procedimiento.

\espacio
Esto tiene tres consecuencias:
\item{$A.$} Los manejadores se organizan de forma recursiva, y el manejador que se
   invoca se selecciona  dependiendo de las llamadas de  las funciones en
   tiempo de ejecuci\'on.
\item{$B.$} Si  se lanza  una excepci\'on  dentro  de  un manejador,  se  invoca  el
   manejador  de nivel  justamente anterior.  Esta caracter\'{\i}stica  de los
   manejadores  se  puede usar  para  implementar  esquemas complejos  de
   reserva  recursiva de  recursos con  gran facilidad,  (como se ver\'a).
\item{$C.$} Si se lanza una excepci\'on en un nivel en el que no existe un manejador
   de  menor  nivel  (o  en  programas  que  no  tienen  ning\'un  tipo  de
   manejadores), se  finaliza el programa.  (es decir, |Raise(x)|  tiene el
   mismo efecto que |CleanUp(0)|)

\espacio
Veamos otras funciones de manejadores:

\proto{Throw(IDexcepcion,valor)}
Como |Raise()|,  s\'olo que ahora lleva  un valor arbitrario con ellas.  Y
luego  se puede  escrutar  ese  valor en  el  manejador  con la  variable
|exceptioninfo|.

\proto{ReThrow()}
No  tiene argumentos.  Simplemente hace  un  |Throw()| con  el valor  de
excepci\'on actual.  S\'{\i} y solo s\'{\i} es |<>0|



\seccion Definici\'on de excepciones para funciones predefinidas (|RAISE/IF|).
Con lo  que vimos hasta ahora  de las excepciones  ya  tenemos grandes
ventajas  sobre la  forma de  definir  la funci\'on  |error()| de  siempre,
aunque hay  que escribir demasiado para  comprobrar la igualdad a  |NIL| de
cada llamada a |New()|.

\noin El sistema  de manejo  de excepciones  de E  permite la  definici\'on de
excepciones para todas las funciones de~E  (como |New()|, |OpenW()|, etc.), y
para todas  las funciones de Librer\'{\i}a  (|OpenLibrary()|, |AllocMem()|, etc.),
incluso para aquellas que se incluyen como m\'odulos.

\Espacio
\ejemplos
\qquad Sintaxis:&|RAISE |\<IDexception>| IF |\<func> \<comp> \<valor>|, ...|\cr
\fin
la parte que sigue a |RAISE| se puede repetir con una |,|.
\Ejemplos
Ejemplo:&|RAISE NOMEM IF New()=NIL,|\cr
        &|      NOLIBRARY IF OpenLibrary()=NIL|\cr
\fin
la primera l\'{\i}nea quiere decir algo como: {\sl siempre que una llamada a |New()|\/
resulte en |NIL|, lanza autom\'aticamente la excepci\'on |NOMEM|}.  \<comp>  puede
ser cualquiera entre  |= <> > < >= <=|.  Tras esta definici\'on, a lo largo
de nuestros programas podemos escribir:\quad|mem:=New(size)|\quad sin tener  que
escribir\quad|IF mem=NIL THEN Raise(NOMEM)|.

\noin F\'{\i}jate que la  \'unica diferencia es que |mem| nunca  recibe un valor si
el  sistema  invoca  al  manejador:   para cada llamada a |New()| se genera
c\'odigo que comprueba su resultado y llama a |Raise()| si es necesario.

\espacio
   Vamos  a implementar un peque\~no ejemplo que ser\'{\i}a complejo de resolver
sin  manejo  de  excepciones:   llamamos  a una funci\'on recursivamente, y
reservamos  un  recurso  en cada llamada (en este caso se reserva memoria
antes  de  la llamada recursiva, y se libera despu\'es).  ?`Qu\'e ocurre si en
alg\'un  momento  en la recursi\'on ocurre un fallo severo, y tenemos que dar
el programa por terminado?  Cierto, al dejar el programa no podr\'{\i}amos (en
un  lenguaje  convencional)  liberar  todos  los  recursos  reservados en
niveles  de recursi\'on inferiores, debido a que todos los punteros a tales
\'areas de memoria se encuentran en variables locales inalcanzables.  En E,
simplemente  lanzamos una excepci\'on, y lanzamos otra al final del manejador,
llamando de esta forma recursivamente a los manejadores, y liberando
todos los recursos.  Ejemplo:
\begintt
CONST SIZE=100000
ENUM NOMEM  /*, ... */

RAISE NOMEM IF AllocMem()=NIL

PROC main()
  reserva()
ENDPROC

PROC reserva() HANDLE
  DEF mem                 -> veamos cuantos bloques de
  mem:=AllocMem(SIZE,0)   -> memoria se pueden obtener.
  reserva()               -> realiza la recursion.
EXCEPT DO
  IF mem THEN FreeMem(mem,SIZE)
  ReThrow()        -> llama recursivamente a los manejadores.
ENDPROC
\endtt

\espacio
Por  supuesto,  esto  es una simulaci\'on de un problema de programaci\'on
natural,  que  normalmente  es bastante m\'as complejo, y que por ello hace
m\'as evidente la necesidad del manejo de excepciones.  Hecha un vistazo al
c\'odigo  fuente de la utilidad \enspace|D.e|\enspace para ver un programa real de ejemplo,
en el que el manejo de errores se complicar\'{\i}a sin manejo de excepciones.

\espacio
El  |DO|  que  va  despu\'es  de  |EXCEPT| indica que en lugar de saltar a
|ENDPROC|,  el  c\'odigo  principal  simplemente  contin\'ua la ejecuci\'on en el
manejador  cuando  llega  a  ese  punto.   Tambi\'en fija la excepci\'on a~0.
Puede ser \'util si en el manejador liberas recursos locales al |PROC|.



\seccion Uso de |ID| de excepciones.
En  realidad  un  |ID | de  excepci\'on es un valor de 32-bits normal (por
supuesto),  y  puedes  pasar  lo que quieras al manejador de excepciones:
por ej., algunos los usan para pasar cadenas de descripci\'on de errores:
\ejemplos
&|Raise('!`No pude abrir la "gadtools.library"!')|\cr
\finsma
Sin embargo, si quieres usar las excepciones de una forma expandible y
deseas  poder  usar m\'odulos futuros que lanzen excepciones sin definir en
tu programa, sigue las siguientes normas:

\item{$-$} Usa y define el |ID| 0 como {\sl no error} (finalizaci\'on normal).
\item{$-$} Usa los IDs 1-10000 para excepciones espec\'{\i}ficas de tu programa.
  Def\'{\i}nelos como siempre con |ENUM|:
\itemitem{} |ENUM OK,NOMEM,NOFILE, ...|
\itemitem{} (|OK| ser\'a 0, y los dem\'as 1+)
\item{$-$} Los |ID|'s |12336| a |2054847098| (todos formados por letras may\'usculas
  o min\'usculas  y d\'{\i}gitos entre comillas,  y tienen longitud 2, 3 o 4)
  est\'an reservados para  excepciones comunes.  Una excepci\'on com\'un es una
  excepci\'on que no es necesario definir en tu programa,  y  que puede ser
  usada  por los implementadores de m\'odulos (con  funciones)  para lanzar
  excepciones: por ejemplo, si dise\~nas  un conjunto de procedimientos que
  realizan cierta tarea,  puede ser  que desees lanzar excepciones.  Dado
  que podr\'{\i}as  querer usar esas  funciones en varios programas,  no ser\'{\i}a
  pr\'actico tener que coordinar los |ID|s con el programa principal, es m\'as,
  si usas m\'as de un conjunto de funciones (en un m\'odulo, en el futuro)  y
  cada m\'odulo tuviera un identificador  diferente para {\sl sin memoria}, las
  cosas se  har\'{\i}an impracticables.  Ah\'{\i} es  donde  entran las excepciones
  comunes:  el  |ID | com\'un  para  sin-memoria  es  |"MEM"|  (incluyendo  las
  comillas): cada implementador deber\'{\i}a escribir simplemente
\itemitem{} |Raise("MEM")|
\item{} desde cualquier procediemiento, y el programador que use el m\'odulo s\'olo
  necesita proporcionar un manejador de exepciones que entienda |"MEM"|.

\espacio
\item{} Futuros m\'odulos que contengan  conjuntos de funciones especificar\'an las
  excepciones que pueden alcanzar cada uno de esos  procedimientos,  y si
  \'estas  coinciden con  los |ID|s  de  otros procedimientos,  la tarea  del
  programador que tiene  que tratar con excepciones  se ver\'a simplificada
  significativamente.
\Ejemplos
Ejemplos:\cr
(sistema)\cr
\esptab
|"MEM"|&sin memoria\cr
|"FLOW"|&pila (pr\'acticamente) llena\cr
|"STCK"|&recolector de residuos con problemas de pila\cr
|"^C"|&Ruptura por Control-C\cr
|"ARGS"|&args err\'oneos\cr
\esptab
(exec/librerias)\cr
\esptab
|"SIG"|&no se pudo reservar se\~nal\cr
|"PORT"|&no se pudo crear puerto de mensajes\cr
|"LIB"|&library no disponible\cr
|"ASL"|&no asl.library\cr
|"UTIL"|&no utility.library\cr
|"LOC"|&no locale.library\cr
|"REQ"|&no req.library\cr
|"RT"|&no reqtools.library\cr
|"GT"|&no gadtools.library (similar para las dem\'as)\cr
\esptab
(intuition/gadtools/asl/gfx)\cr
\esptab
|"WIN"|&fallo al abrir ventana\cr
|"SCR"|&fallo al abrir pantalla\cr
|"REQ"|&no se pudo abrir requester\cr
|"FREQ"|&no se pudo abrir requester de ficheros\cr
|"GAD"|&no se pudo crear gadget\cr
|"MENU"|&no se pudo crear menu(s)\cr
|"FONT"|&problema obteniendo fuente\cr
\esptab
(dos)\cr
\esptab
|"OPEN"|&no pude abrir fichero/fichero no existe\cr
|"OUT"|&problemas escribiendo\cr
|"IN"|&problemas leyendo\cr
|"EOF"|&fin de fichero no esperado\cr
|"FORM"|&error en formato de entrada\cr
|"SEG"|&problemas con loadseg\cr
\finsma
\item{} La tendencia general es:
\itemitem{*} todas las letras may\'usculas para excepciones generales del sistema,
\itemitem{*} mezcladas para excepciones usadas por m\'as de una aplicaci\'on, pero
    no suficientemente generales,
\itemitem{*} todas min\'usculas para excepciones lanzadas dentro  varios  m\'odulos de
    tu propia aplicaci\'on.

\item{$-$} Todas los dem\'as, (incluyendo los IDs negativos) estan reservados.



\endchapter\saltacap
\beginchapter Cap\'{\i}tulo 14. Programaci\'on\\Orientada\\a Objetos

Las caracter\'{\i}sticas que se describen en esta secci\'on est\'an agrupadas como
tal ya que constituyen lo que generalmente se conoce como los tres
principales componentes esenciales que hacen a un lenguaje 'Orientado a
objetos' (es decir, herencia--ocultamiento de datos--polimorfismo).  Sin
embargo, en~E no son un {\it tema independiente} ya que cada uno de ellos se
puede usar de todas formas junto con otras caracter\'{\i}sticas del~E.


\seccion Herencia de Objetos.
Siempre resulta inc\'omodo el no poder expresar dependencias entre |OBJECT|os, o
reusar c\'odigo que funciona en un |OBJECT|o particular con otro mayor que
encapsula al primero.  La herencia de objetos en~E permite justamente hacer
eso.  Cuando tienes un objeto |a|:
\ejemplos
&|OBJECT a|\cr
&\quad|sig, indice, term|\cr
&|ENDOBJECT|\cr
\fin
puedes crear un nuevo objeto |b|  con las mismas propiedades de |a|
(y compatible con el c\'odigo que se sirve de |a|):
\ejemplos
&|OBJECT b OF a|\cr
&\quad|bla, x, burp|\cr
&|ENDOBJECT|\cr
\fin
y que equivale a:
\ejemplos
&|OBJECT b|\cr
&\quad|sig, indice, term,         /* de a */|\cr
&\quad|bla, x, burp|\cr
&|ENDOBJECT|\cr
\fin
de  forma  que  con |DEF p:b| podr\'as acceder directamente no s\'olo a |p.bla|
sino tambi\'en a |p.sig|.

\espacio
Por ejemplo, si se tiene un m\'odulo con un |OBJECT|o para implementar un
cierto tipo de datos con procedimientos de apoyo, (por ejemplo, una lista
doblemente enlazada) se puede simplemente heredar de ella, a\~nadiendo datos
propios al objeto, y usar las funciones {\sl existentes} para manipular la
lista.  Sin embargo la herencia s\'olo ofrece toda su potencia cuando se
combina con m\'etodos.



\seccion Ocultamiento de datos (|EXPORT/PRIVATE/PUBLIC|).
E posee un mecanismo de ocultamiento de datos bastante controlable.  Otros
lenguajes, como el C++, usan el ocultamiento de datos en clases, lo cual nos
lleva a la necesidad de trampas (como {\it friends}), y hace el ocultamiento de
datos inseguro (Eiffel).  El ocultamiento de datos de~E funciona a nivel de
m\'odulos, lo cual permite modelar el ocultamiento de datos a nivel de clases,
pero tambi\'en permite esquemas m\'as inteligentes.

\espacio
   |PUBLIC|  y  |PRIVATE| declaran visible o no al mundo exterior una secci\'on
de un objeto;  en este caso, el mundo exterior es todo el c\'odigo ajeno al
m\'odulo.  Por otra parte, todo es visible para el c\'odigo del m\'odulo. Veamos un
ejemplo:
\begintt
OBJECT misdatos PRIVATE                 -> todo el objeto es privado
  bla:PTR TO misdatos, burp, grrr:INT
ENDOBJECT

OBJECT aaargh
  blerk:PTR TO aaargh                   -> publico
PRIVATE
  x:INT, y:INT, z:INT                   -> privado
PUBLIC
  hmpf[10]:ARRAY OF misdatos            -> publico de nuevo
ENDOBJECT
\endtt
Un objeto  es p\'ublico por  omisi\'on, la  aparici\'on de |PRIVATE|  o |PUBLIC|
actua como interruptor para la visibilidad del objeto en ese momento.  En
el primer  objeto todo  es privado.  El segundo  s\'olo tiene  (x,y,z) como
privado.  Las palabras clave |PRIVATE| y |PUBLIC| pueden aparecer:
\item{$-$} En la l\'{\i}nea de cabecera del objeto.
\item{$-$} Como l\'{\i}nea en si misma dentro de la definici\'on del objeto.
\item{$-$} Precediendo declaraciones en la definici\'on del objeto.

\noin (es decir, pr\'acticamente en cualquier lugar)

\Espacio
{\it ?`Por que ocultamiento de datos?}

\espacio
Si  quieres saber  por  qu\'e  el ocultamiento  de  datos  es una  buena
t\'ecnica,  es  probable que quieras  leer alg\'un buen libro de OO\null{}.  Pero en
resumen: por lo  general se supone que gran cantidad  de los problemas de
mantenimiento y mejora de fragmentos grandes de c\'odigo  se deben al hecho
de que resulta  dificil cambiar las cosas, debido a  que gran cantidad de
c\'odigo empieza a  depender de ciertas estructuras del c\'odigo.  Si ocultas
un objeto,  s\'olo el c\'odigo dentro del m\'odulo depender\'a del formato de los
objetos,  y podr\'as  modificar f\'acilmente la representaci\'on de un objeto y
el c\'odigo que trabaja con \'el  (por ejemplo, podr\'{\i}as cambiar f\'acilmente la
implementaci\'on  de una  pila de  |ARRAY| a  una lista).  Si gran  parte del
c\'odigo de  una gran  aplicaci\'on depende del  hecho de que  la pila  es un
|ARRAY|, no podr\'as cambiarlo con facilidad, lo cual acarrear\'a problemas. En
resumen, intenta  ocultar tanto  como puedas sin  llegar a  ser demasiado
restrictivo en  el uso  de tu objeto.  El uso de  m\'etodos te  permitir\'a a
menudo mantener todo el objeto privado.



\seccion M\'etodos y m\'etodos virtuales.
Un  m\'etodo  es  muy parecido a un |PROC|, con la diferencia de que forma
parte de un |OBJECT|o.  Adem\'as, tambi\'en permite explotar el polimorfismo en
los objetos, como veremos a continuaci\'on.  Veamos la definici\'on de un m\'etodo:
\ejemplos
&|OBJECT blerk PRIVATE|\cr
&\quad|x:PTR TO blerk, y:INT, z|\cr
&|ENDOBJECT|\cr
\Esptab
&|PROC getx() OF blerk IS self.x|\cr
\fin
la parte |OF blerk| le dice al compilador que pertenece al objeto |blerk|.
F\'{\i}jate en que, aparte de |OF|, la sintaxis es completamente igual a la de un
|PROC|, sin embargo, no se puede invocar como tal, y tambi\'en funciona de
forma diferente.

\espacio
|self| es una variable local que est\'a disponible en todo m\'etodo, y es un
puntero al objeto al que pertenece el m\'etodo (en este caso |self:PTR TO blerk|).
Esta funci\'on s\'olo retorna el valor de campo |x| de |blerk|, lo cual
tiene sentido, ya que esto te permite modificar m\'as tarde lo que representa |x|.

\espacio
Los m\'etodos se pueden llamar de forma similar a como se hace la selecci\'on de
objetos ``|.|'':
\ejemplos
&|DEF a:PTR TO blerk|\cr
&|NEW a|\cr
&| ...|\cr
&|a.getx()           -> invoca metodo getx() en el objeto a|\cr
\fin
en este ejemplo, sobre la invocaci\'on  |a| toma el valor de |self| durante
la jecuci\'on de |getx()|.

\espacio
   Como  ves,  el uso de m\'etodos es interesante, aunque no hemos visto su
poder real, el cual s\'olo aparece cuando se usa junto con la herencia.

\espacio
   Si heredo  un objeto  que tiene m\'etodos,  de forma  autom\'atica obtengo
esos m\'etodos en el nuevo objeto:
\begintt
OBJECT burp OF blerk PRIVATE   -> como blerk, + campo extra
  prut:INT
ENDOBJECT

DEF b:PTR TO burp
NEW b
 ...
b.getx()                       -> mismo metodo
\endtt

\espacio
Lo interesante  viene ahora,  ya que  en lugar  de heredar  un m\'etodo,
tambi\'en puedes redefinirlo:
\ejemplos
&|PROC getx() OF burp IS self.x+1|\cr
\fin
(no hace falta decir que tambi\'en puedes a\~nadir nuevos m\'etodos)

\espacio
   As\'{\i}   que,  cuando  sea  apropiado,  puedes  optar  por  modificar  el
funcionamiento  de  los  m\'etodos que obtenemos de otros objetos, mientras
que el interface a \'el (en este caso |getx()|) se mantiene igual.  Esto no
s\'olo  permite  la  reutilizaci\'on  del  c\'odigo de forma selectiva, tambi\'en
podemos hacer uso del polimorfismo:
\ejemplos
&|PROC hazalgo(o:PTR TO blerk)|\cr
&|  ...|\cr
&|  o.getx()|\cr
&|  ...|\cr
&|ENDPROC|\cr
\Esptab
&|hazalgo(a)|\cr
&|hazalgo(b)|\cr
\fin
podemos  llamar  a este |PROC| tanto con |a| como con |b|, ya que ambos son
compatibles con un objeto |blerk|.  Aunque, ?`Cual de las dos implementaciones
de |getx()| se invoca con |o.getx()|?\qquad Repuesta:\quad las dos.  Las llamadas
a m\'etodos en~E son lo que se llaman m\'etodos virtuales en otros lenguajes:
act\'uan  din\'amicamente  en  el tipo real del objeto (|o|) y llaman al m\'etodo
apropiado.

\espacio
Un ejemplo m\'as claro:
\ejemplos
&|-> Ejemplo clasico de polimorfismo OO|\cr
\esptab
&|OBJECT loc|\cr
&|  PRIVATE posx:INT, posy:INT|\cr
&|ENDOBJECT|\cr
\esptab
&|OBJECT punto OF loc|\cr
&|  PRIVATE color:INT|\cr
&|ENDOBJECT|\cr
\esptab
&|OBJECT circulo OF punto|\cr
&|  PRIVATE rados:INT|\cr
&|ENDOBJECT|\cr
\esptab
&|PROC muestra() OF loc IS WriteF('!`Soy una Localizacion!\n')|\cr
&|PROC muestra() OF punto IS WriteF('!`Soy un Punto!\n')|\cr
&|PROC muestra() OF circulo IS WriteF('!`Soy un Circulo!\n')|\cr
\esptab
&|PROC main()|\cr
&|  DEF x:PTR TO loc,l:PTR TO loc,p:PTR TO punto,c:PTR TO circulo|\cr
&|  ForAll({x},[NEW l,NEW p,NEW c],`x.muestra())|\cr
&|ENDPROC|\cr
\fin
aqu\'{\i} |x| es un |PTR TO loc|,  por lo que podr\'{\i}as esperar que |x.muestra()|
escribiera |!`Soy una Localizacion!| tres veces, pero en su lugar escribe la
cadena correcta para cada objeto.

\espacio
Si  quisieramos  escribir esto en un lenguaje no OO, necesitar\'{\i}amos un
|SELECT|  para  cada  operaci\'on  como  |muestra()|,  comprobando cierto valor
presente  en  el  objeto para ver de qu\'e tipo es.  Si quisiera a\~nadir una
nueva forma a las anteriores, como:
\ejemplos
&|OBJECT elipse OF circulo|\cr
\fin
necesitar\'{\i}a cambiar  todos los |SELECT|s a  lo largo de la  aplicaci\'on para
que  lo tengan  en cuenta.  Con el  polimorfismo de objetos,  simplemente
escribir\'{\i}a  un m\'etodo |muestra()|,  y  {\bf todo} el c\'odigo de  la aplicaci\'on que
llame a |x.muestra()| actuar\'{\i}a correctamente cuando |x| sea un |PTR TO elipse|,
!`incluso sin tener que recompilar!

\noin Es dificil mostrar  el poder de esto en unos  pocos ejemplos, la mejor
forma de  descubrirlo es  us\'andolo en aplicaciones  reales, y:  como dije
antes, leyendo un libro sobre ello.

\Espacio
{\it ?`C\'omo funciona el polimorfismo?}

\noin En los ejemplos anteriores, est\'a claro que el compilador no sabe a qu\'e
m\'etodo  llamar\'a.  Ese es el motivo por el cual~E usa un {\it objeto clase}, y
cada  objeto creado obtiene un puntero a este objeto.  En el objeto clase
se  guarda  toda  la  informaci\'on que es com\'un a todos los objetos de ese
tipo,  tales  como  punteros a m\'etodos.  Cuando el compilador detecta una
llamada  como |x.muestra()|, en lugar de mirar directamente en la |muestra()|
que  pertenece  al  tipo  de  |x| (es decir |loc|), generar\'a c\'odigo que llama
autom\'aticamente  a la |muestra()| de punto, cuando |x| es realmente un objeto
punto.  Esto recibe a veces el nombre de enlace en tiempo de ejecuci\'on.

\noin Los objetos que tienen m\'etodos son, por tanto,  4~bytes mayores de  lo
esperado,  ya  que  contienen  un puntero al objeto clase.  El puntero lo
inicializa  autom\'aticamente  |NEW|, raz\'on por la que {\it de momento} |NEW| es la
\'unica forma de crear tales tipos de objetos.

\espacio
Si un  m\'etodo se declara  con el \'unico  prop\'osito de permitir  que las
subclases  lo  redefinan (este  tipo  de  clases  se conocen  en  algunos
lenguajes como clases bases virtuales), se puede usar |EMPTY|:
\ejemplos
&|PROC bla() OF obj IS EMPTY|\cr
\fin
entonces  se  puede  redefinir  en  las subclases.  Dado que puede que el
programador  no  implemente  todos los m\'etodos de una vez, no es un error
que se ejecute el m\'etodo anterior.  Simplemente retornar\'a |0| o |NIL|.

\espacio
Se pueden a\~nadir m\'etodos a los |OBJECT|os del sistema:
\ejemplos
&|OBJECT migadget OF gadget       -> !`de intuition!|\cr
&|  -> campos extra aqui|\cr
&|ENDOBJECT|\cr
&|PROC creategadget() OF migadget IS ...|\cr
\finsma
Un puntero a un objeto como \'este es compatible con el puntero normal a
|gadget|, es decir, se puede a\~nadir directamente a un ventana, etc~\dots



\seccion Constructores, Destructores y Super-M\'etodos.
El  constructor puede tener un nombre cualquiera, aunque suele darsele
el mismo nombre que la clase.  Incluso se pueden tener varios constructores
para  una  misma  clase.  El constructor se llama directamente en un
objeto creado con |NEW|:
\ejemplos
&|NEW obj.pila()|\cr
\finsma
Sin  embargo,  los  destructores deben llamarse |end|.  Y el objeto se
destruye con:
\ejemplos
&|END obj|\cr
\fin
y si |obj| tiene un m\'etodo |end()|, se le llama de forma autom\'atica.  |end()|
no debe tener argumentos, y no tiene sentido que retorne un valor.

\Espacio
El super-m\'etodo de un m\'etodo es el m\'etodo de su super-clase con el mismo
nombre.  Algunas veces es \'util llamar a este m\'etodo para incluir su
comportamiento al de tu clases, sin embargo, debido a que lo has redefinido,
el llamar al super-m\'etodo por su nombre simplemente se llamar\'{\i}a a s\'{\i} mismo.
La palabra clave |SUPER| te permite llamar a cualquier m\'etodo de tu
super-clase (o la super-clase de algun otro):
\ejemplos
&|SUPER obj.metodo()|\cr
\fin
este  fragmento  de c\'odigo se puede usar como expresi\'on y como sentencia.
Sin embargo, hay que tener cuidado, ya que si el superm\'etodo llama a otro
m\'etodo de ese objeto, llamar\'a a la versi\'on redefinida, no la de su propio
{\it nivel}  (aunque  eso  suele  ser lo que queremos).  Adem\'as, el compilador
mira  el  tipo est\'atico de |obj| para encontrar su superclase, no el tipo
din\'amico (aunque pueda tener ese resultado).



\endchapter\saltacap
\beginchapter Cap\'{\i}tulo 15. Ensamblador\\en-l\'{\i}nea

Como habr\'as apreciado en el ejemplo de Mnemot\'ecnicos ensamblador, las
instrucciones en ensamblador se pueden mezclar libremente con c\'odigo~E\null{}.
El gran secreto es que el compilador incluye un ensamblador completo.

\espacio
Adem\'as de los modos de direccionamiento normales del ensamblador, puedes
usar los siguientes identificadores del E:
\begintt
mietiqueta
LEA mietiqueta(PC),A1 /* etiquetas */

DEF a                 /* variables */
MOVE.L (A0)+,a        /* fijate que <var> es <offset>(A4) (o A5) */

MOVE.L dosbase,A6     /* identificadores de llamada a library */
JSR    Output(A6)

MOVEQ  #TRUE,D0       /* constantes */
\endtt

\espacio
El ensamblador de |EC| permite las siguientes construcciones, en las cuales:
\ejemplos
\qquad $n$&   = numregistro\cr
\qquad $x$&   = \'{\i}ndice\cr
\qquad $lab$& = etiqueta, de: ``|etiqueta:|'' o ``|PROC etiqueta()|''\cr
\qquad $abs$& = direcci\'on absoluta\cr
\qquad $s$&   = tama\~no. \enspace|L|, |W| o |B|, el que sea apropiado.\cr
\finsma
\item{$-$} modos de direccionamiento que permite |EC|:
\itemitem{} |D|$n$, |A|$n$, |(A|$n$|)|, |(A|$n$|)+|, |-(A|$n$|)|, $x$|(A|$n$|)|, $x$|(A|$n$|,D|$n$|.|$s$|)|,
            $lab$|(PC)|, $lab$|(PC,D|$n$|.|$s$|)|, $abs$, $abs$|.W|\nota{escribe $abs$|.W| en
            hexadecimal,  para no confundirlo con un valor real, es
            decir escribe  |MOVE.L $4.W,A6|}

\espacio
\item{$-$} permitidos parcialmente:
\itemitem{} |#|\<expconst>

\espacio
\item{$-$} no permitidos:
\itemitem{} $lab$ (igual que $abs$), |#|$lab$
\itemitem{} usa |LEA |$lab$|(PC),A|$n$  en su lugar.

\espacio
\item{$-$} modos extra:
\itemitem{} \<var>|.|$s$ (transfiere contenido de \<var>.$s$ puede ser |.W| o |.B|,
            por omisi\'on es |.L|)
\itemitem{} FuncionDeLibreria(A6)

\espacio
ejemplo:
\begintt
...
MOVE.W mivar.W,D0     -> mueve palabra baja de 'mivar'
...
MOVE.L dosbase,A6
JSR    Write(A6)
\endtt

\espacio
Adem\'as, E permite que las funciones retornen directamente un registro:
\ejemplos
&|ENDPROC D0|\cr
\fin
y  tambi\'en  puedes  interpretar esto c\'omo valores de retorno m\'utiples, es
decir |D0/D1/D2|.



\seccion El ensamblador en l\'{\i}nea comparado con un macro ensamblador.
De alguna forma el ensamblador en-l\'{\i}nea se diferencia del macro-ensamblador
de siempre, debido principalmente al hecho de que es una extensi\'on de~E, y
por tanto sigue la sintaxis de~E\null{}.  Las principales diferencias son estas:

\espacio
\item{$-$} los comentarios se hacen con |/* */| y no ``|;|'',  y su significado es
  ligeramente distinto.
\item{$-$} las palabras clave  y los registros van en may\'usculas,  todo depende de
  si va en may\'usculas o min\'usculas.
\item{$-$} no hay macros ni otros lujos de los ensambladores  (bueno, est\'a todo el
  lenguaje~E para cubrir esto~\dots)
\item{$-$} debes tener en cuenta que los registros |A4/A5|  no se deben ensuciar con
  el  c\'odigo en ensamblador, ya que los utiliza el c\'odigo~E, si tu c\'odigo
  se  puede  llamar  desde  c\'odigo que reserva registros, debes preservar
  |D3-D7|.  La siguiente instrucci\'on puede ayudar en caso de problemas:
\itemitem{} |MOVEM.L D3-D7,-(A7); /*ensamblador en linea*/; MOVEM.L (A7)+,D3-D7|
\item{$-$} {\bf Todavia} no se permite  modelo |LARGE/hunk-reloc|  en ensamblador.  Esto
  quiere decir que  de  momento  debes usar  direccionamiento
  relativo a |PC| (que de todas formas es m\'as r\'apido).



\seccion Utilizaci\'on de datos binarios (|INCBIN/CHAR...|).

\Ejemplos
\qquad Sintaxis:&|INCBIN |\<fichero>\cr
\fin
incluye el fichero binario en el punto exacto de la sentencia,  por tanto
debe separase del c\'odigo.  Por ejemplo:
\ejemplos
&|mitab: INCBIN 'df1:data/blabla.bin'|\cr
\fin

\Espacio
\ejemplos
\qquad Sintaxis:&|LONG |\<valores>|, ...|\cr
         &|INT |\<valores>|, ...|\cr
         &|CHAR |\<valores>|, ...|\cr
\fin
te permite colocar datos binarios directamente en  el programa.  Funciona
como |DC.|$x$  en ensamblador.  Se\~nalar que la sentencia |CHAR|  tambi\'en recibe
cadenas, y siempre estar\'an alineados a direcciones pares.  Ejemplo:
\ejemplos
&|misdatos: LONG 1,2; CHAR 3,4,'!`Que hay amigos!',0,1|\cr
\fin



\seccion OPT ASM.
|OPT ASM| tambi\'en se discute en el apartado sobre  |OPT|\null{}.  Permite  operar
con |EC| como si fuera un ensamblador.  No hay ninguna raz\'on para usar |EC|
en lugar de otros macro-ensambladores, a excepci\'on de que es significativamente
m\'as r\'apido que  por ejemplo A68k, as\'{\i} como DevPac,  y pierde  con
respecto a AsmOne (sniff |8-{|).  Tambi\'en ser\'a tedioso el pasar los  viejos
discos con fuentes de Seka por |EC|, debido a las diferencias descritas con
anterioridad.  Si quieres  escribir programas  en ensamblador con  |EC|,  y
quieres mantener tus fuentes compatibles con otros ensambladores, simplemente
precede todos los elementos espec\'{\i}ficos de~E  con un  ``|;|'', |EC|~los
usar\'a, y cualquier otro ensamblador los tomar\'a como comentarios.  Empieza
los comentarios normales con un smiley (|;->|).  Por ejemplo:
\ejemplos
&|; OPT ASM|\cr
&|comienzo:  MOVEQ   #1,D0           ;-> haz algo tonto|\cr
&|           RTS                     ;-> y sal|\cr
\fin
esto lo ensamblar\'a cualquier ensamblador, incluyendo |EC|.



\seccion Ensamblador en l\'{\i}nea y variables registro.
Las variables registro son una buena ayuda al ensamblador en l\'{\i}nea, ya
que  funcionan como registros, aunque al mismo tiempo tienen un identificador
claro  en lugar de Dx, y adem\'as, el c\'odigo de E los guarda y recupera
de forma autom\'atica.  Por ejemplo:
\ejemplos
&|PROC bla()|\cr
&|  DEF count:REG|\cr
&|  MOVEQ #10,cuenta|\cr
&|bucle: WriteF('cuenta=\d\n',cuenta)|\cr
&|  DBRA cuenta,bucle|\cr
&|ENDPROC|\cr
\fin
todas las instrucciones que funcionan  con |Dx EA| funcionan  con variables
registro:
\ejemplos
&|MOVEQ #1,a|\cr
&|MOVEM.L D0/D1/a/b/A0,-(A7)|\cr
&|LSL.L a,b|\cr
&| ....|\cr
\fin
como se  sabe, |EC|  usa los registros |D3-D7|  para estas  variables registro.
Si quieres escribir c\'odigo que mezcle libremente ensamblador con~E,  es
recomendable mantener  variables  usadas  con  frecuencia  en  variables  registro,  y
temporales en |D0-D2|/|A0-A3|/|A5|.



\endchapter\saltacap
\beginchapter Cap\'{\i}tulo 16. Notas T\'ecnicas

\seccion La palabra clave OPT.

\Ejemplos
\qquad Sintaxis:&|OPT |\<opciones>|, ...|\cr
\finsma
Te permite cambiar alg\'un funcionamiento del compilador:
\smallskip
\vbox{\halign{{\tt#}\hfil&
         \quad\vtop{\parindent=0pt\hsize=24pc\hangindent=0pt\strut#\strut}\cr
LARGE&Fija el modelo de c\'odigo y datos en grande (|LARGE|).  Por
                omisi\'on es  peque\~no (|SMALL|);  El compilador suele generar
                c\'odigo relativo a~|PC|, con un tama\~no m\'aximo de~32k.  |LARGE|
                no pone tales l\'{\i}mites, y genera bloques (hunks) reloc.\cr
STACK=x&Fija el tama\~no de la pila a |x|~bytes.  \'Usalo siendo consciente de lo
                que haces.  Normalmente  el  compilador  hace  una  buena
                estimaci\'on del espacio de pila que se necesita.\cr
ASM&Pone el compilador en modo  ensamblador.  A partir de ese
                momento  s\'olo se  permiten instrucciones  en ensamblador,
                y no se genera c\'odigo de inicializaci\'on.\cr
NOWARN&Elimina  las  advertencias.  El compilador  te avisar\'a si 
                {\sl piensa}  que  tu  programa  es  incorrecto,  aunque  sea
                sint\'acticamente correcto.\cr
DIR=dirmodulos&Indica el directorio en  el que el compilador buscar\'a los
                m\'odulos,  por omisi\'on es |EMODULES:|.\cr
OSVERSION=vers&Por  omisi\'on es 33 (v1.2).  Fija  la  versi\'on m\'{\i}nima de  KickStart
                (como  37 para  v2.04) bajo  la que  funcionar\'a tu
                programa.  De esta forma, tu programa fallar\'a al abrir la
                dos.library  en el  c\'odigo  de  inicializaci\'on cuando  tu
                c\'odigo  se  ejecuta  en  m\'aquinas  anteriores.  De  todas
                formas, es  de m\'as utilidad  al usuario si  compurebas la
                versi\'on t\'u mismo y das un mensaje de error apropiado.\cr
MODULE&Indica que este c\'odigo es un m\'odulo.\cr
EXPORT&Exporta autom\'aticamente las declaraciones del m\'odulo.\cr
RTD&Genera RTDs en vez de RTS en fuente principal. S\'olo |020+|.\cr
   &({\it optimizaci\'on experimental\/})\cr
020,881,040&Genera c\'odigo para esa CPUs. Aun no utilizable.\cr
REG=n&Usa |n| registros para reserva de registros.\cr
}}

\Ejemplos
Ejemplo:&|OPT STACK=20000,NOWARN,DIR='df1:modules',OSVERSION=39,REG=3|\cr
\finsma


\seccion Modelo SMALL/LARGE.
\E/ te permite  elegir entre modelo de datos\b/c\'odigo |SMALL| y  |LARGE|\null{}.
F\'{\i}jate que la  mayor\'{\i}a de los programas que  escribir\'as (especialmente si
acabas de empezar con~E) entrar\'an en~32KB al compilarlos:  no tendr\'as que
preocuparte  de poner  alg\'un modelo  de  generaci\'on de  c\'odigo.  Te dar\'as
cuenta de la  necesidad de un modelo  |LARGE| tan pronto como  |EC| empieze a
quejarse de  que ya  no puede poner tu c\'odigo en~32KB\null{}.  Para compilar un
fuente con modelo |LARGE|:
\ejemplos
&|1> ec -l grande.e|\cr
\fin
o mejor incluso, incluye la sentencia
\ejemplos
&|OPT LARGE|\cr
\fin
al principio de tu c\'odigo.



\seccion Organizaci\'on de la pila.
Para guardar las variables locales y globales, el sistema en tiempo de
ejecuci\'on de un ejecutable generado por AmigaE reserva un bloque de memoria,
del  cual  tomar\'a una parte fija para almacenar todas las variables
globales.   El  resto  se usar\'a din\'amicamente seg\'un se vayan llamando las
funciones.   Cuando se llama a una funci\'on en~E, se reserva espacio en la
pila  para  almacenar todos sus datos locales, el cual se libera al salir
de  la  funci\'on.   Ese  es el motivo por el que tener arreglos grandes de
datos locales puede se peligroso cuando se usa recursivamente:  todos los
datos  de las llamadas anteriores a la misma funci\'on siguen estando en la
pila  y  utilizan  partes  grandes  del  espacio  libre  de la pila.  Sin
embargo,  si  los  procedimientos  se  llaman de una forma lineal, no hay
motivo para que la pila se llene. 

\espacio
El sistema en tiempo de ejecuci\'on siempre reserva 10k~extra por encima
de  esto para  una  recursi\'on  normal (por  ejemplo  con arreglos locales
peque\~nos)  y  buffers  y  espacio  de  sistema  adicionales,  por  lo que
reservar\'a 24k de espacio de pila.



\seccion L\'{\i}mites fijos.

\medskip
\vbox{\halign{#\hfil&\quad#\hfil\cr
\bartab
OBJETO/ELEMENTO&TAMA\~NO/CANTIDAD/MAX\cr
\bartab
valor |CHAR|&                                   $0\ldots 255$\cr
valor |INT|&                                    $-32$ Kb\dots $+32$ Kb\cr
valor |LONG|/|PTR|&                             $-2$ Gb\dots $+2$ Gb\cr
\Esptab
logitud identificador&                          $100$ bytes$^\infty$\cr
logitud l\'{\i}nea de c\'odigo&                        $2000$ tokens l\'exicos$^\simeq$\cr
logitud c\'odigo&                                 $2$ Gb (te\'oricamente)\cr
listas constantes&                              algunos cientos de elementos$^\simeq$\cr
cadenas constantes&                             $1000$ caracteres$^\infty$\cr
anidamiento m\'aximo de bucles (|IF|, |FOR| etc.)&$500$ niveles\cr
anidamiento m\'aximo de comentarios&              $\infty$\cr
\Esptab
n\'umero de variables locales por procedimiento&  $8000$\cr
n\'umero de variables globales&                   $7500$\cr
n\'umero de argumentos a funciones propias&       $8000$ (junto con locales)\cr
n\'umero argumentos funciones varargs de E (|WriteF()|)&$64$ (v2.1) / $1024$ (v2.5)\cr
\Esptab
un  objeto (reservado local/global o din\'amico)& $8$ Kb\cr
un  arreglo, lista o cadena (local o global)&   $32$ Kb\cr
una cadena (din\'amicamente)&                     $32$ Kb\cr
una lista (din\'amicamente)&                      $128$ Kb\cr
un  arreglo (din\'amicamente)&                    $2$ Gb\cr
objetos con |NEW|&                              $64$ Kb elementos\cr
|CHAR|/|INT|/|LONG| con |NEW|&                  $2$ Gb\cr
\Esptab
datos locales por procedimiento&                $250$ Mb\cr
datos globales&                                 $250$ Mb\cr
\Esptab
tama\~no c\'odigo de un prodeciemiento&             $32$ Kb\cr
tama\~no c\'odigo del ejecutable&                   |SMALL| $32$ k, |LARGE| $2$ Gb\cr
l\'{\i}mite pr\'actico actual (puede cambiar)&         $2-5$ (v2.1) / $10$ Mb (v2.5)\cr
\Esptab
tama\~no buffer de c\'odigo generado e identific.&  relativo al fuente\cr
tama\~no buffer de etiquetas/saltos e intermed.&  (re)reservado independ.\cr
\bartab
}}

\espacio
{\eightpoint
\noin {$\simeq$} valor aproximado, depende de la situaci\'on.\par
\noin {$\infty$} el valor no tiene l\'{\i}mite claro, pero este parece razonable.\par
}



\seccion Mensajes de error, advertencias y comprobaci\'on de no referencia.

\subsec Comprobaci\'on de no referencia. Al compilar tu c\'odigo fuente con |EC|,
algunas veces obtienes un mensaje del tipo:
\ejemplos
&|UNREFERENCED: |\<ident>, \<ident>|, ...|\cr
\fin
que aparece cuando declaras variables, funciones o etiquetas, y luego no
las usas.  Este servicio extra que te ofrece el compilador te puede dar
alguna buena pista sobre todos esos errores dif\'{\i}ciles de detectar.

\subsec Advertencias. Suelen indicar cosas que pueden ir mal, aunque realmente
no es un error.

\adver 'A4/A5 used in inline assembly'
  'A4/A5 usado en ensamblador en l\'{\i}nea'
  Esta es la advertencia que obtendr\'as  cuando usas los registros A4 o A5
  en tu c\'odigo ensamblador.  El motivo de esto es  que esos registros los
  usa E  internamente para direccionar  las variables globales  y locales
  respectivamente.  Por  supuesto,  puede  haber  una  buena  raz\'on  para
  utilizarlos,  como hacer  un  |MOVEM.L A4/A5,-(A7)|  antes  de una  parte
  grande de ensamblador en l\'{\i}nea.

\adver 'keep an eye on your stacksize'
  'hecha un ojo al tama\~no de la pila'
\fadver

\adver 'stack is definitely too small'
  'la pila es definitivamente muy peque\~na'
  Ambas  pueden ser  provocadas  por  el uso  de  |OPT STACK=|\<tama\~no>.  El
  compilador simplemente contrastar\'a tu  \<tama\~no>  con su  {\it estimaci\'on},  y
  escribir\'a la primera advertencia si piensa que est\'a bien aunque un poco
  ajustado,  y la \'ultima si probablemente es muy peque\~no.

\adver 'suspicious use of |"="| in void expressions (s). (line \%d)'
  'uso sospechoso de |"="| en expersiones void (s). (l\'{\i}nea \%d)'
  Esta advertencia  aparece si escribes expresiones  como |a=1|  como una
  sentencia.  La raz\'on  de esto  es que  una comparaci\'on  no tiene  mucho
  sentido  como sentencia,  aunque la  raz\'on principal  es que  puede ser
  motivo del frecuente error tipogr\'afico de |a:=1|.  Puede ser dificil de
  encontrar el olvido de ``|:|'',  y puede tener consecuencias desastrosas.

\adver 'module changed |OPT| settings'
  'el m\'odulo cambi\'o las opciones |OPT|'
  Si usas un m\'odulo que usa |OPT OSVERSION=37|,  \'esta  tambi\'en  afectar\'a al
  programa principal.  La advertencia  te avisa de \'esto.  Para eliminarla
  s\'olo tienes que poner un |OPT| del mismo tipo en el programa principal.

\adver 'variable used as function'
  'variable usada como funci\'on'
  En  v3,  cualquier  variable  se  puede usar  como  una  funci\'on.  Esta
  advertencia est\'a para {\it avisarte} por si lo haces de forma accidental.

\adver 'code outside |PROC|s'
  'c\'odigo fuera de |PROC|s'
  Has escrito c\'odigo entre |PROC|s, lo cual es de rara utilidad.

\Espacio
\subsec Errores.
   El compilador escribir\'a la l\'{\i}nea de c\'odigo fuente que caus\'o el error a
continuaci\'on de \'este,  y un cursor en el punto exacto del error.  El cursor
denota el punto en el que se hallaba el compilador cuando {\it descubri\'o}
el  error,  por lo que parece l\'ogico pensar que el s\'{\i}mbolo que provoc\'o el
error es el que est\'a justo {\it antes} del cursor.

\parindent=4em
\error 'Sintaxis error'
  'Error de sintaxis'
  El error m\'as com\'un.  Este error aparece tanto cuando  no hay otro error
  apropiado, como cuando la estructura de tu c\'odigo es demasiado anormal.

\error 'unknown keyword/const'
  'palabra clave/constante desconocida'
  Has utilizado un identificador en may\'usculas (como |IF| o |TRUE|), y el
  compilador no pudo encontrar una definici\'on de \'el. Causas:\hfil\break
  $\bullet$ palabra clave mal escrita\hfil\break
  $\bullet$ usaste una constante, pero olvidaste definirla en una sentencia |CONST|\hfil\break
  $\bullet$ te olvidaste de indicar el m\'odulo en el que se define la constante

\error '|":="| expected'
  'se esperaba |":="|'
  Has escrito  una sentencia  |FOR| o  de asignaci\'on,  y pusiste  otra cosa
  diferente de |:=| en su lugar.

\error 'unexpected characters in line'
  'caracteres en la l\'{\i}nea no esperados'
  Usaste caracteres  que no  tienen significado  sint\'actico fuera  de una
  cadena.  Por ejemplo: |@!&\~|

\error 'label expected'
  'se esperaba una etiqueta'
  En algunos puntos,  por ejemplo  despu\'es de la palabra clave |PROC| o |JUMP|, se
  pide un identificador de etiqueta,  y escribiste algo diferente.

\error '|","| expected'
  'se esperaba |","|'
  Al  especificar  una lista  de  elementos  (por  ejemplo una  lista  de
  par\'ametros), escribiste algo que no era una coma.

\error 'variable expected'
  'se esperaba una variable'
  Por ejemplo en:\qquad|FOR |\<var>|:= ...| etc.

\error 'value does not fit in 32 bit'
  'el valor no entra en 32 bits'
  Al especificar una constante diste un n\'umero demasiado grande, como:
  \quad|$FFFFFFFFF|, |"abcdef"|.  Tambi\'en ocurre cuando defines  un |SET|
  con m\'as de 32~elementos.

\error 'missing apostrophe/quote'
  'falta ap\'ostrofe/comilla'
  Te olvidaste del |'| al final de una cadena.

\error 'incoherent program structure'
  'estrutura de programa incoherente'
  $\bullet$ empezaste un nuevo PROC antes de acabar el anterior,\hfil\break
  $\bullet$ no anidas los bucles correctamente, por ejemplo:\hfil\break
  \null\qquad\qquad|FOR|\hfil\break
  \null\qquad\qquad|  IF|\hfil\break
  \null\qquad\qquad|  ENDFOR|\hfil\break
  \null\qquad\qquad|ENDIF|

\error 'illegal command-line option'
  'opci\'on de l\'{\i}nea de comandos ilegal'
  Al especificar |'EC -opt fuente'| escribiste algo para |-opt|  que no es
  una opci\'on legal de~|EC|.

\error 'division and multiplication 16bit only'
  'divisi\'on y multiplicaci\'on s\'olo con 16 bits'
  El compilador detect\'o que  estabas a punto de usar 32 bits  para |*| o |/|.
  Lo cual no tendr\'{\i}a el resultado deseado en tiempo de ejecuci\'on.

\error 'superfluous items in expression/statement'
  'elementos superfluos en expresi\'on/sentencia'
  Despu\'es de  haber compilado  tu sentencia,  el compilador  a\'un encontr\'o
  tokens l\'exicos  en vez del  final de l\'{\i}nea.  Es probable que  te hallas
  olvidado del \<|lf|> o ``|;|'' para separar dos sentencias.

\error 'procedure |"main"| not available'
  'no se dispone del procedimiento |"main"|'
  !`Tu programa no incluye un procedimiento |main()|!

\error 'double declaration of label'
  'doble declaraci\'on de una etiqueta'
  Declaraste una etiqueta dos veces, por ejemplo:\qquad|etiqueta:|\quad y\quad|PROC etiqueta()|

\error 'unsafe use of |"*"| or |"/"|'
  'uso de |"*"| o  |"/"| no seguro'
  De nuevo relacionado con el hecho de que los operadores |*| y |/| son de 16 bits, y no de 32.
  Mira 'divisi\'on y multiplicaci\'on s\'olo con 16 bits'.

\error 'reading sourcefile didn{'}t succeed'
  'sin \'exito al leer el fichero fuente'
  Comprueba  la  especificaci\'on de  fichero  fuente  que diste  con |ec mifuente|,
  aseg\'urate de que acaba en |.e|\nota{en la versi\'on actual del compilador
  ya no es necesario poner la extensi\'on.}

\error 'writing executable didn{'}t succeed'
  'sin exito al escribir el ejecutable'
  Al escribir el c\'odigo generado como ejecutable produjo un error de DOS\null{}.
  Por ejemplo, el ejecutable que ya exist\'{\i}a no se pudo reescribir.

\error 'no args'
  'faltan argumentos'
  |USAGE: ec [-opts] <sourcecodefilename> (`.e' is added)|\hfil\break
  |USO: ec [-opts] <nombrefichfuente> (se a\~nade `.e')|\hfil\break
  Obtienes esto simplemente con escribir |ec| sin ning\'un argumento.

\error 'unknown/illegal addressing mode'
  'modo de direccionamiento desconocido/ilegal'
  Este error s\'olo es del ensamblador en l\'{\i}nea.  Las posibles causas son:\hfil\break
  $\bullet$ usaste alg\'un tipo de direccionamiento que no existe en el 68000\hfil\break
  $\bullet$ el modo de direccionamiento existe, pero no para esa instrucci\'on.  No
    todas  las instrucci\'ones  en ensamblador  permiten todas las combinaciones
    de direcci\'on efectiva tanto para origen como destino.

\error 'unmatched parentheses'
  'discordancia de par\'entesis'
  Tu sentencia tienen m\'as ``|(|'' que ``|)|'' o la rev\'es.

\error 'double declaration'
  'declaraci\'on doble'
  Un identificador se usa en dos o m\'as declaraciones.

\error 'unknown identifier'
  'identificador desconocido'
  Un  identificador  no  se  usa  en ninguna declaraci\'on; es desconocido.
  Probablemente te olvidaste de ponerlo en una sentencia |DEF|.

\error 'incorrect \#of args or use of |()|'
  'n\'umero de args o uso de |()| incorrecto'
  $\bullet$ Te olvidaste poner ``|(|'' o ``|)|'' en el punto correcto,\hfil\break
  $\bullet$ pasate un n\'umero de argumentos incorrecto a alguna funci\'on.

\error 'unknown e/library function'
  'funci\'on de E/de biblioteca desconocida'
  Utilizas un identificador con el primer caracter en may\'uscula y segundo
  en min\'uscula, pero el compilador no le encontr\'o ninguna definici\'on.
  Posibles causas:\hfil\break
  $\bullet$ Nombre de funci\'on m\'al escrito.\hfil\break
  $\bullet$ Se te olvid\'o incluir el m\'odulo que define esa llamada.

\error 'illegal function call'
  'llamada ilegal a funci\'on'
  Raramente aparece.  Puede aparecer  si intentas  construir  llamadas  a
  extra\~nas, como |WriteF()|s anidados. \ Ejemplo:\qquad|WriteF(WriteF('!`hola!'))|

\error 'unknown format code following $\backslash$'
  'c\'odigo de formato que sigue a $\backslash$ desconocido'
  Especificaste un c\'odigo de formato ilegal en una cadena.

\error '|/*| not properly nested comment structure |*/|'
  '|/*| estrutura de comentarios incorrectamente anidada |*/|'
  N\'umero de |/*| no es igual al de |*/|, o est\'an en orden inapropiado.

\error 'could not load binary'
  'no he podido leer binario'
  No se pudo leer \<especfichero> en |INCBIN |\<especfichero>.

\error '|"|$\}$|"| expected'
  'se esperaba |"|$\}$|"|'
  Empezaste una expresi\'on con |{|\<var>, pero se te olvid\'o el |}| final.

\error 'immediate value expected'
  'se esperaba un valor inmediato'
  Algunas construcciones  requieren un  valor inmediato  en lugar  de una
  expresi\'on.  Por ejemplo:\hfil\break
  \null\qquad\qquad|DEF s[x*y]:STRING  -> mal: s\'olo es legal algo como s[100]:STRING|

\error 'incorrect size of value'
  'tama\~no de valor incorrecto'
  Especificaste un valor inaceptablemente  grande (o peque\~no) para alguna
  construcci\'on.  Ejemplos:\hfil\break
  \null\qquad\qquad|DEF s[-1]:STRING, t[1000000]:STRING    /* debe ser 0..32000  */|\hfil\break
  \null\qquad\qquad|MOVEQ #1000,D2                         /* debe ser -128..127 */|

\error 'no e code allowed in assembly modus'
  'no se permite c\'odigo E en modo ensamblador'
  Pusiste  el compilador  en modo  ensamblador con |OPT ASM|,  pero  por
  accidente escribiste algo de c\'odigo en~E.

\error 'illegal/inappropriate type'
  'tipo ilegal/no apropiado'
  En alg\'un lugar donde se necesitaba una especificaci\'on \<tipo> escribiste
  algo no apropiado.  Ejemplos:\hfil\break
  \null\qquad\qquad|DEF a:PTR TO ARRAY       /* no hay tal tipo */|\hfil\break
  \null\qquad\qquad|[1,2,3]:STRING|

\error '|"]"| expected'
  'esperaba |"]"|'
  Empezaste con |[| pero nunca lo acabaste con |]|.

\error 'statement out of local/global scope'
  'sentencia fuera del alcance local/global'
  Un punto de  ruptura del alcance es la primera sentencia |PROC|\null{}.  Antes de
  ella s\'olo se permiten definiciones globales (|DEF|,|CONST|,|MODULE|,etc.), no
  c\'odigo.  En la segunda parte s\'olo son legales c\'odigo  y definiciones de
  funciones, no definiciones globales.

\error 'could not read module correctly'
  'no se pudo leer el m\'odulo correctamente'
  Ocurri\'o un error DOS intentando leer un m\'odulo en una sentencia |MODULE|\null{}.
  Causas:\hfil\break
  $\bullet$ |EModules:| no ha sido asignado correctamente.\hfil\break
  $\bullet$ Nombre del m\'odulo escrito de forma incorrecta, o no existe.\hfil\break
  $\bullet$ Escribiste |MODULE 'bla.m'| en lugar de |MODULE 'bla'|.

\error 'workspace full!'
  '!`espacio de trabajo lleno!'
  Raras veces aparece.  Si lo hace,  deber\'as usar la opci\'on ``|-m|'' (|ADDBUF|)
  para forzar a~|EC|  a que haga una estimaci\'on superior de la cantidad  de
  memoria que necesita.  Intenta compilar  con  |-m2|,  luego con  |-m3|,~\dots,
  hasta que desaparezca el error.  Es probable que hayas escrito una
  aplicaci\'on enorme con cantidades de datos gigantes antes de poder tener la
  oportunidad de obtener este error.

\error 'not enough memory while (re-)allocating'
  'memoria no suficiente al (re-)reservar'
  Simplemente eso.  Posibles soluciones:\hfil\break
  |1. |Estabas  corriendo  otros  programas  en  multitarea.  Aband\'onalos  e
     intentalo de nuevo.\hfil\break
  |2. |Ten\'{\i}as,  poca  memoria  y  tu  memoria  estaba
     fragmentada.  Prueba reiniciando el sistema.\hfil\break
  |3. |Ninguna de |1-2|.  Compra una expansi\'on de memoria (ejem!).

\error 'incorrect object definition'
  'definci\'on de objeto incorrecta'
  Escribiste alguna torpeza en las definiciones entre |OBJECT| y |ENDOBJECT|.

\error 'illegal use of/reference to object'
  'uso ilegal de/referencia a objeto'
  Si usas expresiones como |ptr.miembro|, |miembro| debe ser un miembro legal
  del objeto al que apunta |ptr|.

\error 'incomplete |IF THEN ELSE| expression'
  'expresi\'on |IF THEN ELSE| incompleta'
  Si usas |IF| como operador, la parte |ELSE| es imprescindible: una expresi\'on
  con un |IF| en ella siempre necesita retornar un valor,  mientras que una
  sentencia con un  |IF|  en ella puede,  simplemente,  no hacer nada si no
  est\'a presente una parte |ELSE|.

\error 'unknown object identifier'
  'identificador de objeto desconocido'
  Usaste  un identificador  reconocido por  el compilador  como parte  de
  alg\'un objeto, pero se te olvid\'o declararlo.  Motivos:\hfil\break
  $\bullet$ nombre mal escrito\hfil\break
  $\bullet$ falta el m\'odulo\hfil\break
  $\bullet$ el identificador del m\'odulo no se escribe como esperas  de los RKRMs.
    Compruebalo con |ShowModule|.  Tienes que tener en cuenta que el sistema
    de objetos del Amiga  se hereda de  los identificadores del ensamblador,
    no del~C\null{}.  Y adem\'as siguen la sintaxis de~E.

\error 'double declaration of object identifier'
  'redeclaraci\'on de identificador de objeto'
  Se usa un mismo identificador en la definici\'on de dos objetos.

\error 'reference(s) out of 32k range: switch to |LARGE| model'
  'referencia(s) fuera del rango de 32k: cambia a modelo |LARGE|'
  S\'olo tienes que poner |OPT LARGE| en tu c\'odigo fuente y seguir.

\error 'reference(s) out of 256 byte range'
  'referencia(s) fuera del rango de 256 bytes'
  Es probable que hayas escrito un |BRA.S| o |Bcc.S| a gran distancia.

\error 'too sizy expression'
  'expresi\'on muy grande'
  Usaste cadenas |''| o listas |[]|, quizas |[[]]| recursivas, de gran tama\~no.

\error 'incomplete exception handler definition'
  'definici\'on de manejador de excepciones incompleto'
  Probablemente usaste |EXCEPT| sin |HANDLE|, o al rev\'es.

\error 'not allowed in a module'
  'no permitido en un m\'odulo'
  Estas haciendo  una de  las pocas cosas  que no se  pueden hacer  en un
  m\'odulo, como son variables globales con inicializaci\'on.

\error 'allowed in modules only'
  's\'olo se permite en m\'odulos'
  Es probable que hayas usado |EXPORT| en tu c\'odigo fuente principal.

\error 'this doesn{'}t make sense'
  'esto no tiene sentido'
  Error general.

\error 'you need a newer version of |EC| for this |:-)|'
  'necesitas una versi\'on m\'as reciente de |EC| para esto |:-)|'
  Es  probable que  estes  usando un  m\'odulo que  fue  compilado con  una
  versi\'on m\'as reciente de la que tienes.

\error 'no matching |"["|'
  '|"["| sin emparejar'
  Se encontr\'o un |]| en una sentencia sin un |[| que lo empareja.

\error 'this instruction needs a better |CPU/FPU| (see |OPT|)'
  'esta instrucci\'on necesita una |CPU/FPU| mejor (mira |OPT|)'
  Usas  una  construcci\'on  (probablemente  una  instrucci\'on en ensamblador)  que
  requiere un |OPT 020| o parecido.

\error 'object doesn{'}t understand this method'
  'el objeto no entiende este m\'etodo'
  Invocaste un m\'etodo que no fu\'e definido para ese objeto.

\error 'method doesn{'}t have same \#of args as method of baseclass'
  'el m\'etodo no tiene el mismo n\'umero de args que el de la clase base'
  Si redefines  un m\'etodo,  debes asegurarte  de que  el nuevo  tiene el
  mismo n\'umero de argumentos que el original.

\error 'too many register variables in this function'
  'demasiadas variables registro en esta funci\'on'
  Estas declarando variables resgitro con |:REG|, y de momemto
  no se pueden usar m\'as de |5|.

\error 'Linker can{'}t find all symbols'
  'el enlazador no encuentra todos los s\'{\i}mbolos'
  Si usas un  m\'odulo $A$ que usa a  su vez un m\'odulo $B$,  $B$ tambi\'en debe ser
  enlazado.  $A$ depende  de ciertos  |PROC|s  que estan  en  $B$,  y si $B$  fue
  recompilado sin esos  |PROC|s,  entonces el enlazador tendr\'a problemas al
  crear tu ejecutable.

\error 'could not open |"mathieeesingbas.library"|'
  'no pude abrir |"mathieeesingbas.library"|'
  Si usas c\'odigo con reales, el propio compilador necesitar\'a funciones de
  reales para poder generar el c\'odigo.

\error 'illegal destructor definition'
  'definici\'on de desctructor ilegal'
  Definiste un m\'etodo |end()| con argumentos (o con valor de retorno).

\error 'implicit initialisation of private members'
  'inicializaci\'on impl\'{\i}cita de miembros privados'
  Escribiste una expresi\'on |[...]| o |NEW [...]| que tiene partes privadas.

\error 'double method declaration'
  'redefinici\'on de m\'etodo'
  Definiste un m\'etodo dos veces para el mismo objeto.

\error 'object referenced by other object not found'
  'objeto hace referencia a otro que no se encuentra'
  Es probable  que heredaras de  alg\'un otro objeto  en otro m\'odulo,  y lo
  cambiaste  (por ejemplo  su  nombre) sin  cambiar\b/recompilar los  dem\'as
  m\'odulos que dependen de \'el tambi\'en.

\error 'unknown preprocessor keyword'
  'palabra clave de preprocesador desconocida'
  El preprocesador de |EC| s\'olo reconoce |#define|, |#ifdef|, |#ifndef| y |#endif|.

\error 'illegal macro definition'
  'definici\'on de macro ilegal'
  Provocaste un error de sintaxis al escribir tu |#define|.

\error 'incoherent \#|ifdef|/\#|ifndef| nesting'
  'anidamiento de \#|ifdef|/\#|ifndef| no coherente'
  Se te olvid\'o cerrar con |#endif|, o algo parecido.

\error 'macro redefinition'
  'redefinici\'on de macro'
  No puedes usar el mismo identificador de nombre de macro dos veces.

\error 'Sintaxis error in \#|ifdef|/\#|ifndef|/\#|else|/\#|endif|'
  'error de sintaxis en \#|ifdef|/\#|ifndef|/\#|else|/\#|endif|'
  ({\it mira el apartado sobre la correcta compilaci\'on de c\'odigo condicional\/}).

\error 'macro(s) nested too deep'
  'macro(s) anidada(s) a un nivel muy profundo'
  Obtendr\'as esto si tienes macros que  se expanden a otras, las cuales se
  expanden a otras,~\dots,  de forma que  la cantidad de  memoria necesaria
  para esto se empieza a desmadrar.  Lo m\'as seguro es  que hayas definido
  una macro recursiva (que intentar\'a expandirse indefinidamente).

\error 'method definition out of object/module scope'
  'definci\'on de m\'etodo fuera del alcance del objeto/m\'odulo'
  S\'olo puedes definir m\'etodos para un objeto en el mismo m\'odulo\b/fuente en
  el que se define el objeto.

\parindent=2em

\seccion Organizaci\'on del buffer del compilador y reserva.
Es \'util saber  como organiza |EC| sus buffers,  cuando obtienes un error
de {\ninebf 'workspace full'} (raras veces),  o quieres saber qu\'e  es lo que sucede
realmente cuando se compila tu programa.

\espacio
   Un compilador, y en este caso  |EC|, necesita buffers para mantener todo
tipo de cosas,  como identificadores, etc~\dots,  y necesita  un buffer para
almacenar  el c\'odigo que genera.  |EC|  desconoce el tama\~no que deben tener
esos buffers.  Esto no representa ning\'un problema para  la mayor\'{\i}a de los
buffers, como el que se utiliza para varias estructuras,  si el buffer se
llena durante la compilaci\'on,  |EC| s\'olo tiene que reservar  un nuevo fragmento
de memoria y continuar.  Sin embargo,  otros buffers,  como  el que
contiene el c\'odigo  generado, debe estar en un bloque de memoria cont\'{\i}guo
que no cambien durante la compilaci\'on: |EC| necista hacer una buena estimaci\'on
sobre el tama\~no de este buffer para poder compilar c\'odigo fuente  ya
sea grande o peque\~no.  Para ello  |EC|  calcula  la memoria  que necesitar\'a
dependiendo  del  tama\~no  del  c\'odigo  fuente,  y  le suma  una  cantidad
apropiada.  De esta forma,  en el  99\%~de los casos,  |EC|  habr\'a reservado
suficiente memoria  para compilar practicamente cualquier  c\'odigo fuente,
en los dem\'as casos, se te ofrecer\'a un error y tendr\'as que especificar m\'as
memoria con la opci\'on |-m| (|ADDBUF|).

\espacio
   Para ver c\'omo funciona esto en la pr\'actica prueba con fuentes de diferentes
tipos y tama\~nos en combinaci\'on con la opci\'on |-b| (|SHOWBUF|).



\seccion Reserva de registros.
E v3 permite la reserva de registros, que es una t\'ecnica para mantener
variables en  registros en  lugar de  la pila.  En c\'odigo normal  que use
rutinas del~SO  no  notar\'as mucho la  diferencia,  aunque para  bucles de
computaci\'on peque\~nos, esta optimizaci\'on puede marcar una gran diferencia.

\espacio
Hay dos formas de utilizar reserva de registros:
\item{$-$} Con la opci\'on |REG|.
\item{} Si,  por ejemplo,  escribes  |EC REG=3 bla.e|,  (de momento max=5),  |EC|
  buscar\'a para  cada |PROC| las tres  variables m\'as usadas y  las pondr\'a en
  registros.  La resreva  de  registro  es una  t\'ecnica  que intenta  ser
  inteligente: calcular\'a un peso para cada variable,  y usar\'a heur\'{\i}sticos
  para incrementar tal peso, por ejemplo, una variable usada en un bucle
  |FOR| obtiene  un peso relativamente mayor  que una usada fuera de \'el,  y
  una en un  |IF| obtendr\'a un peso incluso menor.  Estos pesos se combinan,
  de forma que un |WHILE| en un |FOR| obtiene un peso bastante mayor.
\item{$-$} HTM (Hazlo Tu Mismo).
\item{}  Puedes poner  la palabra  clave |REG|  delante de  cualquier tipo  en una
  declaraci\'on, por ejemplo:
\itemitem{} |DEF x:REG, s[4]:REG LIST|
\item{}  puedes utilizarlo si no crees en el reservador de registros, o si quieres
  realizar un ajuste fino en un s\'olo |PROC|\null{}.  Incluso  puedes  usar las
  dos t\'ecnicas juntas:  si en un |PROC| tienes una variable con |:REG|, compilar
  con |REG=5| permitir\'a a~|EC| repartir los 4~restantes por s\'{\i} mismo.

\Espacio
Por omisi\'on |REG=0|, haciendo que |EC| opere como en versiones anteriores.

\espacio
S\'olo  se {\bf pueden}  reservar  variables locales  que  no son  par\'ametros.
Ademas, si tomas la direcci\'on de una  variable con |{}|, no la puedes poner
en un  registro (adivina  por qu\'e).  No se  pueden reservar  registros en
|PROC|s que tienen manejador de excepciones, de momento.

\Espacio
Estas son algunas cosas a tener en cuenta al usar registros:
\item{$-$} Esta parte de |EC| (E v3.0a)  se ha comprobado ser bastante fiable,  pero
  debes seguir comprobando que el funcionamiento sea igual que  en c\'odigo
  sin reserva.
\item{}  {\sl Debe} funcionar bien, pero es demasiado pronto para garantizarlo |:-)|
  Resumiendo: desde este momento, ten cuidado al aplicar estas t\'ecnicas.
\item{$-$} |EC| usa  los  registros  |D7...D3|  para  variables,  de modo  que si usas
  ensamblador en l\'{\i}nea,  debes procurar que los |PROC|s que usan reserva de
  registros  o  |:REG|  no  los  ensucien.   El c\'odigo generado por un |PROC|
  guarda  de  forma  autom\'atica  los  registros  que usa para proteger el
  c\'odigo desde el que fu\'e llamado.
\item{$-$} Pista:  compilar con |REG=5|  no tiene porqu\'e ser m\'as r\'apido,  ya  que el
  guardar las variables en llamadas a funci\'on\b/librer\'{\i}a implica m\'as c\'odigo
  a ejecutar.  Adem\'as, si {\it todo} el c\'odigo en cuesti\'on opera con llamadas
  de librer\'{\i}a  en lugar de  computaci\'on pura, no esperes  ninguna ventaja
  con los registros.

\begintt
PROC main()                -> este programa sera dos veces mas rapido
  DEF a,b=10,c=20,d        -> facilmente si se reservan registros.
  FOR a:=1 TO 1000000 DO d:=b+c
ENDPROC

PROC main()                -> este sera, como mucho, un 5% mas rapido
  DEF a,s[100]:STRING,t    -> reservando registros.
  t:='poner "a" en un reg no creo que acelere esto mucho.'
  FOR a:=1 TO 100000 DO StrCopy(s,t)
ENDPROC
\endtt



\endchapter\saltacap
\beginchapter Cap\'{\i}tulo 17. Utilidades\\imprescindibles

\seccion bin/showmodule.
Como ya habr\'as notado,  el equivalente de~E para los {\sl includes\/}\nota{ficheros de cabecera},
los m\'odulos,  son ficheros binarios,  muy parecidos a los que se  ofrecen con
los compiladores de Modula2 por ejemplo.  Para ver el  contenido de tales
ficheros en forma \ASCII/ legible,  puedes utilizar |ShowModule|:
\ejemplos
&|ShowModule |\<especmodulo>\cr
\fin
\Ejemplos
Ejemplos:&|1> showmodule EModules:intuition/intuition|\cr
         &|1> showmodule >gadtools.txt EModules:gadtools|\cr
\fin
Por omisi\'on  |ShowModule|  escribe  a |stdout|,  y  se  puede
detener en cualquier momento con \<|CtrlC|>.


\seccion sources/utilities/showhunk{.}e, bin/showhunk.
Muestra  todo  tipo  de   ficheros  ejecutables,  adem\'as  de  ficheros
objeto |.o| generados por (otros) compiladores\b/ensambladores.  Muestra la
estructura  (muy simple)  de  los ejecutables  generados  por~|EC|,  aunque
tambien permite ficheros overlay complejos. Tambi\'en muestra las etiquetas
(como |XREF|s y |XDEF|s).  Y lo  m\'as importante de todo,  |ShowHunk| ofrece
un  desensamblador para los bloques de c\'odigo, usando la opci\'on |DISASM/S|.
\ejemplos
&|ShowHunk |\<ficheroeje>\cr
\fin
\Ejemplos
Ejemplos:&|1> ShowHunk holamundo|\cr
         &|1> ShowHunk DISASM dpaint|\cr
\fin


\seccion bin/iconvert, bin/pragma2module.
Estas  dos utilidades  son  s\'olo para  programadores  de~E avanzados\nota{al igual
 que la utilidad |ShowModule|,  ya  no  se incluye el c\'odigo
 fuente de estas utilidades en la distribuci\'on, ya que la gente utilizaba
 de forma incorrecta  su conocimiento  del  formato  de los m\'odulos |.m|.
 Es {\bf privado}.  Contacta conmigo primero si quieres hacer algo con \'el.}.
S\'altate este apartado si crees que (todav\'{\i}a) no eres uno de ellos.

\espacio
|IConvert|  convierte definiciones  de estructuras  y constantes  de los
ficheros |.i| en ensamblador a m\'odulos~E,  y |Pragma2Module|  hace lo mismo
con ficheros |pragma| de SAS/C de definici\'on de librer\'{\i}a.  Por supuesto, ya
se han  convertido de esta  forma todos  los includes de Commodore,  pero
digamos que  encuentras una librer\'{\i}a  de PD que  te gustar\'{\i}a usar  con~E,
entonces necesitar\'as estas utilidades.

\espacio
   La mayor\'{\i}a  de las  librer\'{\i}as vienen  con varios  includes definiendo,
obviamente, las llamadas  a librer\'{\i}a de la librer\'{\i}a,  as\'{\i} como constantes
y  estructuras  (|OBJECT|os  en~E)  que  utiliza.  Digamos  que  se  llama
|tools.library|, entonces, es probable que incluya:
\ejemplos
&|pragmas/tools_pragmas.h|\cr
&|includes/tools.i|\cr
\fin
entonces tienes que hacer:
\ejemplos
&|1> Pragma2Module tools_pragmas.h|\cr
\fin
renombrar el   |tools_pragmas.m|  resultante  a  |tools.m|   y  ponerlo  en
|EModules:|, luego comprueba con |ShowModule| si todo fue correcto.  Despu\'es de esto
ya puedes usar la |tools.library| en tu programa:
\ejemplos
&|MODULE 'tools'|\cr
\Esptab
&|PROC main()|\cr
&|  IF (toolsbase:=Openlibrary('tools.library',37))=NIL THEN error()|\cr
&|....|\cr
&|  ToolsFunc()|\cr
&|....|\cr
\finsma
Ahora con |IConvert| convierte  |tools.i| a |tools.m|,  el cual  puedes
colocar  en el directorio |EModules/libraries/|.  |IConvert|  necesita  un
ensamblador como el A68k  de DP para hacer la mayor  parte del trabajo de
traducci\'on del ensamblador.
\Ejemplos
&|1> IConvert tools.i|\cr
\fin
mira con  |ShowModule|  todo lo que se obtuvo del fichero |.i|.  Y  ya lo  podr\'as
usar en tu programa con:
\ejemplos
&|MODULE 'libraries/tools'|\cr
\Esptab
&|DEF x:toolsobj, y=TOOLS_CONST|\cr
\finsma
La  conversi\'on  con  |IConvert|  puede requerir  alguna  experiencia  con
ensamblador,  ya que |IConvert|  depende del  formato correcto  del fichero
|.i|, justo como los includes de ensamblador de  Commodore.  Es necesario
corregir amano cerca del 10\% de los ficheros |.i| para poder {\it convertirlos}.
Las expresiones que |IConvert| piensa que son correctas son, entre otras:
\ejemplos
&\<etiqueta>| EQU |\<expresi\'on\_cualquiera>\cr
\Esptab
&|STRUCTURE |\<nombreEs>|,0  ; |si |<>0,| entonces \<estructura>|_SIZEOF|\cr
&|ULONG |\<nombreEs>|_|\<etiqueta>\cr
&|BPTR |\<nombreEs>|_|\<etiqueta>\cr
&|  ; |etc.\cr
&|LABEL |\<nombreEs>|_SIZEOF  ; |o |"_SIZE"|\cr
\fin

\Espacio
Para tener una idea del tipo de expresiones en ensamblador con las que
puede  operar  |IConvert|,  hecha  un vistazo a los includes ensamblador de
Commodore y comp\'aralos con sus m\'odulos equivalentes (ej.~|intuition.i|).


\seccion bin/ShowCache, bin/FlushCache.
El  Cach\'e de  Modulos de E  es un  fragmento de  memoria que  permite
mantener m\'odulos  (|.m|) entre compilaciones.  La primera  vez que  usas un
cierto m\'odulo,  |EC|  lo leer\'a  del  disco y  lo  pondr\'a en  el cach\'e.  Las
siguientes veces |EC| lo encontrar\'a en el cach\'e,  y no tendr\'a que leer nada
de disco.  Si  |EC|  compila un m\'odulo del cual hay una versi\'on anterior en
el cach\'e lo sacar\'a del cach\'e.  Puedes imaginar que esto supone una mejora
en el tiempo de compilaci\'on enorme cuando se usan gran cantidad de m\'odulos
y se recompila a menudo, incluso para  gente con  disco duro,

\noin Para ver  qu\'e es  lo que  est\'a almacenado  en el  cach\'e en  un momento
determinado (y cuanta memoria se est\'a empleando |:-)|), teclea:
\ejemplos
&|1> ShowCache|\cr
\finsma
Una segunda utilidad,  |FlushCache|, permite eliminar selectivamente los
m\'odulos del cach\'e.  Las razones de esto pueden ser:
\item{$-$} No te puedes permitir prescindir de la memoria que utiliza,
\item{$-$} Creaste un nuevo |.m|,  con una herramienta distinta de |EC|,  por lo que
  nececitas vaciar el cach\'e a mano.

\espacio
   El argumento que recibe es la cadena que debe aparacer en el nombre de
un  m\'odulo para eliminarlo del cach\'e.  El no dar un argumento implica
el vaciado completo.
\ejemplos
&|1> FlushCache            ; vacia todo el cache|\cr
&|1> FlushCache intuition/ ; elimina modulos de intuition|\cr
\finsma
Puedes usar  la opci\'on de  |EC| |IGNORECACHE/S| para compilar  un fuente
sin usar el cach\'e.  Ya est\'e el cach\'e lleno o vac\'{\i}o,  |EC| lo  leer\'a todo de
disco,  y no pondr\'a nada en \'este.

\espacio
Si dos |EC|s intentan acceder al cach\'e simult\'aneamente en multitarea, el
segundo |EC| actuar\'a como si se le hubiera dado la opci\'on |IGNORECACHE|.


\seccion rexx/ecompile{.}rexx\nota{?`quien mantiene los otros scripts de ARexx?}.
Este es  un script  ARexx para  CygnusEd (tm),  y te  permite compilar
programas desde el editor.  Asigna este script a una tecla de
funci\'on en  el editor  con |Install Dos/Arexx Command ...|  (comprueba tu
manual de CED si no estas seguro de como hacer esto).  Ahora,  escribe tu
programa,  y pulsa  |Fx| si quieres compilar.  El c\'odigo fuente se guardar\'a
si  es  necesario, se  invocar\'a  al  compilador  en una  ventana  consola
separada,  y se ejecutar\'a el programa  en una ventana  consola diferente.
Cuando el programa acabe,  puedes pulsar  \<|return|>  para volver al editor
(el script realiza de forma  autom\'atica el cambio de la  pantalla de  CED
adelante y detr\'as).  Si ocurre un error durante la compilaci\'on, el script
permitir\'a a CED saltar a la l\'{\i}nea del error despu\'es de pulsar \<|return|>.

\espacio
(en  el script  hay un nombre  de camino que  indica donde  se puede
encontrar el compilador.  Es probable  que tengas que cambiarlo.  Adem\'as,
el  script copia |EC| a |RAM:|  para sistemas con un dispositivo |SYS:|  lento,
puede que quieras deshabilitar esto si tienes un disco duro r\'apido.)


\seccion bin/o2m.
Si tienes  bloques de  fuente en ensamblador  grandes que  te gustar\'{\i}a
usar,  ser\'{\i}a tedioso tener que,  como poco,  convertirlos todos a  mano a
ensamblador en  l\'{\i}nea de~E\null{}.  |o2m| te permite  hacer que, de forma sencilla, tu
macro-ensamblador  favorito te  lo ensamble  todo  a un  fichero |.o|,  y
entonces |o2m|  te convertir\'a ese fichero  |.o| a un fichero  |.m| para ser
usado con~E\null{}.  Si tienes un fichero |bla.o|:
\ejemplos
&|1> o2m bla|\cr
\fin
producir\'a |bla.m|.  Sin embargo,  el fichero |.o| tendr\'a que seguir ciertas
reglas.  Debe consistir  de un  s\'olo  bloque de  c\'odigo con  definiciones
externas (|XDEF|s)  para cada s\'{\i}mbolo al que desees  hacer referencia desde~E,
y ning\'un |XREF|\null{}.  Por lo general, tu fuente se parecer\'a a:
\ejemplos
&|        XDEF suma__ii|\cr
\Esptab
&|suma__ii:|\cr
&|        move.l  4(a7),d0|\cr
&|        add.l   8(a7),d0|\cr
&|        rts|\cr
\fin
un fragmento de ensamblador que recibe dos argumentos (de
ah\'{\i}  las  dos  ``|i|''  de  entero).  Los argumentos se encuentran en la
pila, donde |4(a7)| es el \'ultimo argumento, |8(a7)| el anterior,~\dots

\espacio
|ShowHunk| muestra esto como:
\ejemplos
&|        hunk_unit:|\cr
&|HUNK -1 hunk_name:|\cr
&|        hunk_code: 12 bytes|\cr
&|        hunk_ext|\cr
&|          add__ii = $0|\cr
\fin
este tipo de fichero |.o| se puede convertir facilmente a |.m| con |o2m|:
\ejemplos
&|/* this module contains 12 bytes of code! */|\cr
\Esptab
&|PROC add(a,b)|\cr
\finsma
Hay que destacar algunas cosas:
\item{$-$} si tu c\'odigo ensamblador usa |D3-D7/A4/A5| es probable que debas guardarlos.
\item{$-$} si una etiqueta  no tienen el  ``|__|'' con un  ``|i|''  para cada funci\'on,  se
  convierte  en una  funci\'on sin  par\'ametros.  No te preocupes  de si  la
  etiqueta  en  realidad  hace  referencia a  datos,  puedes  obtener  la
  direcci\'on de ese |PROC| con |{}|,  y usarla como un puntero a tus datos.

\espacio
En teor\'{\i}a, |o2m| se podr\'{\i}a usar para  enlazar c\'odigo~C a programas en~E,
sin  embargo,  a menudo,  en la  pr\'actica esto  no  es  factible.  Si  tu
compilador de~C te  permite {\sl ajustar} los  ficheros |.o|  resultantes un
poco, podr\'{\i}a funcionar. Aunque nos podemos encontrar con algunos problemas:
\item{$-$} referencia a funciones de C, por ejemplo |_printf()|.
\item{$-$} referencia a variables globales creadas por el c\'odigo de inicializaci\'on de~C\null{}.
  El c\'odigo en~C podr\'{\i}a  hacer referencia a |DOSBase| como |XREF|, mientras
  que  el c\'odigo inicializaci\'on de~E dispone este valor en alg\'un lugar de
  la pila.
\item{$-$} convenios de llamada/registros.

\noin Se pueden enlazar  con~E funciones de~C que s\'olo realicen
c\'alculos simples. (Yo he conseguido utilizarlas con \'exito usando
MaxonC++, cuyo enlazador usa el convenio |__ii| para los par\'ametros.)


\seccion bin/EYacc.
Esta es  una conversi\'on de  la famosa utilidad |Yacc| de Unix,  el cual
ahora produce c\'odigo~E en  lugar de c\'odigo~C\null{}.  Esta es s\'olo  una primera
versi\'on,  por  lo  que no esperes mucho de ella.  Si no tienes idea de lo
que  hace |Yacc|, lee alg\'un texto sobre ello (yo no voy a explicarlo aqu\'{\i}).

\espacio
B\'asicamente, puedes escribir ficheros |.y| como siempre,  s\'olo que donde
las acciones sol\'{\i}an escribirse en~C,  ahora puedes escribirlas en~E\null{}.
Mira el ejemplo |Src/Yacc/bcalc.y|.

\Ejemplos
&|1> eyacc bcalc.y|\cr
\fin
produce un fichero |yyparse.e|
\ejemplos
&|1> ec yyparse|\cr
\fin
genera un m\'odulo,  el cual s\'olo contiene la funci\'on  |yyparse()|.  El resto
del {\it como mediar con Yacc\/} debe ser an\'alogo al~C.

\espacio
({\it tengo a medias una conversi\'on de Lex a E-Lex, aunque no acabada.}\/)

\Espacio
E-Yacc  es  una  modificaci\'on  del  Yacc 1.8 de Berkeley, de
|corbett@berkeley.edu|.   La  inclusi\'on  de  esta  versi\'on modificada en la
distribuci\'on  de~E es totalmente legal, ya que el autor dice en el |README|
original de BYacc1.8:

\espacio
{\sl ``Berkeley  Yacc is  in  the  public  domain.  The data  structures  and
algorithms  used in  Berkeley Yacc  are all  either taken  from documents
available to the  general public or are inventions of  the author. Anyone
may freely  distribute source  or binary forms  of Berkeley  Yacc whether
unchanged or  modified. Distributers  may charge  whatever fees  they can
obtain  for Berkeley  Yacc. Programs  generated by  Berkeley Yacc  may be
distributed freely.''}\nota{No veo ning\'un inter\'es en  realizar la traducci\'on de esto,
si no piensas igual, d\'{\i}melo:\hfil\break |u0868551@oboe.etsiig.uniovi.es|\qquad Antonio J. Gomez Glez.}


\seccion bin/SrcGen.
{\ninesl (Esta utilidad  no ha sido actualizada  para funcionar mejor con el
 sistema de m\'odulos de~E, todav\'{\i}a  genera el c\'odigo fuente llano (el cual
 se  incorpora  facilmente en cualquier  m\'odulo).  S\'olo la actualizar\'e si
 hay mucha demanda ello.  Si quieres incluir un GUI decente en tu aplicaci\'on
 echa un vistazo tambi\'en a {\ninett modules/tools/EasyGUI.m}, o a  kits  m\'as
 recientes como {\ninett BGUI} de Jan van den Baard, autor de GadToolBox.)}

\espacio
|SrcGen|, generador de fuente GadToolBox de para E: versi\'on beta

\espacio
Necesitar\'as GadToolBox v2.0 o superior, y tener la |gadtoolsbox.library|
que  viene  con  \'el en tu |LIBS:|.  Ahora, crea con GTB alg\'un ejemplo simple
(una  ventana  con unos pocos gadgets\b/menus etc.), gr\'abalo como |bla| (el
nombre del fichero ser\'a |bla.gui|), y teclea:
\ejemplos
&|1> SrcGen bla|\cr
&|1> EC bla|\cr
&|1> bla|\cr
\finsma
|bla.e| tendr\'a las rutinas de apertura de tu interface,  as\'{\i} como algunas
rutinas  para  manejar mensajes IDCMP, errores,~\dots, y un |main()| sencillo
que  s\'olamente  espera  por  una  selecci\'on.   Ah\'{\i} puedes poner tu propio
c\'odigo.   Mira  el  patr\'on de la l\'{\i}nea de comandos para ver como se evita
que |SrcGen| genere esas rutinas.

\espacio
Eso  es para  todo  lo  que sirve.  Si  tienes problemas,  simplemente
comprueba el c\'odigo que se gener\'o.


\seccion bin/EBuild.
|EBuild| es una copia de |Make|, y funciona de forma similar.  |EBuild| es
una  utilidad  que  te  ayuda  a  recompilar las partes necesarias de una
aplicaci\'on  grande  despu\'es de modificarla.  Escribes un fichero |.build|
en  el  directorio  que  contiene los fuentes de tu proyecto.  El fichero
contiene  informaci\'on  sobre  qu\'e  fuentes  dependen  de qu\'e otros, y qu\'e
acciones  se  deben llevar a cabo si es necesario reconstruir un m\'odulo o
un  ejecutable.   |EBuild| comprueba las fechas de los ficheros para ver si
se  ha  modificado  un fuente  despu\'es  de la \'utima compilaci\'on,  y si el
fuente  usa  m\'odulos  que tambi\'en  han sido modificados,  compilando esos
\'ultimos primero.

\espacio
La sintaxis es como la del make de Unix.  En resumen,  ``|#|'' precede
l\'{\i}neas con comentarios, y en:
\ejemplos
& |objetivo: dep1 dep2 ...|\cr
& |  accion1|\cr
& |  accion2|\cr
& |  ...|\cr
\fin
|objetivo| es el fichero resultado del  que estamos hablando, en la mayor\'{\i}a
de los casos un ejecutable o  un m\'odulo, aunque puede ser cualquier cosa.
Tras los  ``|:|''  puedes  escribir todos los ficheros  de  los que  depende,
probablemente su fuente, y otros m\'odulos.  Las acciones de las l\'{\i}neas que
le siguen son  comandos de AmigaDos normales,  y es necesario precederlos
de al menos un espacio o un tabulador para distinguirlas de objetivos.
\Ejemplos
& |bla: bla.e defs.m|\cr
& |     ec bla quiet|\cr
\fin
este sencillo ejemplo recompilar\'a |bla.e| si ha sido modificado,  o si
|defs.m| ha cambiado.

\espacio
Si  tecleas |EBuild|  sin argumentos,  |EBuild| se asegurar\'a  de que  el
primer objetivo est\'e actualizado.  Por otra parte, puedes darle las siguientes
opciones:
\ejemplos
&|TARGET,FROM/K,FORCE/S:|\cr
\finsma
Si das un |TARGET|\nota{objetivo},  |EBuild| empezar\'a con otro objetivo.  |FROM|
te permite usar otro fichero que no sea |.build|,  y  |FORCE|  reconstruir\'a
todo, independientemente de si era necesario o no.  Veamos un ejemplo:
\ejemplos
&|# fichero build de prueba|\cr
\Esptab
&|all:    bla burp|\cr
&|defs.m: defs.e|\cr
&|        ec defs quiet|\cr
&|bla:    bla.e defs.m|\cr
&|        ec bla quiet|\cr
&|burp:   burp.e|\cr
&|        ec burp quiet|\cr
&|limpia:|\cr
&|        delete defs.m bla burp|\cr
\fin
este fichero build es sobre dos programas, |bla| y |burp|,  de los cuales |bla|
tambi\'en depende de un m\'odulo |defs.m|.  Incorpora un objetivo extra no real
|limpia|  de forma que puedas escribir |EBuild limpia|  para borrar todos
los ficheros generados.

\espacio
Se pueden a\~nadir  otras  dependencias  y  acciones con facilidad.  Por
ejemplo, si tu proyecto usa un analizador generado por E-Yacc:
\begintt
yyparse.m: parser.y
           eyacc parser.y
           ec yyparse quiet
\endtt

\espacio
O  si incorpora c\'odigo de macro-ensamblador como m\'odulo de herramienta
usado a menudo:
\begintt
blerk.m: blerk.s
         a68k blerk.s
         o2m blerk
         copy blerk.m emodules:tools
         flushcache tools/blerk
\endtt

\espacio
En  el momento  en el que logres  conocer |EBuild|,  descubrir\'as que  lo
puedes  usar  para m\'as  prop\'ositos  a  parte  de \'este.  M\'{\i}ralo  como  una
herramienta de scripts inteligente.

\espacio
Si quieres descubrir  en detalle de lo que puede  hacer |EBuild|, lee la
documentaci\'on de alg\'un make de Unix,  ya que  |EBuild| es, de alguna forma,
compatible con \'el.  Lo que de momento no hace es:
\item{$-$} eliminar dependencias c\'{\i}clicas.
\item{$-$} permitir ``|\|'' al final de una l\'{\i}nea para reglas m\'as largas.
\item{$-$} definiciones constantes.

\espacio
Jason  Hulance  ha  actualizado  |EBuild|   para  la  versi\'on  v3.1  del
compilador  de~E,  para  corregir  el  error  que ejecutaba  acciones  en
orden inverso.  Tambi\'en  cambi\'o la  ejecuci\'on de  la acci\'on  a un  script
(transparente).  En ese script a la  variable |target| se le  da el valor
del objetivo actual.  Por ejemplo:
\begintt
test:   test.e
        ec "$target"
        if warn
                echo "Error: fallo la compilacion"
        else
                echo "Compilado OK... ejecutando"
                "$target"
        endif
\endtt
que equivale al siguiente c\'odigo del |EBuild| antiguo, aunque permite m\'as cosas.
\begintt
all:    test
        echo "ok, ejecutando:"
        test

test:   test.e
        ec -q test
\endtt


\seccion EE / Aprof.
({\ninesl Estos se describen en su propia documentaci\'on en el directorio {\ninett tools}.}\/)


\seccion EDBG.
|EDBG| es el depurador e nivel de  fuente de~E\null{}.  Para  usarlo
compila\nota{{\bf No} distribuyas un programa en el que alguna parte ha sido compilada
con  |DEBUG/S|  (puedes comprobarlo con  |ShowHunk|,  no debe contener ning\'un
|hunk_debug|).  Los programas con informaci\'on de depuraci\'on se compilan con
|NOP|s extra  para facilitar la  depuraci\'on, lo cual  no es deseable  en el
c\'odigo final.} tu fuente con la opci\'on |DEBUG| (esto funciona tanto para el
programa principal como para los m\'odulos), lo cual a\~nadir\'a informaci\'on de
depuraci\'on en tu ejecutable\b/m\'odulo.

\espacio
Aseg\'urate  siempre de  que tanto  el c\'odigo  fuente como  el compilado
est\'an en el directorio actual, entonces lanza |EDBG| con:
\ejemplos
&|1> EDBG nombreejecutable|\cr
\fin
\Ejemplos
patr\'on:&|EXECUTABLE/A,PUBSCREEN/K:|\cr
\fin
con |PUBSCREEN|  puedes  hacer que |EDBG| corra en cualquier lugar
(|PUBSCREEN=Workbench| para que funcione en el Workbench).  Por omisi\'on |EDBG|
abre  su  propia pantalla, la cual es una copia del Workbench en tama\~no y
modo de pantalla.  |EDBG| funciona bien en la tarjeta gr\'afica Picasso,~\dots

\noin |EDBG| abre una ventana para cada  fuente en tu proyecto, y empezar\'a con
el que contiene a |main()|.  Desde la  que puedes recorrer tu  c\'odigo, y se
abrir\'an ventanas autom\'aticamente cuando sean necesarias. Cuando el c\'odigo
no tiene  un fuente adjunto,  s\'olo se puede ejecutar  (lo cual es  \'util a
veces, si no es necesario depurarlo).

\noin Desde  ese  momento  todo  es  bastante  intuitivo.  Los  botones  m\'as
importantes son las dos primeras im\'agenes, que son el de {\sl recorre sobre/en}
({\sl step over/in}\/).  Recorre en sigue el c\'odigo paso a paso seg\'un se ejecuta,
recorre sobre hace lo mismo pero no entra en las subrutinas.
(!`Pru\'ebalo!, el depurador es bastante intuitivo).

\noin Otras funciones sacan ventanas de memoria o registros, y algunas otras
funciones  (algunas sin implementar).  Una importante es  hacer un  doble
click  en nombres  de variables:  \'esto nos  mostrar\'a su  contenido en  la
ventana temporal (ya lo s\'e, esto ser\'a algo m\'as c\'omodo en el futuro).

\noin Pegas:
\item{$-$} El programa que se depura corre en la misma tarea que |EDBG|\null{}. Esto quiere
  decir que todo c\'odigo que haga cosas especiales en la tarea  deber\'a ser
  cuidadoso.  Un ejemplo es |Forbid()|.
\item{$-$} Un caso especial es |ReadArgs()|.  Dado que  |EDBG| ya ley\'o los argumentos,
  una  llamada del  programa  que se  depura causar\'a  una  lectura de  la
  consola. De forma que puedes teclear convenientemente los argumentos de
  tu programa en la l\'{\i}nea de comandos y pulsar \<|return|>.

\Espacio
|EDBG| todav\'{\i}a es algo beta, aunque ya bastante  \'util.  Le faltan gran
cantidad de funciones, y tendr\'as que esperar algo antes de que se lleguen
a implementar.  (por lo  tanto,  no  vengas a  contarme que ``{\sl X no
funciona}'' o que ``{\sl |EDBG| necesita X}'' porque  {\bf ya lo se}.)

\Espacio
\subsec Las opciones |LINEDEBUG| y |SYM|.
La  opci\'on |LINEDEBUG|  a\~nade  informaci\'on |linedebug|  a tu  ejecutable
(para cada l\'{\i}nea de c\'odigo dentro de un |PROC|)\null. |EDBG| necesita esta opci\'on,
aunque  la  opci\'on  |DEBUG|  la  activa  de forma autom\'atica.  |LINEDEBUG| es
parcialmente  compatible  con  el  |HUNK_DEBUG|  |"LINE"| producido por otros
compiladores\b/ensambladores,  por  lo que tambi\'en puede ser \'util con otras
herramientas  de  depuraci\'on.   La  opci\'on |SYM| no es necesaria para |EDBG|,
pero puede ser \'util para otros, como |AProf| o desensambladores.

\Espacio
\subsec Errores m\'as graves conocidos.
\item{$-$} no puedes  desplazar la l\'{\i}nea  actual fuera  de la parte visible en una
  ventana de fuente porque |EDBG| intenta mantenerla a la vista.
\item{$-$} muchos otros~\dots, probablemente


\seccion PreProcesador de |EC|.
|EC| tiene un preprocesador interno que ofrece substituciones de macros
y compilaci\'on condicional.  Estas no son caracter\'{\i}sticas  del lenguaje~E,
sino que se han integrado en |EC| por velocidad y flexibilidad.

\subsec Activando el preprocesador.
Hasta que no escribas:
\ejemplos
&|OPT PREPROCESS|\cr
\fin
|EC|  se comportar\'a  como siempre.  Esta  |OPT| es  necesaria para  cualquier
caracter\'{\i}stica relacionada con el preprocesador.

\subsec Macros.
El  macropreprocesador  es compatible con |Mac2E| y el prepocesador del~C\null{}.  Puedes
definir macros con:
\begintt
#define NOMBREMACRO
#define NOMBREMACRO CUERPO
#define NOMBREMACRO(ARG, ...) CUERPO
#define NOMBREMACRO(ARG, ...) CUERPO \
        RESTO DEL CUERPO
\endtt
|NOMBREMACRO| y |ARG| pueden tener tanto may\'usculas como min\'usculas, y pueden
contener |_|  y  |0-9|  como siempre.  Se pueden a\~nadir espacios en cualquier
lugar menos entre |NOMBREMACRO| y |(|,  ya que sino |EC| no podr\'{\i}a distinguir
entre argumentos y el cuerpo.

\noin El |CUERPO| puede contener cada uno  de los argumentos tantas veces como
quiera.  Una macro puede continuar en la l\'{\i}nea siguiente si se precede el
{\sl final-de-l\'{\i}nea}\/ con un |\|.  Una macro sin cuerpo puede ser \'util en
combinaci\'on con compilaci\'on condicional.

\espacio
Los identificadores de macro tienen precedencia sobre los dem\'as.
Las  macros  definidas en un m\'odulo s\'olo se guardan en el m\'odulo si se
activa  |OPT EXPORT| (|#define|  no  se puede preceder con |EXPORT|).  Si eso
representa  un  problema,  mant\'en  las macros juntas en su propio m\'odulo.
Las macros de los m\'odulos se pueden usar en c\'odigo diferente  simplemente
con importarlas con |MODULE|, y usando |OPT PREPROCESS|.

\subsec Usando una macro.
El uso  de |NOMBREMACRO| en cualquier  punto del  programa har\'a  que se
inserte el |CUERPO| de la macro en ese punto. Ten en cuenta que \'esta es una
substituci\'on de texto,  y tiene poco que ver con la sintaxis de~E en s\'{\i}.
Si las macros  tienen argumentos,  \'estos se insertar\'an en sus respectivos
lugares del cuerpo de la macro. Si el cuerpo (o los argumentos) contienen
m\'as macros, \'estos se expander\'an m\'as tarde.

\noin Ejemplo:
\begintt
#define MAX(x,y) (IF x>y THEN x ELSE y)
WriteF('el mayor = \d\n',MAX(10,a))
\endtt
es lo mismo que escribir:
\begintt
WriteF('el mayor = \d\n',(IF 10>a THEN 10 ELSE a))
\endtt

\espacio
Esto nos muestra el peligro de las macros:  escribir
|MAX(computacion_grande(),1)| generar\'a c\'odigo que ejecuta
|computacion_grande()| dos veces, ya que
simplemente se copia  textualmente.  Ten cuidado con eso.

\subsec Compilaci\'on condicional.
Esto puede ser \'util si quieres decidir en el momento de la compilaci\'on
qu\'e parte de tu c\'odigo quieres usar.  Veamos primero un ejemplo:
\begintt
#define DEPURA
->#define DEPURABIEN

#ifdef DEPURA
  WriteF('entrando en bla() con x = \d\n',x)
#ifdef DEPURABIEN
  WriteF('volcando memoria...\n')
  /* ... */
#endif
#endif
\endtt

\Espacio
Su sintaxis es:
\ejemplos
& |#ifdef NOMBREMACRO|\cr
\fin
o
\ejemplos
& |#ifndef NOMBREMACRO|\cr
\fin
el fragmento de c\'odigo  que lo sigue se, o no se compilar\'a dependiendo de
si |NOMBREMACRO| fu\'e definido.  Puedes hacer esto simplemente con:
\ejemplos
& |#define MIBANDERA|\cr
\fin
o algo parecido.  Finaliza el bloque compilado condicionalmente con:
\ejemplos
& |#endif|\cr
\fin
adem\'as, este tipo de bloques se puede anidar como se vió en el ejemplo.



\endchapter\saltacap
\beginchapter Ap\'endice A. Correspondencia\\con otros\\lenguajes

\ninepoint
En este ap\'endice veremos una serie de tablas que tratan de mostrar la equivalencia
de diferentes elementos de E con otros lenguajes.
En las  dos primeras columnas  aparecer\'an las equivalencias entre E  y
AnsiC/C++, la  tercera columna  est\'a reservada  para un  tercer lenguaje.
La mayor parte de las veces usar\'e Pascal en esa  columna, aunque si una caracter\'{\i}stica
lo pide, usar\'e otros (LISP, por ejemplo, con expresiones entrecomilladas,
Ada con excepciones, etc~\dots)

\noin No te tomes muy en serio estas tablas, ya que cada lenguaje tiene sus peculiaridades.

\medskip


\halign to\hsize{\tt#\hfil\tabskip=2em plus30em minus1em& #\hfil& \tt#\hfil\tabskip=0pt\cr
\bartab
\multispan3\sc ESTRUCTURA/SENTENCIAS\hfil\cr
\sc E&                    \sc C/C++ &               \sc Pascal \cr
\bartab
PROC x() &               |int x() {| &              FUNCTION x: INTEGER; \cr
PROC x(y,z) &            |int x(y,z) {| &           FUNCTION x(y,z:INTEGER):INTEGER; \cr
PROC x(y=1) &            |int x(y=1) {| &           \rm -- \cr
ENDPROC &                |return 0; };| &           x:=0; END; \cr
ENDPROC e &              |return e; };| &           x:=e; END; \cr
ENDPROC e,f,g &          -- &                       \rm -- \cr
RETURN e &               |return e;| &              \rm ? \cr
\Esptab
IF e &                   |if(e) {| &                IF e THEN BEGIN \cr
ELSEIF e &               |} else if(e) {| &         END ELSE IF e THEN BEGIN \cr
ELSE &                   |} else {| &               END ELSE BEGIN \cr
ENDIF &                  |};| &                     END; \cr
IF e THEN s &            |if(e) s;| &               IF e THEN s; \cr
IF e THEN s ELSE t &     |if(e) s else t;| &        IF e THEN s ELSE t; \cr
\Esptab
FOR x:=e TO f &          --$^{(1)}$ &               FOR x:=e TO f DO BEGIN \cr
FOR x:=e TO f STEP i &   -- &                       \rm --$^{(2)}$ \cr
EXIT e &                 |if(e) break;| &           \rm -- \cr
ENDFOR &                 -- &                       END; \cr
FOR x:=e TO f DO s &     -- &                       FOR x:=e TO f DO s; \cr
\Esptab
WHILE e &                |while(e) {| &             WHILE e DO BEGIN \cr
EXIT e &                 |if(e) break;| &           \rm -- \cr
ENDWHILE &               |};| &                     END; \cr
WHILE e DO s &           |while(e) s;| &            WHILE e DO s; \cr
s; WHILE e &             |for(s;e;u) {| &           s; WHILE e DO BEGIN \cr
\quad t; u &             |  t;| &                   \quad t; u \cr
ENDWHILE &               |};| &                     END; \cr
\Esptab
REPEAT &                 |do {| &                   REPEAT \cr
UNTIL e &                |} while(!e);| &           UNTIL e; \cr
\Esptab
LOOP &                   |for(;;) {| &              WHILE TRUE DO BEGIN\rm (?) \cr
ENDLOOP &                |};| &                     END; \cr
\Esptab
SELECT x &               |switch(x) {| &            CASE x OF \cr
SELECT x OF y &          |switch(x) {| &            CASE x OF \cr
CASE 1; s... &           |case 1: s...; break| &    1: BEGIN s... END \cr
CASE a+1 &               -- &                       \rm -- \cr
CASE 1,2,3 &             |case 1: case 2: case3:| & 1,2,3: \cr
CASE "a".."z" &          -- &                       \rm -- \cr
ENDSELECT &              |};| &                     END \cr
\Esptab
INC x &                  |x++;| &                   x:=x+1; (INC()) \cr
DEC x &                  |x--;| &                   x:=x-1; (DEC()) \cr
JUMP lab &               |goto lab;| &              GOTO lab; \cr
x:=e &                   |x=e;| &                   x:=e; \cr
/* */ &                  |/* */| &                  |{ }| \cr
-> &                     |//| &                     \rm -- \cr
\bartab
\multispan3$^{(1)}$ mira |WHILE|; C no tiene |FOR|, |for| es otra forma de escribir |while|\hfil\cr
\multispan3$^{(2)}$ s\'olo |STEP -1| con |DOWNTO|\hfil\cr
}


\bigskip


\halign to\hsize{\tt#\hfil\tabskip=2em plus30em minus1em& #\hfil& \tt#\hfil\tabskip=0pt\cr
\bartab
\multispan3\sc VALORES\hfil\cr
\sc E&                    \sc C/C++&              \sc Pascal\cr
\bartab
1 &                     |1| &                      1 \cr
1.0 &                   |1.0| &                    1.0 \cr
\$1 &                   |0x1| &                    \rm ? \cr
\%1 &                   ? &                        \rm ? \cr
"a" &                   |'a'| &                    chr(97) (?) \cr
'blabla' &              |"blabla"|&                'blabla' \cr
[1,2,3] &               --$^{(1)}$ &               \rm -- \cr
[1,2,3]:INT &           -- &                       \rm -- \cr
\bartab
\multispan3$^{(1)}$ |mifunc([1,2,3]) --> int temp[]={1,2,3}; mifunc(temp);|\hfil\cr
}


\medskip


\halign to\hsize{\tt#\hfil\tabskip=2em plus30em minus1em& #\hfil& \tt#\hfil\tabskip=0pt\cr
\bartab
\multispan3\sc OPERADORES\hfil\cr
\sc E&                   \sc C/C++&              \sc Pascal\cr
\bartab
+ - * / &                |+ - * /| &              + - * DIV \cr
= <> > < >= <= &         |== != > < >= <=| &      = <> > < >= <= \cr
AND OR  (log) &          |&& |\|\| &              and or \cr
AND OR  (bit) &          |& |\| &                 \rm ? \cr
SIZEOF x &               |sizeof(x)| &            \rm -- \cr
`e &                     --&                      --$^{ (1)}$ \cr
\^{}x $^{ (4)}$ &        |*x| &                   ... \cr
$\{$x$\}$ &              |&x| &                   ... \cr
x++ &                    |x++| &                  \rm -- \cr
x-- &                    |--x| &                  \rm -- \cr
-x &                     |-x| &                   -x \cr
IF e THEN f ELSE g &     |e ? f : g| &            \rm -- \cr
x.y &                    |x->y| &                 x\^{}.y \cr
\rm -- &                 |x.y| &                  x.y \cr
x.y.z &                  |x->y->z| &              x\^{}.y\^{}.z \cr
x:=e &                   |x=e| &                  \rm -- \cr
e BUT f &                |(e,f)| &                \rm -- \cr
x[] &                    |x[0] *x|$^{(2)}$ &      x[0] \cr
x[1] &                   |x[1]| &                 x[1] \cr
x[1] $^{(3)}$ &          |&x[1]| &               \rm ? \cr
x[1].y &                 |x[1]->y| &              x[1]\^{}.y \cr
x[]++ &                  |*x++| &                 \rm -- \cr
x[1].y++ &               |*(x+1)++| &             \rm -- \cr
x::y.a &                 |((y *)x)->a| &          \rm -- \cr
x.y::z.a &               |((z *)x->y)->a| &       \rm -- \cr
\bartab
\multispan3$^{(1)}$ mira expresiones entrecomilladas.\hfil\cr
\multispan3$^{(2)}$ otros tambi\'en mantienen la equivalencia entre |*(x+e)| y |x[e]|.\hfil\cr
\multispan3$^{(3)}$ con |ARRAY OF |\<objeto>\hfil\cr
\multispan3$^{(4)}$ {\bf s\'olo} para pasar por referencia. En otro caso: |[]|\hfil\cr
}


\medskip


\halign to\hsize{\tt#\hfil\tabskip=2em plus30em minus1em& #\hfil\tabskip=0pt\cr
\bartab
\multispan2\sc PROGRAMACION ORIENTADA A OBJETOS\hfil\cr
\sc E&                    \sc C/C++\cr
\bartab
OBJECT x &                 |class x {| \cr
OBJECT x OF y &            |class x : y {| \cr
self.i &                   |this->i| \cr
PROC a OF x IS self.i &    |virtual int x::a() { return i; }| \cr
\rm -- &                   |int x::a() { return i; }| \cr
PROC a OF x IS EMPTY &     |virtual int x::a() =0| \cr
PUBLIC &                   |public:| \cr
a.method$^{(1)}$ &         |a->method|$^{(1)}$ \cr
\bartab
\multispan2$^{(1)}$ mira tambi\'en en el siguiente apartado en NEW\hfil\cr
}

\medskip


\halign to\hsize{\tt#\hfil\tabskip=2em plus30em minus1em& #\hfil& \tt#\hfil\tabskip=0pt\cr
\bartab
\multispan3\sc CONSTANTES/TIPOS\hfil\cr
\sc E&                    \sc C/C++&              \sc Pascal\cr
\bartab
CONST X=1 &             |#define X 1| &           CONST X=1; \cr
&                       |const int X=1;| \cr
ENUM X,Y,Z &            |#define X 0 (etc.)| &    TYPE x=(X,Y,Z); \cr
&                       |enum x{X,Y,Z};| \cr
SET X,Y,Z &             -- &                      TYPE x=SET OF (X,Y,Z); \cr
DEF &                   &                         VAR \cr
x &                     |int x; (or: long x;)| &  x:INTEGER; \cr
x:LONG &                |int x;| &                x:INTEGER; \cr
x:PTR TO y &            |struct y* x;| &          x:\^{}y; \cr
x:y &                   |struct y x;| &           x:y; \cr
x[10]:ARRAY OF y &      |struct y x[10];| &       x:ARRAY [0..9] OF y; \cr
x[10]:STRING &          --$^{(1)}$ &              x:STRING[10];$^{(2)}$ \cr
x[10]:LIST &            --$^{(1)}$ &              \rm --$^{(1)}$ \cr
x:REG &                 |register int x;| \cr
OBJECT x &              |struct x {|$^{(3)}$ &    TYPE x = RECORD \cr
\qquad y:CHAR,z:INT &   |  char y; short z;| &    \qquad y:CHAR; z:INTEGER; \cr
ENDOBJECT &             |};| &                    END; \cr
\bartab
\multispan3$^{(1)}$ en C sim\'ulalo con un arreglo de char/int con comprobaci\'on de rango propia.\hfil\cr
\multispan3$^{(2)}$ no en Wirth Pascal, pero disponible en todos los dialectos populares.\hfil\cr
\multispan3$^{(3)}$ o clase p\'ublica.\hfil\cr
}


\medskip

\halign to\hsize{\tt#\hfil\tabskip=2em plus30em minus1em& #\hfil& \tt#\hfil\tabskip=0pt\cr
\bartab
\multispan3\sc FUNCIONES PREDIFINIDAS Y RESERVA DE MEMORIA\hfil\cr
\multispan3\sl (s\'olo algunas funciones como ejemplo.)\hfil\cr
\sc E&                    \sc C/C++&              \sc Pascal\cr
\bartab
WriteF(fs,...) &         |printf(fs,...);| &      WriteLn(a,b,...); \cr
&                        |cout << a << b ... ;| \cr
ReadStr(f,s) &           |scanf(fs,...)| &        ReadLn(s) \cr
Val(s) &                 &                        Val() \cr
&                        |cin >> s;| \cr
StrCopy(s,s,n)$^{(1)}$ & |strcpy(s,s)| &          s:=s;$^{(2)}$ \cr
\Esptab
Mod(e,e) &               |e%e| &                  e MOD e \cr
Shl(e,n) &               |e<<n| &                 Shl() \cr
Long(e) &                -- &                     \rm -- \cr
\Esptab
p:=New(e) &              |p=malloc(e);| &         New(p); \cr
NEW p &                  |p=new type;| \cr
NEW p.constr() &         |p=new constr()| &       \rm -- \cr
NEW [e,f,g] &            -- &                     \rm -- \cr
Dispose(p) &             |free(p);| &             Dispose(p); \cr
END p &                  |delete p;| \cr
\bartab
\multispan3$^{(1)}$ aseg\'urate de convertir los arreglos de char en |STRING|s de verdad. \hfil\cr
\multispan3$^{(2)}$ no se que funci\'on se necesita en el caso de punteros.\hfil\cr
}


\medskip


\halign to\hsize{\tt#\hfil\tabskip=2em plus30em minus1em& #\hfil& \tt#\hfil\tabskip=0pt\cr
\bartab
\multispan3\sc UNIFICCION Y CELDAS LISP\hfil\cr
\sc E&                   \sc LISP&              \sc PROLOG\cr
\bartab
<1\|2> &                 |(1 . 2)| &            [1\|2] \cr
<1,2,3> &                |(1 2 3)| &            [1,2,3] \cr
<1,2\|3> &               |(1 2 . 3)| &          [1,2\|3] \cr
\esptab
\sc E&                   \sc HASKELL&           \sc PROLOG\cr
\bartab
e <=> <x\|y> &           |(x:y) = e| &          e = [X\|Y] \cr
e <=> <1,2,x> &          |[1,2,x] = e| &        e = [1,2,X] \cr
e <=> [1,x] &            -- &                   \rm -- \cr
\bartab
}


\bigskip


\halign to\hsize{\tt#\hfil\tabskip=2em plus30em minus1em& #\hfil& \tt#\hfil\tabskip=0pt\cr
\bartab
\multispan3\sc EXPRESIONES ENTRECOMILLADAS\hfil\cr
\esptab
\sc E&                    \sc LISP&              \sc MIRANDA\cr
\bartab
`e &                    |(QUOTE e)  'e| &        $^{(3)}$ \cr
&                       |(LAMBDA () e)| &        $^{(1)}$ \cr
`x+y &                  |'(+ x y)| \cr
Eval(`e) &              |(EVAL `e)| \cr
ForAll(v,l,`e) &        --$^{(2)}$ \cr
MapList(v,l,l,`e) &     |(MAPCAR (LAMBDA (V) E) L)| & map ($\backslash$v->e) l \cr
\bartab
\multispan3$^{(1)}$ realmente |QUOTE|, pero usado a veces donde en |LISP| se usar\'{\i}a |LAMBDA|,
    como en |MapList|()\hfil\cr
\multispan3$^{(2)}$ ni siquiera en ProLog, mira en otros lenguajes de l\'ogica.\hfil\cr
\multispan3$^{(3)}$ en su lugar se usar\'{\i}a 'lazyness'\hfil\cr
}

\espacio
Ejemplo:
\Ejemplos
\qquad E: &       |MapList({x},[1,2,3,4],a,`x*x)| \cr
\qquad MIRANDA: & |map (\x->x*x) [1,2,3,4]| \cr
\qquad LISP: &    |(MAPCAR (LAMBDA (X) (* X X) `(1 2 3 4))| \cr
\fin


\bigskip


\halign to\hsize{\tt#\hfil\tabskip=2em plus30em minus1em& #\hfil& \tt#\hfil\tabskip=0pt\cr
\bartab
\multispan3\sc EXCEPCIONES\hfil\cr
\esptab
\sc E&                    \sc C/C++&                 \sc ADA\cr
\bartab
PROC x() HANDLE &         |int x() { try {| &        function x is begin \cr
EXCEPT &                  |} catch (exc) {|$^{(1)}$& exception \cr
EXCEPT DO &               -- &                       \rm -- \cr
ENDPROC &                 |}};| &                    end x; \cr
\Esptab
Raise(e) &                |throw e;| &               raise e; \cr
Throw(e,f) &              ? &                        \rm -- \cr
ReThrow() &               |throw e;| &               raise e; \cr
RAISE "MEM" IF New()=0 &  -- &                       \rm --$^{(2)}$ \cr
\bartab
\multispan3$^{(1)}$ |catch| s\'olo controla un excepci\'on concreta, es bastante diferente de como se usan los\hfil\cr
\multispan3 \quad manejadores de excepciones generales en E. \hfil\cr
\multispan3$^{(2)}$ el sistema en tiempo de ejecuci\'on lanza algunas excepciones, pero no estoy seguro de\hfil\cr
\multispan3 \quad si se pueden {\it definir} excepciones lanzadas autom\'aticamente en ADA. \hfil\cr
}


\bigskip

\noin En las tablas aparec\'{\i}an una serie de abreviaturas y signos cuyo significado es
el siguiente:
\Ejemplos
\qquad --&      = caracter\'{\i}stica no disponible en el lenguaje en cuesti\'on.\cr
\qquad ?&       = el autor no tiene idea a qu\'e se traduce esa caracter\'{\i}stica. (o no est\'a seguro).\cr
\qquad ...&     = puede estar disponible, pero no en relaci\'on 1:1 que la haga interesante.\cr
\qquad x,y,z&   = indetificadores arbritarios.\cr
\qquad e,f,g&   = expresiones arbritarias.\cr
\qquad s,t,u&   = sentencias arbritarias.\cr
\qquad i,j,k&   = enteros arbritarios.\cr
\qquad etc.\cr
\fin



\endchapter\saltacap
\beginchapter Ap\'endice B. FAQ

\ninepoint
   Esta  lista-FAQ (Frequently Asked Questions\nota{Preguntas realizadas
con Frecuencia, de fecha 1-10-04 al 1-12-94}) ha sido recogida mirando en el
email viejo y escongiendo aquellas preguntas que se repet\'{\i}an una y otra vez.
\medskip
\parindent=0pt
\advance\leftskip by15pt
\advance\rightskip by15pt

{\bf Compilador/Enlazador/Ejecutables}

\pregunta{?`C\'omo puedo enlazar c\'odigo~E con otros lenguajes\b/usar un formato de
          objeto estandard?}

  La conversi\'on entre |.m| y |.o| no  es en realidad un  gran problema,  como
  podemos ver con la utilidad |o2m|,  que permite la cooperaci\'on entre~E  y
  macro-ensambladores bastante  bien.  El  problema con el~C radica  en el
  c\'odigo compilado,  no  el  formato del  fichero.  A no ser  C~trivial,
  cualquier c\'odigo compilado en~C  har\'a referencia a cosas como |_DOSBase|,
  librer\'{\i}as  de enlace,  bases  de  pila,  y otras  cosas  del c\'odigo  de
  inicializaci\'on  que~E  proporciona  de una  forma  algo diferente,  por
  ejemplo, el c\'odigo  de inicializaci\'on de E es bastante  diferente de el
  de los compiladores de~C\null{}. Estos problemas pueden aparecer incluso entre
  dos  compiladores de~C\null{}.  Si  puedes conseguir  que tu  compilador de~C
  genere un |.o|  sin referencias externas, etc, entonces podr\'as enlazarlo
  con~E (yo ya lo he hecho una vez con MaxonC++).

\pregunta{?`Puedo enlazar con \/|amiga.lib|?}

  De momento no.  Aunque en menor medida, esto tiene los mismos problemas
  que los  ficheros |.o|,  aunque con la ayuda de  un ensamblador y  |o2m| se
  podr\'{\i}a traducir un fichero |.lib| a |.m|, de hecho, ya se ha realizado para
  algunas.  S\'olo es cuesti\'on de tiempo  que alguien lo haga  para (partes
  de) |amiga.lib|.

\pregunta{?`Se puede hacer residente el c\'odigo de~E?}

  Practicamente {\bf todo}  el c\'odigo de E  ya se puede hacer  residente sin la
  ayuda del programador.  Seg\'un creo, la \'unica construcci\'on~E  que puede
  violar \'esto es un lista est\'atica |[]| con una expresi\'on en ella (como |[a]|
  por ejemplo. Con |[1]| y |NEW [a]| van bien).

\pregunta{Tengo una aplicaci\'on con ensamblador en l\'{\i}nea, y con |OPTI/S|
          no funciona bien.  ?`Qu\'e sucede?}

  El ensamblador en l\'{\i}nea puede usar los mismos registros a la vez que el
  opimizador de registros.  Busca en otra parte del documento sobre eso.

\pregunta{He escrito \/|X| tanto en~C como en~E, y la versi\'on en~E es
          \/|Y|~veces m\'as r\'apida\b/lenta. ?`A~qu\'e se debe?}

  No  es f\'acil  hacer una  comparaci\'on  de forma  totalmente objetiva.  A
  menudo, se  puede dar el  caso que alguno de los dos tenga  rutinas m\'as
  optimizadas para  algo (manejo de cadenas, E/S,  etc~\dots).  El uso  de un
  profiler  puede ayudar  a descubrirlo.  Si  el c\'odigo en cuesti\'on  s\'olo
  realiza c\'alculos, no hay ninguna raz\'on por la que alguno de los dos sea
  significativamente m\'as lento que el otro, si se usan correctamente.


\pregunta{He escrito un buen \/|misutils.m|, y aunque s\'olo use una funci\'on
          suya, \/|EC|~lo enlaza todo.  !`No me gusta!.}

  El estilo  de escritura de  m\'odulos en  E es mantenerlos  como unidades
  relativamente peque\~nas,  s\'olo con c\'odigo y datos  relacionados.  (Esto
  tiene m\'as sentido  si sabes que el m\'odulo es  la unidad de ocultamiento
  de datos de~E\null{}).  !`Div\'{\i}delo!

\pregunta{?`Puedo dejar |EC| residente?}

  No, de momento no.  El propio |EC| esta escrito en un estilo de
  ensamblador anticuado, y no se puede hacer residente |;-)|

\Espacio
{\bf Recursos}

\pregunta{En la documentaci\'on no se explican las funciones de
          |intuition.library|,~\dots\quad ?`Por qu\'e?}

  Esas funciones no son parte de E, sino que forman parte del SO de Amiga.
  Como tales,  se describen  en los  documentos de  Commodore,  no en los
  documentos de E\null{}. ``{\sl The AMIGA ROM Kernel Reference Manuals\/}'' son una serie
  de libros publicados  por  Addison Wesley.  Un  buen  lugar por  donde
  empezar es  el libro de  ``{\sl Libraries\/}'' de esa serie,  ISBN~0-201-56774-1.
  Tambi\'en hay otros libros que merecen la pena ser considerados,  como el
  ``{\sl The Amiga Guru Book\/}'' de Ralph Babel.

\pregunta{Me gustar\'{\i}a leer m\'as c\'odigo fuente a parte del que viene con la
          distribuci\'on,  ?`Donde debo buscar?}

  Hay cantidad  de lugares  en los  que mirar,  aunque  el mejor sin duda
  alguna  es {\it Aminet}  (Una colecci\'on de  sites de  FTP  en Internet),  por
  ejemplo |ftp.luth.se|.  En el directorio  |/pub/aminet/dev/e| encontrar\'as
  todo tipo de cosas relacionadas con~E\null{}.  Algunas BBSs  fuera de Internet
  tambi\'en  tienen {\it Aminet},  e incluso hay disponibles  CDROMS\null{}.  Otro  buen
  lugar para recoger  fuentes y hablar con buenos programadores en~E,  es
  la lista  de correo  de~E\null{}.  Env\'{\i}a un email  con ``|HELP|''  en el  cuerpo a
  |amigae-request@bkhouse.cts.com| para escuchar todo sobre  ello.  Tambi\'en
  hay discusiones sobre~E en otras redes ({\it FidoNet},  {\it AmigaNet\/}), series de
  discos de dominio  p\'ublico (EPD en Europa\b/Alemania,  la misma direcci\'on
  que el lugar de registro alem\'an), adem\'as, hay gran cantidad de clubs de
  usuarios, BBS que apoyan~E\null{}.  Simplemente echa un vistazo en tu zona.

\pregunta{He oido hablar de esa lista de correo. ?`Qu\'e tal est\'a?}

  Compruebalo  tu  mismo.  Si  vas en serio  con~E,  es  definitivamente
  imprescindible, adem\'as de que es el primer lugar en el que aparecen las
  noticias sobre~E.

\pregunta{He tenido problemas para introducirme en la lista.  ?`Podr\'{\i}as
          ocuparte tu de eso por mi?}

  Yo  no  tengo,  personalmente, nada que ver con la administraci\'on de la
  lista,  de  forma  que  no  te  puedo  ayudar  m\'as  que cualquier otro.
  Recuerda que el servidor es un proceso autom\'atizado, de forma que debes
  ser preciso en lo que le envias.  No env\'{\i}es correo administrativo  a la
  lista, en su lugar, intenta contactar con el administrador.

\pregunta{Soy nuevo en Internet.  ?`Me ayudar\'{\i}as a conseguir la lista de
          correo, ficheros FTP de {\it Aminet}, etc~\dots?}

  Cosas de  este tipo  van m\'as  all\'a de mi  cometido.  Por favor, intenta
  contactar localmente con alguien.

\pregunta{?`C\'omo se cual es la \'ultima versi\'on y c\'omo la recibo?}

  Si  estas  en  la  lista  de   correo  ser\'as  el  primero  en  saberlo.
  {\it Aminet}  es el  primer lugar  en el  que aparecen  las distribuciones  y
  actualizaciones. Los usuarios registrados obtendr\'an las actualizaciones
  y/o notas de forma autom\'atica en su mbox.

\pregunta{?`C\'omo registrarse?}

  Por favor mira en otra parte de este documento.

\pregunta{?`Existe E para otras plataformas?}

  No  todav\'{\i}a.  Me  he comprometido personalmente  con  un proyecto  para
  realizar compiladores\b/traductores,  y algunos otros tienen proyectos de
  compilador~E para otras plataformas, aunque de momento a\'un no hay nada.

\pregunta{?`Puedo convertirme en un lugar de registro para el pa\'{\i}s~\/|X|?}

  Generalmente  los  lugares los  elijo  yo  mismo  cuando creo  que  es
  necesario y conozco muy bien a alguien en ese pa\'{\i}s.

\pregunta{?`Puedo apoyar E con una BBS / con un club de programaci\'on~\dots?}

  Siempre puedes hacerlo, sin falta de preguntarme.  Aunque por supuesto,
  me gusta tener noticias sobre esfuerzos de ese tipo~\dots

\Espacio
{\bf Programaci\'on}

\pregunta{?`Puedo hacer \/|X| en E?  (donde \/|X| = $\{$\/juegos, autoedici\'on,~\dots$\}$)}

  E es  un lenguaje de programaci\'on  de prop\'osito general,  por lo que no
  deber\'{\i}a haber ning\'un tipo de programa que  no se pueda hacer con~E (con
  alguna rara excepci\'on,  que  est\'a cubierta con  el ensamblador en l\'{\i}nea
  de~E\null{}). Esto no significa que~E est\'e equipado especialmente para ciertos
  tipos  de programas,  es decir,  E~no  tiene funciones  especiales para
  juegos (aunque su extensibilidad permite incorporarlas facilmente).

\pregunta{?`C\'omo creo \/|X| en E?  (donde \/|X| = $\{$\/ventana, manejador de
          interrupciones,~\dots$\}$)}

  Al igual  que en la  pregunta anterior,  E~s\'olo abre la posibilidad de
  escribir lo que quieras, y no siempre tiene una funci\'on espec\'{\i}fica.  En
  el peor  de los casos  eso significar\'a  el usar funciones  dif\'{\i}ciles de
  alguna librer\'{\i}a,  aunque merece la pena meterte en detalle con eso.  Si
  tienes suerte alg\'un  otro programador ya habr\'a  realizado algo parecido
  de lo que puedas aprender.

\pregunta{Por favor escr\'{\i}beme un ejemplo de como hacer \/|X| en~E.}

  Por favor, intente imaginartelo t\'u mismo,  o pregunta a otros programadores de~E.

\pregunta{El compilador no quiere compilar cosas como \/|mipantalla.rastport.bitmap|,
          incluso cuando en general \/|x.y.z| es posible. ?`Por qu\'e?}

  Para poder  hacer referencia al  \'ultimo |bitmap|,  el compilador necesita
  saber el  tipo de la  expresi\'on |mipantalla.rastport|.  Y si miras  en el
  m\'odulo |intuition/screens.m| ver\'as que el campo |rastport| no tiene tipo.

\pregunta{\dots ?`por qu\'e no tenemos nuevos m\'odulos con tipos corregidos?}

  Porque los includes en ensamblador (|.o|) de los cuales se convierten los
  m\'odulos~E no contienen esa informaci\'on.  No se pueden usar los ficheros
  |.h| de~C en su lugar, porque usan de alguna forma otros identificadores,
  y romper\'{\i}a la compatibiladad anterior.

\pregunta{\dots entonces, ?`qu\'e hago?}

  El m\'etodo cl\'asico es poner |x.y|  en un puntero con tipo, y entoces hacer
  referencia a |.z|  desde \'ese.  Con la mutaci\'on de punteros en~v3, tambi\'en
  puedes hacer referencia a \'el directamente (m\'{\i}ralo en otra parte de este
  documento).

\pregunta{Cuando escribo c\'odigo como el siguiente el compilador me lo acepta,
          pero m\'as tarde me da problemas.  ?`Qu\'e hay mal en este c\'odigo?}

  \qquad|DEF s[100]:STRING|\par
  \qquad|s:='mi bonita cadena'|
\smallskip
  Si estas acostumbrado al  {\sc BASIC},  por  ejemplo,  estar\'as acostumbrado a
  usar las cadenas  de la misma forma  que los enteros,  ya que ambos son
  {\sl valores}.  Sin embargo  en~E no  hay variables  cadena  reales en  el
  sentido  del {\sc BASIC},  el  |DEF| anterior  crea un  trozo  de memoria  para
  almacenar  la cadena,  luego fija  la variable  como un  puntero a  esa
  memoria.  El puntero y la memoria son, aparte de la implementaci\'on, dos
  entidades no relacionadas.  A partir del |DEF|, todas las operaciones que
  acceden directamente a  |s| est\'an accediendo al puntero.  La asignaci\'on
  pone la  direccion de  |mi bonita cadena|  en |s|,  sobreescribiendo el
  valor anterior.  La memoria  de cadena  creada por  el |DEF|  se mantiene
  inalterada, y ahora inaccesible ya que no hay ning\'un puntero que apunte
  ella.  Las  funciones  como  |StrCopy()| pueden  usar  ese  puntero  para
  encontrar la memoria real, y rellenarla:

  \qquad|StrCopy(s,'mi bonita cadena')|

  es  correcto.  Por  supuesto,  la asiganci\'on  de  cadenas como punteros
  tambi\'en es de utilidad, por ejemplo,  si s\'olo quieres leer los datos de
  la cadenas, y no hacer nada m\'as con ellos, entonces:

  \qquad|DEF s:PTR TO CHAR|

  no  reserva  ninguna  memoria  para  la cadena,  s\'olo  el  puntero.  La
  asignaci\'on anterior  tendr\'{\i}a sentido ahora.  Todo esto  nos lleva  a la
  diferencia entre punteros y valores (o sem\'antica por valor\b/referencia),
  y es importante que lo entiendas para programar en~E con \'exito.

\pregunta{?`Como retorno un \/|STRING|, |OBJECT|, etc. de una funci\'on?}

  Depende.  Si  s\'olamente  quieres   utilizarlo  como  valor  de  retorno
  temporal,  pasa  una cadena  como  argumento  y  deja que la rutina  la
  rellene.  Si   necesitas  crear  una  cadena\b/objeto   nuevo,  reserv\'alo
  din\'amicamente dentro de la funci\'on, y retorna el puntero.

\Espacio
{\bf Errores}

\pregunta{Recuerdo cuando estaba programando algo que de pronto el compilador
          rompi\'o\b/funcion\'o mal\b/produjo un error interno\b/gener\'o mensajes
          de error err\'oneos.  ?`No deber\'{\i}as hacer algo sobre esto?}

  Si no tengo pistas sobre donde buscar un error, no podr\'e corregirlo. Si
  te  encuentras  con algo  que  estas  seguro de  que  es  un error  del
  compilador, haz una copia del fuente que reproduce el error (si puedes
  recorta el fuente al m\'{\i}mino manteniendo el error) y env\'{\i}amelo con tanta
  informaci\'on como sea posible.  Por ejemplo, los hits de  |Enforcer| de~|EC|
  son bastante \'utiles.

\pregunta{He escrito un programa \/|X|, pero rompe.  Estoy seguro de que no tiene
          errores, por lo que debe ser un error del compilador.}

  Debido a la falta de tipos de E, nunca puedes estar completamente
  seguro de que tu c\'odigo es correcto.  La mayor parte del c\'odigo que se
  me envi\'o con comentarios como el anterior se comprob\'o m\'as tarde que
  eran errores en el c\'odigo, casi siempre debidos a una falta de
  conocimiento de~E\null{}.\quad !`Lee la documentaci\'on, y usa |EDGB|!

\Espacio
{\bf Caracteristicas Futuras}

?`Tendr\'a E~\dots
\pregunta{argumentos en registros?}

  Estoy seguro de que es posible, pero como muchas otras cosas, no es
  prioritario para m\'{\i}.

\pregunta{enlazador de librer\'{\i}a/dispositvo (Library\b/Device)?}

  Ya lo habr\'{\i}a hecho si no fuera por la forma en que~E guarda la
  variables globales (en la pila), lo cual complica las cosas bastante.
  Esto simplemente necesitar\'a algo de tiempo.

\pregunta{herencia m\'ultiple?}

  No es posible en E\null{}.  La herencia m\'ultiple rompe la compatibilidad
  estructural entre objetos, y necesita de una comprobaci\'on de tipos
  bastante severa para resolverlo.

\pregunta{|PROC|s dentro de |PROC|s?}

  No creo.

\pregunta{arreglos multidimensionales?}

  Tampoco lo creo.  Realmente en E no hay nada parecido a un arrreglo,
  s\'olo punteros que apuntan a grandes cantidades de objetos del mismo
  tama\~no.  Para tener arreglos de dos dimensiones, ser\'{\i}a necesario tener
  el concepto de {\sl tama\~no\/} de un arreglo, lo cual~E no tiene.

\pregunta{m\'as aopoyo a |020|/|881|?}

  Si, eventualmente.  Aunque no est\'a entre las primeras cosas a realizar.

\pregunta{sintaxis compatible con C?}

  A menudo la gente est\'a acostumbrada a alg\'un tipo de lenguaje
  (principalmente~C), y no entiende porque el dise\~no de un lenguaje de
  programaci\'on no es tan configurable como una utilidad de directorio o
  un editor de texto:\par
  {\obeylines
  \qquad {\sl Prefiero |==|/|=| m\'as que |=|/|:=|}
  \qquad {\sl ?`No puedes intercambiar |"| y |'| ?}
  \qquad {\sl ?`Por qu\'e |--| no funciona como en C?}
  \qquad {\sl !`Odio escribir las palabras clave en may\'usculas!}
  \qquad {\sl !`La falta de precedencia es odiosa!}}

  Las caracter\'{\i}sticas {\sl referidas} arriba jam\'as cambiar\'an, y ser\'a
  mejor que te acostumbres a ellas.  Todas las decisiones de dise\~no tienen
  buenas razones, y al contrario de lo que dicen algunos rumores, no se
  hicieron por razones de velocidad del compilador (de hecho, el implementarlas
  de una forma tradicional no har\'{\i}a m\'as lento al compilador).

\pregunta{?`Por qu\'e la caracteristica~\/|X| en~E no es como en el lenguaje~\/|Y|?
          (que yo encuentro mejor).}

  Lo mismo que antes, el dise\~no de un lenguaje no se puede cambiar debido
  a una preferencia personal.  Si tienes ideas serias de c\'omo debe ser un
  lenguaje seg\'un tus preferencias, y esas ideas provienen del lenguaje |Y|,
  entonces utiliza |Y|\null{}.  Si no encuentras tus ideas en ning\'un lenguaje
  existente, entonces !`es el momento de dise\~nar e implementar el tuyo
  propio!  (No me estoy burlando, !`merece la pena!, y siempre puedes
  empezar con~E~\dots |:-)|)

\pregunta{quiz\'as \/|X|?}

  Despu\'es de haber visto pr\'acticamente cientos de lenguajes de
  programaci\'on, las posibilidades que tienes de sugerir una nueva
  caracter\'{\i}stica para~E en la que no haya pensado, no son muy grandes.
  Muchas cosas no son apropiadas para~E, y en general el tiempo est\'a
  limitado para a\~nadir cosas m\'as interesante.  (Si te fijas bien, la
  cantidad de caracter\'{\i}sticas de~E ya es bastante alta para un lenguaje
  de programaci\'on medio).  Tengo una lista bastante grande de posibles
  caracter\'{\i}sticas para~E, y se implementar\'an eventualmente algunas de
  ellas.  S\'olo espera y ver\'as~\dots


\endchapter
\eject
\end

------------Corta por aquí -------------------
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%	Definitionen zur Unterstützung des ECMA 94 Latin 1 Zeichensatzes.
%
%	Zusammengeleimt von Olaf `Olsen' Barthel, 7. April 1991
%		use or misuse this file as you like...
%
%	Probleme gibt es noch bei den Zeichen für Yen, Cent und das
%	isländische Thorr. Hier müßte man eigentlich mit Metafont
%	zuschlagen, wozu ich als TeX-Apprentice leider noch nicht
%	in der Lage bin :-(
%
%	little changes (hes) 9-jul-91
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


% See the new `lplain.tex' for TeX 3.0 (>= Version 2.09  Feb 8, 1990)
%
% if not(TeX >= 3.0) do_nothing else ...
\ifx\undefined\inputlineno \else
\ifnum\inputlineno=-1 \else

\message{AMIGA-style (ECMA 94 Latin 1)}

\lccode`à=`à
\uccode`à=`À
\lccode`À=`à
\uccode`À=`À
\catcode`à=\active \def à{\`{a}}
\catcode`À=\active \def À{\`{A}}
\lccode`á=`á
\uccode`á=`Á
\lccode`Á=`á
\uccode`Á=`Á
\catcode`á=\active \def á{\'{a}}
\catcode`Á=\active \def Á{\'{A}}
\lccode`â=`â
\uccode`â=`Â
\lccode`Â=`â
\uccode`Â=`Â
\catcode`â=\active \def â{\^{a}}
\catcode`Â=\active \def Â{\^{A}}
\lccode`ã=`ã
\uccode`ã=`Ã
\lccode`Ã=`ã
\uccode`Ã=`Ã
\catcode`ã=\active \def ã{\~{a}}
\catcode`Ã=\active \def Ã{\~{A}}
\lccode`ä=`ä
\uccode`ä=`Ä
\lccode`Ä=`ä
\uccode`Ä=`Ä
\catcode`ä=\active \def ä{\"{a}}
\catcode`Ä=\active \def Ä{\"{A}}
\lccode`å=`å
\uccode`å=`Å
\lccode`Å=`å
\uccode`Å=`Å
\catcode`å=\active \def å{\aa}
\catcode`Å=\active \def Å{\AA}
\lccode`æ=`æ
\uccode`æ=`Æ
\lccode`Æ=`æ
\uccode`Æ=`Æ
\catcode`æ=\active \def æ{\ae}
\catcode`Æ=\active \def Æ{\AE}

\lccode`ç=`ç
\uccode`ç=`Ç
\lccode`Ç=`ç
\uccode`Ç=`Ç
\catcode`ç=\active \def ç{\c{c}}
\catcode`Ç=\active \def Ç{\c{C}}

\lccode`è=`è
\uccode`è=`È
\lccode`È=`è
\uccode`È=`È
\catcode`è=\active \def è{\`{e}}
\catcode`È=\active \def È{\`{E}}
\lccode`é=`é
\uccode`é=`É
\lccode`É=`é
\uccode`É=`É
\catcode`é=\active \def é{\'{e}}
\catcode`É=\active \def É{\'{E}}
\lccode`ê=`ê
\uccode`ê=`Ê
\lccode`Ê=`ê
\uccode`Ê=`Ê
\catcode`ê=\active \def ê{\^{e}}
\catcode`Ê=\active \def Ê{\^{E}}
\lccode`ë=`ë
\uccode`ë=`Ë
\lccode`Ë=`ë
\uccode`Ë=`Ë
\catcode`ë=\active \def ë{\"{e}}
\catcode`Ë=\active \def Ë{\"{E}}

\lccode`ì=`ì
\uccode`ì=`Ì
\lccode`Ì=`ì
\uccode`Ì=`Ì
\catcode`ì=\active \def ì{\`{\i}}
\catcode`Ì=\active \def Ì{\`{I}}
\lccode`í=`í
\uccode`í=`Í
\lccode`Í=`í
\uccode`Í=`Í
\catcode`í=\active \def í{\'{\i}}
\catcode`Í=\active \def Í{\'{I}}
\lccode`î=`î
\uccode`î=`Î
\lccode`Î=`î
\uccode`Î=`Î
\catcode`î=\active \def î{\^{\i}}
\catcode`Î=\active \def Î{\^{I}}
\lccode`ï=`ï
\uccode`ï=`Ï
\lccode`Ï=`ï
\uccode`Ï=`Ï
\catcode`ï=\active \def ï{\"{\i}}
\catcode`Ï=\active \def Ï{\"{I}}

\lccode`ñ=`ñ
\uccode`ñ=`Ñ
\lccode`Ñ=`ñ
\uccode`Ñ=`Ñ
\catcode`ñ=\active \def ñ{\~{n}}
\catcode`Ñ=\active \def Ñ{\~{N}}

\lccode`ò=`ò
\uccode`ò=`Ò
\lccode`Ò=`ò
\uccode`Ò=`Ò
\catcode`ò=\active \def ò{\`{o}}
\catcode`Ò=\active \def Ò{\`{O}}
\lccode`ó=`ó
\uccode`ó=`Ó
\lccode`Ó=`ó
\uccode`Ó=`Ó
\catcode`ó=\active \def ó{\'{o}}
\catcode`Ó=\active \def Ó{\'{O}}
\lccode`ô=`ô
\uccode`ô=`Ô
\lccode`Ô=`ô
\uccode`Ô=`Ô
\catcode`ô=\active \def ô{\^{o}}
\catcode`Ô=\active \def Ô{\^{O}}
\lccode`õ=`õ
\uccode`õ=`Õ
\lccode`Õ=`õ
\uccode`Õ=`Õ
\catcode`õ=\active \def õ{\~{o}}
\catcode`Õ=\active \def Õ{\~{O}}
\lccode`ö=`ö
\uccode`ö=`Ö
\lccode`Ö=`ö
\uccode`Ö=`Ö
\catcode`ö=\active \def ö{\"{o}}
\catcode`Ö=\active \def Ö{\"{O}}
\lccode`ø=`ø
\uccode`ø=`Ø
\lccode`Ø=`ø
\uccode`Ø=`Ø
\catcode`ø=\active \def ø{\o}
\catcode`Ø=\active \def Ø{\O}

\lccode`×=`×
\uccode`×=0
\catcode`×=\active \def ×{$\times$}
\lccode`÷=`÷
\uccode`÷=0
\catcode`÷=\active \def ÷{$\div$}

\lccode`ù=`ù
\uccode`ù=`Ù
\lccode`Ù=`ù
\uccode`Ù=`Ù
\catcode`ù=\active \def ù{\`{u}}
\catcode`Ù=\active \def Ù{\`{U}}
\lccode`ú=`ú
\uccode`ú=`Ú
\lccode`Ú=`ú
\uccode`Ú=`Ú
\catcode`ú=\active \def ú{\'{u}}
\catcode`Ú=\active \def Ú{\'{U}}
\lccode`û=`û
\uccode`û=`Û
\lccode`Û=`û
\uccode`Û=`Û
\catcode`û=\active \def û{\^{u}}
\catcode`Û=\active \def Û{\^{U}}
\lccode`ü=`ü
\uccode`ü=`Ü
\lccode`Ü=`ü
\uccode`Ü=`Ü
\catcode`ü=\active \def ü{\"{u}}
\catcode`Ü=\active \def Ü{\"{U}}

\lccode`ý=`ý
\uccode`ý=`Ý
\lccode`Ý=`ý
\uccode`Ý=`Ý
\catcode`ý=\active \def ý{\'{y}}
\catcode`Ý=\active \def Ý{\'{Y}}

\lccode`ß=`ß
\uccode`ß=0
\catcode`ß=\active \def ß{\ss}

\lccode`ÿ=`ÿ
\uccode`ÿ=0
\catcode`ÿ=\active \def ÿ{\"{y}}

\lccode`¡=`¡
\uccode`¡=0
\catcode`¡=\active \def ¡{!`}

\lccode`£=`£
\uccode`£=0
\catcode`£=\active \def £{\pounds}

\lccode`§=`§
\uccode`§=0
\catcode`§=\active \def §{\S}

\lccode`©=`©
\uccode`©=0
\catcode`©=\active \def ©{\copyright}

\lccode`ª=`ª
\uccode`ª=0
\catcode`ª=\active \def ª{\leavevmode\kern-.1em\raise.5ex\hbox{\b{a}}}

\lccode`«=`«
\uccode`«=0
\catcode`«=\active \def «{$\ll$}

\lccode`¬=`¬
\uccode`¬=0
\catcode`¬=\active \def ¬{$\neg$}

\lccode`±=`±
\uccode`±=0
\catcode`±=\active \def ±{$\pm$}

\lccode`²=`²
\uccode`²=0
\catcode`²=\active \def ²{\leavevmode\kern.1em\raise.5ex\hbox{\the\scriptfont0 2}}

\lccode`³=`³
\uccode`³=0
\catcode`³=\active \def ³{\leavevmode\kern.1em\raise.5ex\hbox{\the\scriptfont0 3}}

\lccode`µ=`µ
\uccode`µ=0
\catcode`µ=\active \def µ{$\mu$}

\lccode`¶=`¶
\uccode`¶=0
\catcode`¶=\active \def ¶{\P}

\lccode`¹=`¹
\uccode`¹=0
\catcode`¹=\active \def ¹{\leavevmode\kern.1em\raise.5ex\hbox{\the\scriptfont0 1}}

\lccode`º=`º
\uccode`º=0
\catcode`º=\active \def º{\leavevmode\kern-.1em\raise.5ex\hbox{\b{o}}}

\lccode`»=`»
\uccode`»=0
\catcode`»=\active \def »{$\gg$}

\lccode`¼=`¼
\uccode`¼=0
\catcode`¼=\active \def ¼{\leavevmode\kern.1em\raise.5ex\hbox{\the\scriptfont0 1}\kern-.1em/\kern-.15em\lower.25ex\hbox{\the\scriptfont0 4}}

\lccode`½=`½
\uccode`½=0
\catcode`½=\active \def ½{\leavevmode\kern.1em\raise.5ex\hbox{\the\scriptfont0 1}\kern-.1em/\kern-.15em\lower.25ex\hbox{\the\scriptfont0 2}}

\lccode`¾=`¾
\uccode`¾=0
\catcode`¾=\active \def ¾{\leavevmode\kern.1em\raise.5ex\hbox{\the\scriptfont0 3}\kern-.1em/\kern-.15em\lower.25ex\hbox{\the\scriptfont0 4}}

\lccode`¿=`¿
\uccode`¿=0
\catcode`¿=\active \def ¿{?`}


% After transferring files there's sometimes an Ctrl-Z at the end.
% (This could also handled in the CodePage with a line ^^Z>^^@)
\catcode`^^Z=9                          % ignore it or ...
%\catcode`^^Z=\active \def^^Z{\endinput}% ... make it active

\fi\fi


\endinput

