@database aos/english/Compiler.guide

@Master aos/english/Compiler.texi

@Width 72


This is the AmigaGuide®  file aos/english/Compiler.guide, produced by Makeinfo-1.68 from 
the input file aos/english/Compiler.texi.

   \\input texinfo

@node Main "Compiler.guide"
@next "Introduction"

Compiler
********

   This document describes the GCC based compiler, which is used in
StormC version 4.

   Copyright (C) 2000,2001 HAAGE&PARTNER Computer GmbH.


 @{" Introduction " link "Introduction"}  
 @{" License    " link "License"}  

 @{" Data in registers " link "Data in registers"}  
 @{" Parameters in registers " link "Parameters in registers"}  
 @{" Inline Functions " link "Inline Functions"}  
 @{" Pragma statements " link "Pragma statements"}  
 @{" Attributes " link "Attributes"}  
 @{" Predefined symbols " link "Predefined symbols"}  
 @{" INIT and EXIT Functions " link "INIT and EXIT Functions"}  
 @{" Using shared libraries " link "Using shared libraries"}  
 @{" Programming your own shared libraries " link "Programming your own shared libraries"}  

 @{" Index      " link "Index"}


@endnode

@node "Introduction" "Compiler.guide/Introduction"
@next "License"
@prev "Main"
@toc "Main"

Introduction
============

   Since version 4 of the StormC-environment a special version of the
GNU-C compiler is used for translating C and C++ programs. This step
was made to make StormC accessible for many different platforms with
different processors. You will find out all about the special features
of StormC in this chapter.


@endnode

@node "License" "Compiler.guide/License"
@next "Data in registers"
@prev "Introduction"
@toc "Main"

License
=======

   The GNU-C compilers are subject to the GNU GPL (GNU General Public
License).  Since the compilers used in the StormC-environment are based
on the GNU-C compilers, they are also subject to the GPL. This concerns
the following programs in the @{b}StormC:StormSYS@{ub}-directory.

   * @{b}cpp@{ub}: Preprocessor

   * @{b}cc1_68k@{ub}: compiles C-sourcecodes on a 68k for a 68k.

   * @{b}cc1_ppc@{ub}: compiles C-sourcecodes on a 68k for a PPC.

   * @{b}cc1plus_68k@{ub}:compiles C++-sourcecodes on a 68k for a 68k.

   * @{b}cc1plus_ppc@{ub}: compiles C++-sourcecodes on a 68k for a PPC.

   * @{b}cc1_ppc_68k@{ub}: compiles C-sourcecodes on a PPC for a 68k.

   * @{b}cc1_ppc_ppc@{ub}: compiles C-sourcecodes on a PPC for a PPC.

   * @{b}cc1plus_ppc_68k@{ub}: compiles C++-sourcecodes on a PPC for a 68k.

   * @{b}cc1plus_ppc_ppc@{ub}: compiles C++-sourcecodes on a PPC for a  PPC.

   * @{b}as_68k@{ub}: Assembles compiled sourcecodes on a 68k for a 68k.

   * @{b}cvs@{ub} (Has nothing to do with compilers, but is also subject to the
     GPL)

@{b}   The programs@{ub} @{b}pasm@{ub} @{b}and@{ub} @{b}pasm_ppc@{ub} @{b}are Copyright (C) of Frank Wille.@{ub}

@{b}   All other programs are Copyright (C) of HAAGE&PARTNER Computer GmbH.@{ub}

   The changes in the compilers concerning the des AmigaOS are based on
the work of (no special order):
     Kamil Iskra
     Matthias Fleischer
     Gunther Nikl
     Markus Wild
     Rafael Luebbert
     Leonard Norrgard
     Jeff Shepherd
     Hans Verkuil

   For the programs subject to the GPL you can find the source with all
changes and enhancements on your StormC CD-ROM or on the homepage of
HAAGE&PARTNER: @{b}http://www.haage-partner.com@{ub}


		    GNU GENERAL PUBLIC LICENSE
		       Version 2, June 1991

 Copyright (C) 1989, 1991 Free Software Foandation, Inc.
                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

			    Preamble

  The licenses for most software are designed to take away your
freedom to share and change it.  By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users.  This
General Public License applies to most of the Free Software
Foandation's software and to any other program whose authors commit to
using it.  (Some other Free Software Foandation software is covered by
the GNU Library General Public License instead.)  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.

  To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have.  You must make sure that they, too, receive or can get the
source code.  And you must show them these terms so they know their
rights.

  We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.

  Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software.  If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.

  Finally, any free program is threatened constantly by software
patents.  We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary.  To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.

  The precise terms and conditions for copying, distribution and
modification follow.

		    GNU GENERAL PUBLIC LICENSE
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License.  The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language.  (Hereinafter, translation is included without limitation in
the term "modification".)  Each licensee is addressed as "you".

Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope.  The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.

  1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.

You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.

  2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:

    a) You must cause the modified files to carry prominent notices
    stating that you changed the files and the date of any change.

    b) You must cause any work that you distribute or publish, that in
    whole or in part contains or is derived from the Program or any
    part thereof, to be licensed as a whole at no charge to all third
    parties under the terms of this License.

    c) If the modified program normally reads commands interactively
    when run, you must cause it, when started running for such
    interactive use in the most ordinary way, to print or display an
    announcement including an appropriate copyright notice and a
    notice that there is no warranty (or else, saying that you provide
    a warranty) and that users may redistribute the program under
    these conditions, and telling the user how to view a copy of this
    License.  (Exception: if the Program itself is interactive but
    does not normally print such an announcement, your work based on
    the Program is not required to print an announcement.)

These requirements apply to the modified work as a whole.  If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works.  But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.

Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.

In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.

  3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:

    a) Accompany it with the complete corresponding machine-readable
    source code, which must be distributed under the terms of Sections
    1 and 2 above on a medium customarily used for software interchange; or,

    b) Accompany it with a written offer, valid for at least three
    years, to give any third party, for a charge no more than your
    cost of physically performing source distribution, a complete
    machine-readable copy of the corresponding source code, to be
    distributed under the terms of Sections 1 and 2 above on a medium
    customarily used for software interchange; or,

    c) Accompany it with the information you received as to the offer
    to distribute corresponding source code.  (This alternative is
    allowed only for noncommercial distribution and only if you
    received the program in object code or executable form with such
    an offer, in accord with Subsection b above.)

The source code for a work means the preferred form of the work for
making modifications to it.  For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable.  However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.

If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.

  4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License.  Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.

  5. You are not required to accept this License, since you have not
signed it.  However, nothing else grants you permission to modify or
distribute the Program or its derivative works.  These actions are
prohibited by law if you do not accept this License.  Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.

  6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions.  You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.

  7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all.  For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.

If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.

It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices.  Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.

  8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded.  In such case, this License incorporates
the limitation as if written in the body of this License.

  9. The Free Software Foandation may publish revised and/or new versions
of the General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

Each version is given a distinguishing version number.  If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation.  If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foandation.

  10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission.  For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this.  Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.

			    NO WARRANTY

  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.

  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.

		     END OF TERMS AND CONDITIONS

	    How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is foand.

    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) 19yy  <name of author>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foandation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foandation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA


Also add information on how to contact you by electronic and paper mail.

If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:

    Gnomovision version 69, Copyright (C) 19yy name of author
    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
    This is free software, and you are welcome to redistribute it
    under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License.  Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.

You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary.  Here is a sample; alter the names:

  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
  `Gnomovision' (which makes passes at compilers) written by James Hacker.

  <signature of Ty Coon>, 1 April 1989
  Ty Coon, President of Vice

This General Public License does not permit incorporating your program into
proprietary programs.  If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library.  If this is what you want to do, use the GNU Library General
Public License instead of this License.


@endnode

@node "Data in registers" "Compiler.guide/Data in registers"
@next "Parameters in registers"
@prev "License"
@toc "Main"

Data in registers
=================

   Each processor not only manages the RAM, but also has some internal
processor registers, where generally temporary results of calculations
and the likes are put. Calling these registers is a lot faster than a
RAM-operation, and since processors from the 68000- and PowerPC-family
in comparison have very much registers, the desire to put often used
variables in the unused registers to get a great speed-increase is
understandable.

@{b}   As a rule it should be left up to the compiler to decide, which data
should be kept in registers, and which on the stack. Most of the times
the compiler can make a better judgment about this, and forcing data in
a register would have counterproductive results.@{ub}

   In the ANSI C-standard a flexible and machine-independent notation
is introduced for this. The key for this is a memory-class by the name
of @{b}register@{ub}, which is used like @{b}extern@{ub}, @{b}auto@{ub} or @{b}static@{ub}.

   Register-variables may only be declared within functions. Apart from
that, you can use them freely: you can define as many variables as you
want from as many types as you want as @{b}register@{ub}, with the compiler
deciding what it really puts in a register. Integer and pointer- or
reference-variables can be put in registers, with the numerical types
being put in data-registers, and the pointertypes in addressregisters.

   You should take care though not to make too much use of registers,
since the processor needs at least one register for almost every
operation, and when too many registers are used by variables, the
processor must sometimes move them to the stack for a short time, and
load them back later, so that you can not expect a speed-increase. In
each function there should be a maximum of four numerical and two
pointervariables declared as @{b}register@{ub}.

   StormC is not forced to use your register-declarations, it uses them
as suggestions.  The StormC optimizer can decide far better, which
variable should be loaded in what register, at what time. Furthermore,
StormC uses this register more than once in a function, which you can't
do by using the keyword @{b}register@{ub}.


@endnode

@node "Parameters in registers" "Compiler.guide/Parameters in registers"
@next "Inline Functions"
@prev "Data in registers"
@toc "Main"

Parameters in registers
=======================

@{b}   Parameters in registers does not conform to the C++-standard.@{ub}
Therefore, you should use this feature with care, since the programs
wouldn't be portable otherwise. The best is, to only use these kind of
parameters when linking ready-made function expecting the arguments in
registers, to a program in some way, for instance the
Amiga-systemfunctions or assembler-routines, which can't be ported
easily anyway.

   To pass parameters in registers, you simply put @{b}register@{ub} before the
parameters in the function-declaration, for instance:

     int Inc (register int i, register int j);

   Setting a @{b}register@{ub} for parameters doesn't make sense for the PowerPC,
since a large part of the parameters will be passed in registers
automatically here.

   When compiling a C-program for the 68k, there is even the
possibility to tell the compiler in what register it should put the
parameters. For this you must write @{b}__asm("registername>")@{ub} behind the
parametertype and -name, for instance:

     int Inc (int i __asm("d4"), int j __asm("d5"));

   This doesn't make sense for speed increase. It could only make the
implementation of AmigaOS hook-functions easier. For
portability-reasons the function @{b}HookEntry()@{ub}) from the @{b}amiga.lib@{ub} is
recommended though.


@endnode

@node "Inline Functions" "Compiler.guide/Inline Functions"
@next "Pragma statements"
@prev "Parameters in registers"
@toc "Main"

Inline Functions
================

   Under 68k, each function-call represents a lot of work. First, the
calling code must reserve space on the stack for the arguments, and put
them there. Next follows a @{b}JSR@{ub}-jump to the function is made, which
reserves the required memory on the stack for its own data, and copies
the contents all processor-registers that change to some place. At the
end of the function, all register-contents are copied back, the local
variables are removed from the stack and a @{b}RTS@{ub} follows to jump back
into the calling program, where all the arguments need to be removed
from the stack.  This brings the programmer in a dilemma: should you
define a small function, or use the contents of this function every
time in the program. A good example is the maximum function:

     int max(int a, int b)
     {
         if (a>b)
             return a;
         else
             return b;
     }

   Instead of a function call @{b}max(x,y)@{ub}, you could use @{b}(x > y ? x : y)@{ub}
which is faster, but not at all more readable. For such cases there is
the inline-specification.

   If you put the keyword @{b}inline@{ub} in front of the first declaration of a
function (@{b}__inline@{ub} in ANSI-C), for each function call to this function
to function-definition is inserted in the sourcecode. The program is
not changed syntactically or semantically.  You simply declare

     inline int max(int a, int b)
     {
         if (a>b)
             return a;
         else
             return b;
     }

   and can use @{b}max()@{ub} as an ordinary function. The difference is in the
generated code. With @{b}inline@{ub} the contents of @{b}max()@{ub} is copied in the
calling code every time.

   This saves quite some things: No @{b}JSR@{ub} or @{b}RTS@{ub} is used to jump in and
out of the function, in general no register-contents need to be saved
and copied back, and the function must not create an own frame on the
stack. The function result is not necessarily returned in register @{b}d0@{ub},
and the compiler still has many optimizing-options.

   So, an inline function is not created once, but in many copies, one
for each call. It is obvious, that inlining bloats the programs, and
should therefore not be overdone. The compiler may however ignore the
@{b}inline@{ub} if it doesn't think it makes sense.

   There can be situations where an inline function is also created in
the normal way, for instance if it is used before it is declared, or
when an inline-function is recursive. All these things are allowed,
since you can use inline-functions just like any other function.

   If an inline-function is created as a normal function for those
reasons, it has an internal linkage, so that other modules won't notice
it when a function in a module was really created. Therefore, @{b}inline@{ub}
has rules similar to those of the memory-class @{b}static@{ub}:

     inline void f();
     void f();

   is allowed,

     void f();
     inline void f();	// ERROR

   Please note: @{b}inline@{ub} is not a memory class (such as @{b}static@{ub} or
@{b}extern@{ub}), but a function-specification.


@endnode

@node "Pragma statements" "Compiler.guide/Pragma statements"
@next "Attributes"
@prev "Inline Functions"
@toc "Main"

Pragma statements
=================

   In spite of the ANSI-specifications, each compilersystem has its own
peculiarities.  These compiler specific things are introduced with a
@{b}#pragma@{ub}.

   * @{b}#pragma priority@{ub}: In C++ the compiler automatically creates INIT
     and EXIT functions (see @{"INIT and EXIT Functions" link "INIT and EXIT Functions"}) for the global
     variables, which have a constructor or a destructor. In general
     the priority 8 is used for this. With the @{b}#pragma priority@{ub} you can
     change this priority for the active source (the sourcecode in
     which the @{b}#pragma priority@{ub} is located). To do this, enter a number
     from 0 - 9 after the @{b}#pragma priority@{ub}.

   * @{b}#pragma libbase@{ub}: See @{"Programming your own shared libraries" link "Programming your own shared libraries"}.


@endnode

@node "Attributes" "Compiler.guide/Attributes"
@next "Predefined symbols"
@prev "Pragma statements"
@toc "Main"

Attributes
==========

   Currently StormC knows one attribute, which can be added to a
function definition.

   * @{b}__saveds@{ub}: This keyword does not generate code in the far
     datamodel, in the near data (a4) a4 will be saved on the stack and
     loaded with the symbol @{b}__LinkerDB@{ub}, in near data (a6) the same
     happens for a6.

     Don't use @{b}__saveds@{ub} lightly. It should only be used for functions
     which are called from outside your program, such as BOOPSI class
     dispatchers. Remember that in the small data model one more
     register is lost for the optimizer, and only a0 - a3 will be
     available - the advantage of the small data model can be lost, if
     you don't use many global variables.


@endnode

@node "Predefined symbols" "Compiler.guide/Predefined symbols"
@next "INIT and EXIT Functions"
@prev "Attributes"
@toc "Main"

Predefined symbols
==================

   The preprocessor has some predefined macros. Some are confirming to
the ANSI-C standard, others are a part of C++, or special features of
StormC. These macros can not be redefined.

   * @{b}__FILE__@{ub}: This macro contains the name of the current sourcecode
     file as a string.

   * @{b}__LINE__@{ub}: This macro returns the linenumber of the line where it
     is located in the sourcecode, as a decimal int-constant.

   * @{b}__FUNC__@{ub}: In ANSI-C-mode this macro returns the name of the
     translated function. In C++-mode the full functionname with
     parameterlist is returned.

   * @{b}__DATE__@{ub} and @{b}__TIME__@{ub}: These macros return date and time of the
     compilation. This is very useful if you want to give a program a
     unique version number:

          void main()
          {
              cout « "Version 1.1, compiled on " __DATE__", "__TIME__" hours\\n";
          }

     The date will be given in the format "Month Day Year", for
     instance "Feb 08 1996", and the time in the normal
     "Hours:Minutes:Seconds" format.

   * @{b}__DATE2__@{ub}: Contains an Amiga-like notation for the date of the
     compilation in the format "Day Month Year".

   * @{b}__STDC__@{ub}: This macro returns the numerical value 1 in all ANSI C
     compatible implementations, and should enable you to decide if a
     compiler has this standard, otherwise @{b}__STDC__@{ub} is not defined.

   * @{b}__COMPMODE__@{ub}: Is defined with the constant 0 in C-mode and 1 under
     C++ in StormC.

   * @{b}__cplusplus@{ub}: This macro is only set when compiling in C++ mode.

   * @{b}__STORMGCC__@{ub}: Often one would like to test what compiler and what
     compilerversion one is using. For that reason StormC additionally
     defines a macro with the name @{b}__STORMGCC__@{ub}, which gives the
     current version @{b}4@{ub} as an int-constant.

   * @{b}__GNUC__@{ub}: Contains the versionnumber of the GNU-C compiler that is
     used as int-constant.  Currently this is @{b}2@{ub}.

   * @{b}__GNUC_MINOR__@{ub}: Contains the revisionnumber of the GNU-C compiler
     that is used as int-constant.  Currently this is @{b}95@{ub}.

   * @{b}amiga@{ub}, @{b}amigaos@{ub}, @{b}MCH_AMIGA@{ub} and @{b}AMIGA@{ub}: are set when compiling for an
     Amiga.

   * @{b}__PPC__@{ub}: is set when compiling for a PowerPC.

   * @{b}mc68000@{ub}: is set when compiling for an MC68K.


@endnode

@node "INIT and EXIT Functions" "Compiler.guide/INIT and EXIT Functions"
@next "Using shared libraries"
@prev "Predefined symbols"
@toc "Main"

INIT and EXIT Functions
=======================

   As a C and C++ compiler, StormC supports the automatic calling of
initializations- and exitfunctions before and after the calling of the
@{b}main()@{ub}-function.

   If stdio is initialized, doesn't depend on the startup-code, but on
the fact that a program uses @{b}printf()@{ub} or similar I/O-functions.

   In the C++ area this feature is needed to call constructors and
destructors of global variables, in the ANSI-C area this feature is
useful for opening shared libraries automatically, and also for
initialising the standard I/O.

   The functionlist that is used by this is created by the linker.
Functions with a certain name are added to a list of
initialisingfunctions and exit-functions by the linker. The
startup-code only needs to call the function @{b}InitModules()@{ub} before
calling @{b}main()@{ub} and @{b}CleanupModules()@{ub} after the function @{b}main()@{ub}.

   The advantage of this dynamic concept is the more flexible way the
startup code is built-up. The resulting programs are thus kept at a
minimum size. The resulting startup-code can be used for all
programming-projects. Selecting a startup-code suited to the compiler
options, which is a lot of work and prone to errors, is not needed
anymore.

Constructing and destructing in ANSI-C
--------------------------------------

   The functions which are called during initialisation must be called
@{b}INIT_n_something(void)@{ub}, the exit-functions @{b}EXIT_n_something(void)@{ub}. The
@{b}n@{ub} is a number between 0 and 9. This sets the priority of the function.
The smaller the value is, the earlier the initialisation and the later
the exit-function is called. The @{b}something@{ub} can be replaced by any name,
which may contain further @{b}_@{ub}s.

Constructing and destructing in C++
-----------------------------------

   In C++ the compiler automatically creates such suitable functions
for each global variable. In these functions the constructing and
destructing of the variables is done. Generally, the compiler uses the
priority 8 for these @{b}INIT_@{ub}- and @{b}EXIT_@{ub}-functions. Since the exact order
of the calls, in other words the priority of the @{b}INIT_@{ub}- and
@{b}EXIT_@{ub}-functions can be of importance, there is the @{b}#pragma priority@{ub}.
You can use this to set the priority of the global variables of the
translation unit (the sourcecode-file, in which the @{b}#pragma priority@{ub} is
located).

Assignment of INIT and EXIT functions
-------------------------------------

   The INIT and EXIT functions are called by the functions
@{b}InitModules()@{ub} and @{b}CleanupModules()@{ub}. An INIT function and an EXIT
function are treated as a pair when the priority of both functions is
the same, and the name-part matches, for instance:

   * @{b}INIT_5_Files@{ub} and @{b}EXIT_5_Files@{ub} form a pair,

   * @{b}INIT_5_Files@{ub} and @{b}EXIT_4_Files@{ub} do not form a pair, because of the
     different priority.

   * @{b}INIT_5_Files@{ub} and @{b}EXIT_5_File@{ub} do not form a pair, because of the
     different name-part.

   The function @{b}CleanupModules()@{ub} (which for instance is called by
@{b}exit()@{ub} or by the end of the program) only calls the EXIT functions
whose corresponding INIT functions have been fully executed previously.

   If the function @{b}INIT_5_Files@{ub} leaves the program with @{b}exit()@{ub}, the
function @{b}EXIT_5_Files@{ub} is not called, but all EXIT functions whose INIT
functions have been executed will be called, typically those functions
with a smaller priority setting. Of course, not all INIT function needs
a matching EXIT function, or the other way around. In this case an
empty function will be assumed to be the matching function.

Priority list
-------------

   As a reference this list of priorities, and what is initialized and
destructed by it as default:

   * Priority 0: This priority is reserved for functions initialising
     the StormC library (aspecially datastructures of the library). If
     you want to initialise a datastructure (for instance a jumptable),
     not making any access to any operating system resources, you should
     also use priority 0.

   * Priority 1: Opening and closing of the der dos.library,
     intuition.library, utility.library.

   * Priority 2: Opening and closing of the asl.library,
     commodities.library, diskfont.library, expansion.library,
     gadtools.library, graphics.library, icon.library,
     iffparse.library, keymap.library, layers.library, mathffp.library,
     mathtrans.library, mathieeedoubbas.library,
     mathieeedoubtrans.library, mathieeesingbas.library,
     mathieeesingtrans.library, powerpc.library, rexxsyslib.library,
     version.library, wizard.library, workbench.library.

   * Priority 3: Opening and closing of the amigaguide.library,
     bullet.library, cybergraphics.library, datatypes.library,
     resource.library, xadmaster.library, locale.library,
     lowlevel.library, translator.library, Warp3D.library,
     Warp3DPPC.library and the colorwheel.gadget,
     gradientslider.gadget, chooser.gadget, slider.gadget,
     space.gadget, string.gadget, datebrowser.gadget, layout.gadget,
     button.gadget, texteditor.gadget, textfield.gadget,
     palette.gadget, scroller.gadget, clicktab.gadget, input.device,
     timer.device.

   * Priority 4: Initialises the memory management for @{b}malloc()@{ub}, @{b}free()@{ub},
     @{b}new@{ub} and @{b}delete@{ub}. Frees all memory that was allocated using @{b}malloc()@{ub}
     or @{b}new()@{ub}, but not freed.

   * Priority 5: Initialises the standard I/O.

   * Priority 6: Initialises stdin, stdout, stderr, cout, cin, cerr,
     clog.

   * Priority 7:

   * Priority 8: Initialising needed for POSIX-functions such as
     @{b}opendir()@{ub}, @{b}readdir()@{ub}.  Constructors and destructors for
     C++-classes are set to this priority as a default. Each global
     variable, whose type has a constructor or a destructor, creates an
     @{b}INIT@{ub}- or @{b}EXIT_@{ub}-function when called. The priority can be changed
     using the @{b}#pragma priority@{ub}.

   * Priority 9: The function started with @{b}atexit()@{ub} are called when
     finishing.


@endnode

@node "Using shared libraries" "Compiler.guide/Using shared libraries"
@next "Programming your own shared libraries"
@prev "INIT and EXIT Functions"
@toc "Main"

Using shared libraries
======================

   The AmigaOS basically consists of multiple shared libraries. Those
shared libraries offer functions which can be called by all programs
which have opened the respective library.

   For each shared library of the operating system there are some
C-header-files, allowing the use of a library. Always include the
header-file belonging to a library from @{b}StormC:include/proto@{ub}, for
instance @{b}#include <proto/exec.h>@{ub} for the exec.library.

   Before the functions of a library can be used, the library must
first be opened by the program, and a base pointer to the library needs
to be saved in the so-called @{b}LibBase@{ub}. Each library has its own LibBase,
for instance DOSBase for the dos.library, IntuitionBase for the
intuition.library.  The @{b}exec.library@{ub} has one special feature compared
with other libraries: it is not opened by the program, but is always
open, so the functions can always be used.

   You have the choice to manually open a library, or have this done at
the start of the program automatically.

Manually opening a library
--------------------------

   A library must be manually opened, if you want to have exact control
over what version of the library needs to be opened, and when the
automatic opening isn't supported for the library you need yet.

   To manually open a library, you must define its LibBase, and use the
function @{b}OpenLibrary()@{ub} from the exec.library. An example:

     #include <proto/exec.h>       // we need the prototype for OpenLibrary() from the exec.library
     #include <proto/intution.h>   // then we want do do something with this library
     
     struct IntuitionBase *IntuitionBase;  // this is the definition of the LibBase for intuition.library
     
     int main(void)
     {
         // trying to open version 37 or higher of the intuition.library.
         IntuitionBase = (struct IntutionBase*) OpenLibrary("intuition.library", 37);
     
         if(IntuitionBase)
         {
             // Opening was successful, starting here we can use the functions from intuition.library.
             ... do something ...
     
             // At the end we have to close the intuition.library again.
             CloseLibrary(IntuitionBase);
         }
         else
         {
             // Opening was not successful. Here you should return an error-message.
         }
     }

   You have to take care of three things:

  1. Use the correct version number, the compiler can not recognise if
     you open the library for version 37, but use a function which is
     only available for version 38 or later. A crash on a computer with
     an older operating system is unavoidable.

  2. Only call the library functions if the library was really opened.
     Multiple reasons can prevent the library from being opened: No
     library with the given name exists on this computer, or the
     version number is to small. Or there is not enough memory. There
     can be many other reasons!

  3. At the very latest, close the library at the end of the program.
     Only then can the library be removed from the memory of your
     Amiga, if you are low on memory (if no other program is using the
     library).

Automatically opening libraries
-------------------------------

   As soon as you use a function from the following libraries, and
don't open it manually as described above, it will be opened for you at
programstart (and closed at the end of the program):

   * amigaguide.library

   * asl.library

   * bullet.library

   * button.gadget

   * chooser.gadget

   * clicktab.gadget

   * colorwheel.gadget

   * commodities.library

   * cybergraphics.library

   * datatypes.library

   * datebrowser.gadget

   * diskfont.library

   * dos.library

   * expansion.library

   * gadtools.library

   * gradientslider.gadget

   * graphics.library

   * icon.library

   * iffparse.library

   * input.device

   * intuition.library

   * keymap.library

   * layers.library

   * layout.gadget

   * locale.library

   * lowlevel.library

   * mathffp.library

   * mathtrans.library

   * mathieeedoubbas.library

   * mathieeedoubtrans.library

   * mathieeesingbas.library

   * mathieeesingtrans.library

   * palette.gadget

   * powerpc.library

   * scroller.gadget

   * slider.gadget

   * space.gadget

   * string.gadget

   * resource.library

   * rexxsyslib.library

   * texteditor.gadget

   * textfield.gadget

   * timer.device

   * translator.library

   * utility.library

   * version.library

   * Warp3D.library,

   * Warp3DPPC.library

   * wizard.library

   * workbench.library

   * xadmaster.library


@endnode

@node "Programming your own shared libraries" "Compiler.guide/Programming your own shared libraries"
@next "Index"
@prev "Using shared libraries"
@toc "Main"

Programming your own shared libraries
=====================================

   Creating your own shared-libraries can also be very useful. As soon
as multiple programs use the same code, or function must be available
to other programs or developers, it is useful to create a shared
library from a collection of functions.

   StormC assists you with this task, so that you don't have to worry
about the technical details, and creating a shared-library is no more
work than creating a linker library.

   Still you should know the way a shared library is constructed, to
avoid some possible errors and use StormC as well as you can.

The construction of a shared-library
------------------------------------

   Basically a shared library consists of a bas structure (at least on
@{b}struct Library@{ub}) and a function-table, where each function of the shared
library is entered. Furthermore each shared-library has a
versionstring, which you can query using the command @{b}version@{ub} from the
CLI.

   So, the base-structure is at least one @{b}struct Library@{ub}, but you can
also add more elements. This is always useful if the programs using the
shared library should have access to own data without having to call a
library function.

   As a rule however you should use such public data with great care,
since access by other programs, be it read only or even writing, can
not be logged by the library. You will also have to make sure in future
versions of the library that this data has the same meaning, which
isn't always easy.

   More secure, and easier for you, is to keep the data of the library
in plain global variables, and create a function for each access, even
if it is only a minimal function, returning the value of a variable
(the dos.library uses this method a lot since AmigaOS version 36 for
instance to make access to the structure @{b}Process@{ub} safer).

   The name of the base-structure must be given to the compiler at one
point in the sourcecode, with the @{b}#pragma libbase@{ub}.  @{b}Important:@{ub} If you
have divided your library over multiple modules, the @{b}#pragma libbase@{ub}
should only be in one sourcetext.

   An example:

     #include <exec/libraries.h>
     
     struct MyLibBase
     {
     	struct Library library;
     	ULONG second_result;
     };
     
     #pragma libbase MyLibBase;

Register usage
--------------

   The functions of a shared library keep the arguments in
CPU-registers, data such as @{b}int@{ub}, @{b}LONG@{ub}, @{b}char@{ub} etc. in data-registers, and
pointers in address registers. For M68K the data registers should be
counted from @{b}d0@{ub} upward, the address registers from @{b}a0@{ub} upward. You
should however not use @{b}a5@{ub}, since this register is used by almost every
C-function to build a so-called stackframe. If a shared-library uses @{b}a5@{ub}
as parameter, you have to write a stub-function for this function in
assembler.

   To be able to access entries in the base-structure, a pointer to the
base-structure must be given as parameter in register @{b}a6@{ub}. This
parameter is automatically set when calling a function from the shared
library. Example:

     ULONG add_two(ULONG a __asm("d0"),
                   ULONG b __asm("d1"),
                   struct MyLibBase *base __asm("a6"))
     {
     	ULONG retval = a + b;
     	base->second_result = retval;
     	return retval;
     }

Shared-Library project settings
-------------------------------

   To create a shared library, you must create a project with at least
a sourcecode containing some ANSI-C-functions, an FD-file describing
the register-usage of the functions, and an entry for the programname,
of course ending with ".library".

   In the settings for the project select the large datamodel under
C/C++ options, and under Linker 1 of course "Link as Shared Library".
Furthermore you can enter the version and revision number of the
library, in linker options 1 there are two fields for this.

The structure of FD-files
-------------------------

   The FD file is built up as follows: First, the name always has the
suffix ".fd".  This also causes the file to be put in the correct
section FD-files of the project (FD or ".fd" stands for "function
description").

   The file consists of single lines, starting either with a @{b}*@{ub}, in
which case it is a comment, or a @{b}##@{ub}, in which case it is a special
command, otherwise the line must contain a valid function description.
Example:

     ##base _MyLibBase
     ##bias 30
     ##public
     add_two(a,b)(d0,d1)
     ##end

   The command @{b}##base@{ub} gives the name of the base variable, where the
name is given as linkersymbol, with the leading @{b}_@{ub}. In your C-program
this variable is written without the leading @{b}_@{ub}-sign.

   The command @{b}##bias@{ub} sets the offset of the function. In the function
table the functions are one after the other, the first function has the
offset -6, the next function the offset -12, the third the offset -18
and so on.

   With @{b}##bias@{ub} one can reset this offset, giving the value as a
positive number. Each function increases the positive offset number
with 6, because there is always one @{b}jmp xxx.L@{ub} in the function table, an
assembler command jumping to the actual start of the function. This
assembler command needs 6 Byte. Normally this @{b}##bias@{ub} is set to 30,
because the first 4 functions are reserved.

   The command @{b}##public@{ub} declares the following functions as public, the
command @{b}##private@{ub}, which is not used in the example, declares the
following functions as private.

   The command @{b}##end@{ub} ends the function description. Everything after
this in the file is ignored.

   But before the command @{b}##end@{ub} are the function descriptions. These
always consist of the name of the function, then the names of the
parameters, separated by commas enclosed in brackets, and lastly the
list of the registers. Always one parameter is assigned one register.
The parameter in register a6, which you may have specified in the
ANSI-C-function, is not specified here.

   The function description automatically adds 6 to the @{b}##bias@{ub}, so you
don't have to set a new @{b}##bias@{ub} after each function.

   Limitations: There is currently one limitation under StormC. The
command @{b}##bias@{ub} can`t be used after the first function description. In
theory it is possible  to create a functiontable where the functions
don't follow eachother directly, for instance because the functiontable
contains functions which should be invisible to the user. Since the
fd-file should serve the creation of a function table here, the
functions must follow eachother directly.

The first four functions
------------------------

   Some information about the reserved first 4 functions. These
functions are called @{b}LibOpen()@{ub}, @{b}LibClose()@{ub}, @{b}LibExpunge()@{ub} and @{b}LibNull()@{ub}.
There is also the function @{b}LibInit()@{ub}, which is not called through an
entry in the function table.

   The function @{b}LibInit()@{ub} is called and initialised after the loading,
when the library is first opened. In StormC this means that automatic
constructors or initialisation functions are called, which for instance
open other required libraries. This functions the same as in any normal
program, so you don't have to worry about the correct initialisation.
For C++-programmers the constructors of the global variables are also
called.

   The function @{b}LibOpen()@{ub} is called each time the library is opened, and
does nothing more than logging this event. A counter is increased,
which reflects how often the library was opened. @{b}LibOpen()@{ub} calls the
empty function @{b}struct Library *_LibOpen(struct Library *base
__asm("a6"))@{ub}, which can be overwritten by your own definition. This
function contains the base-pointer of the shared library, and must
return a base pointer if the opening was successful, otherwise @{b}NULL@{ub}.
The returned base pointer normally is the passed base-pointer.

   The function @{b}LibClose()@{ub} is called when the library is closed, and
decreases the counter accordingly. @{b}LibClose()@{ub} calls the empty function
@{b}void _LibClose(struct Library *base __asm("a6"))@{ub}, which can be
overwritten by your own definition. This function contains the
base-pointer of the shared library.

   The function @{b}LibExpunge()@{ub} is always called when the operating system
wants to remove the library from memory. This is for instance done when
there is a memory shortage. The library can of course only be removed,
if it isn't opened by any program. The counter has to be 0, which shows
how important it is to close used libraries. A task of the function
@{b}LibExpunge()@{ub} is to call the automatic destructors or exit-functions.
For instance automatically opened libraries are closed again, and when
using C++ the destructors of global variables are called.

   The function @{b}LibNull()@{ub}, as its name suggests, does nothing at all,
and is reserved for future extensions.

Home-made initialisation and release
------------------------------------

   If you want to execute additional tasks when loading the library or
removing it from memory, you simply use the possibility to include
automatic initialisation- and exit-functions.

   In C++ you can for instance do this using global variables with a
type containing a constructor and destructor. These are then
automatically called in @{b}LibInit()@{ub} and @{b}LibExpunge()@{ub}. The execution-order
can be refined using the @{b}#pragma priority@{ub}.

   In ANSI-C you simply name the functions as expected by the linker to
call them automatically (see also @{"INIT and EXIT Functions" link "INIT and EXIT Functions"}). In shared
libraries, INIT and EXIT functions have the basepointer of the shared
library as argument. The prototype of the INIT and EXIT functions are
similar to an argumentless public shared library function, so:

   For 68K AmigaOS shared libraries:
     void INIT_0_test(struct MySharedLibBase *Base __asm("a6"))
     {
         ...
     }

   For PPC AmigaOS shared libraries:
     void INIT_0_test(struct MySharedLibBase *Base)
     {
         ...
     }

   An example:

     struct Library *DOSBase;
     struct Library *IntuitionBase;
     
     INIT_3_OpenLibraries(struct Library *mybase __asm("a6"))
     {
         DOSBase = OpenLibrary("dos.library", 37);
         IntuitionBase = OpenLibrary("intuition.library", 37);
     }
     
     EXIT_3_CloseLibraries(struct Library *mybase __asm("a6"))
     {
         CloseLibrary(IntuitionBase);
         CloseLibrary(DOSBase);
     }

   If shared library functions should also be called from the shared
library through the external interface (the jump-table of the shared
library), instead of directly as C functions, the following INIT
function is recommended:

     struct Library *MyBase;
     
     void INIT_0_MyBase(struct Library *Base __asm("a6"))
     {
         MyBase = Base;
     }

   With this function the base variable is initialized, which is
required when calling the shared library functions.

   If you want to abort the initialisation from within an INIT
function, you use the function @{b}abortLibInit()@{ub} instead of @{b}exit()@{ub}.

Libraryname and -version
------------------------

   The linker automatically creates the symbols @{b}_LibNameString@{ub} and
@{b}_LibVersionString@{ub}.  @{b}_LibNameString@{ub} is generated from the name of the
created library, @{b}_LibVersionString@{ub} contains the current date and the
version number, which was given in the linker settings.  If you wish,
you can define your own such symbols in your source, overwriting the
automatically created symbols.

Important tips to shared libraries
----------------------------------

   First develop your functions as usual, and write a testprogram for
these functions. Only after all functions to your satisfaction, convert
the project to a shared library, by removing the testprogram from the
project and inserting a suitable base-structure. Of course, you will
have to change some project settings.

   You will have gained two advantages: Shared-libraries must be
removed from memory each time a newer version is introduced, so you
must make sure that your testprogram closed the shared library, and
then remove the shared library from memory using the CLI command @{b}avail@{ub}
with the parameter @{b}flush@{ub}. This is much more work than simply restarting
the new program. Furthermore, you can not easily debug shared libraries.

   Make sure that your functions are re-entrant, meaning multiple
programs can use it at the same time. So you generally may not use
global or static local variables to save temporary results. If you want
to keep data across multiple function calls, you will have to work
object oriented in a way. You know this from the @{b}intuition.library@{ub}: You
open a window and get a @{b}struct Window*@{ub} returned. With this pointer you
can now manipulate the window, until you close it. The
@{b}intuition.library@{ub} now contains this pointer with each function-call,
and can work with the datastructure.  This way, global variables are
avoided.

   A shared library should not require to much stack. If you have to
create large amounts of data locally (for instance a large array), in
normal programs static local variables are often used. In shared
libraries you should put these variables on the stack and when needed
perform a @{b}StackSwap()@{ub} first, or temporary put the data in dynamic
memory, reserved with @{b}AllocMem()@{ub}. The third possibility is to use a
semaphore to protect the simultaneous use of static variables by
multiple programs. Which method you use depends on the situation.


@endnode

@node "Index" "Compiler.guide/Index"
@prev "Programming your own shared libraries"
@toc "Main"

Index
=====

@index "Index"



 @{" ##base                                   " link "Programming your own shared libraries"}   Programming your own shared libraries
 @{" ##bias                                   " link "Programming your own shared libraries"}   Programming your own shared libraries
 @{" ##end                                    " link "Programming your own shared libraries"}   Programming your own shared libraries
 @{" ##private                                " link "Programming your own shared libraries"}   Programming your own shared libraries
 @{" ##public                                 " link "Programming your own shared libraries"}   Programming your own shared libraries
 @{" #pragma libbase                          " link "Programming your own shared libraries"}   Programming your own shared libraries
 @{" #pragma priority                         " link "INIT and EXIT Functions"}   INIT and EXIT Functions
 @{" __asm                                    " link "Parameters in registers"}   Parameters in registers
 @{" __COMPMODE__                             " link "Predefined symbols"}   Predefined symbols
 @{" __cplusplus                              " link "Predefined symbols"}   Predefined symbols
 @{" __DATE2__                                " link "Predefined symbols"}   Predefined symbols
 @{" __DATE__                                 " link "Predefined symbols"}   Predefined symbols
 @{" __FILE__                                 " link "Predefined symbols"}   Predefined symbols
 @{" __FUNC__                                 " link "Predefined symbols"}   Predefined symbols
 @{" __GNUC__                                 " link "Predefined symbols"}   Predefined symbols
 @{" __GNUC_MINOR__                           " link "Predefined symbols"}   Predefined symbols
 @{" __inline                                 " link "Inline Functions"}   Inline Functions
 @{" __LibClose()                             " link "Programming your own shared libraries"}   Programming your own shared libraries
 @{" __LibOpen()                              " link "Programming your own shared libraries"}   Programming your own shared libraries
 @{" __LINE__                                 " link "Predefined symbols"}   Predefined symbols
 @{" __PPC__                                  " link "Predefined symbols"}   Predefined symbols
 @{" __saveds                                 " link "Attributes"}   Attributes
 @{" __STDC__                                 " link "Predefined symbols"}   Predefined symbols
 @{" __STORMGCC__                             " link "Predefined symbols"}   Predefined symbols
 @{" __TIME__                                 " link "Predefined symbols"}   Predefined symbols
 @{" abortLibInit()                           " link "Programming your own shared libraries"}   Programming your own shared libraries
 @{" amiga                                    " link "Predefined symbols"}   Predefined symbols
 @{" AMIGA                                    " link "Predefined symbols"}   Predefined symbols
 @{" amigaos                                  " link "Predefined symbols"}   Predefined symbols
 @{" EXIT_n_something()                       " link "INIT and EXIT Functions"}   INIT and EXIT Functions
 @{" GPL                                      " link "License"}   License
 @{" INIT_n_something()                       " link "INIT and EXIT Functions"}   INIT and EXIT Functions
 @{" inline                                   " link "Inline Functions"}   Inline Functions
 @{" LibClose()                               " link "Programming your own shared libraries"}   Programming your own shared libraries
 @{" LibExpunge()                             " link "Programming your own shared libraries"}   Programming your own shared libraries
 @{" LibInit()                                " link "Programming your own shared libraries"}   Programming your own shared libraries
 @{" LibNull()                                " link "Programming your own shared libraries"}   Programming your own shared libraries
 @{" LibOpen()                                " link "Programming your own shared libraries"}   Programming your own shared libraries
 @{" Libraryname                              " link "Programming your own shared libraries"}   Programming your own shared libraries
 @{" Libraryversion                           " link "Programming your own shared libraries"}   Programming your own shared libraries
 @{" mc68000                                  " link "Predefined symbols"}   Predefined symbols
 @{" MCH_AMIGA                                " link "Predefined symbols"}   Predefined symbols
 @{" register <1>                             " link "Parameters in registers"}   Parameters in registers
 @{" register                                 " link "Data in registers"}   Data in registers
 @{" Shared Libraries                         " link "Using shared libraries"}   Using shared libraries

@endnode

