amiga-e/amigae33a/E_v3.3a/Docs/BeginnersGuide/Appendices.guide

498 lines
19 KiB
Plaintext

@database beginner.guide
@Master beginner
@Width 75
This is the AmigaGuide® file beginner.guide, produced by Makeinfo-1.55 from
the input file beginner.
@NODE "main" "Common Problems"
@Next "Other Information"
@Prev "Examples.guide/Recursion Example"
@Toc "Contents.guide/main"
Common Problems
***************
If you are new to programming or the Amiga E language then you might
appreciate some help locating problems (or @{fg shine }bugs@{fg text }) in your programs. This
Appendix details some of the most common mistakes people make.
@{" Assignment and Copying " Link "Assignment and Copying" }
@{" Pointers and Memory Allocation " Link "Pointers and Memory Allocation" }
@{" String and List Misuse " Link "String and List Misuse" }
@{" Initialising Data " Link "Initialising Data" }
@{" Freeing Resources " Link "Freeing Resources" }
@{" Pointers and Dereferencing " Link "Pointers and Dereferencing" }
@{" Mathematics Functions " Link "Mathematics Functions" }
@{" Signed and Unsigned Values " Link "Signed and Unsigned Values" }
@ENDNODE
@NODE "Assignment and Copying" "Assignment and Copying"
@Next "Pointers and Memory Allocation"
@Toc "main"
Assignment and Copying
======================
This is probably the most common problem encountered by people who are
used to languages like BASIC. Strings, lists, arrays and objects cannot
be initialised using an assignment statement: data must be copied. Unlike
BASIC, this kind of data is represented by a pointer (see @{"PTR Type" Link "Types.guide/PTR Type" }), so
only the pointer would be copied by an assignment statement, not the data
it points to. The following examples all copy a pointer rather than the
data, and so the memory for the data is shared (and this is probably not
what was intended).
DEF s[30]:STRING, t[30]:STRING,
l[10]:LIST, m[10]:LIST,
x:myobj, y:myobj,
a[25]:ARRAY OF INT, b[25]:ARRAY OF INT
/* You probably don't want to do any of these */
s:='Some text in a string'
l:=[-6,4,-9]
x:=[1,2,3]:myobj
a:=[1,-3,8,7]:INT
t:=s
m:=l
y:=x
b:=a
All the declarations allocate memory for the appropriate data. The first
four assignments replace the pointers to this memory with pointers to some
statically allocated memory. The memory allocated by the declarations is
probably now unreachable, because the only pointers to it have been
over-written. BASIC programmers might expect, say, the assignment to @{b }s@{ub } to
have copied the string into the memory allocated for @{b }s@{ub } by its declaration,
but this is not the case (only the pointer to the string is copied).
For the E-string, @{b }s@{ub }, and E-list, @{b }l@{ub }, there is another, disastrous
side-effect. The assignment to @{b }s@{ub }, for example, means that @{b }s@{ub } will point to
a normal string, not an E-string. So, @{b }s@{ub } can no longer be used with any of
the E-string functions. The same considerations apply to the E-list, @{b }l@{ub },
as well.
The final four assignments also copy only the pointers. This means
that @{b }s@{ub } and @{b }t@{ub } will point to exactly the same memory. So they will
represent exactly the same string, and any change to one of them (by a
@{b }StrAdd@{ub }, for example) will appear to change both (of course, only one lump
of memory is being changed, but there are two references to it). This is
called memory @{fg shine }sharing@{fg text }, and is only a problem if you didn't intend to do
it!
To get the result that a BASIC programmer might have intended you need
to copy the appropriate data. For E-strings and E-lists the functions to
use are, respectively, @{b }StrCopy@{ub } and @{b }ListCopy@{ub }. All other data must be
copied using a function like @{b }CopyMem@{ub } (an Amiga system function from the
Exec library). (Normal strings can be copied using @{b }AstrCopy@{ub } built-in
function, see the `Reference Manual'.) Here's the revised forms of the
above assignments:
DEF s[30]:STRING, t[30]:STRING,
l[10]:LIST, m[10]:LIST,
x:myobj, y:myobj,
a[25]:ARRAY OF INT, b[25]:ARRAY OF INT
StrCopy(s, 'Some text in a string') /* Defaults to ALL */
ListCopy(l, [-6,4,-9]) /* Defaults to ALL */
CopyMem([1,2,3]:myobj, x, SIZEOF myobj)
CopyMem([1,-3,8,7]:INT, a, 4*SIZEOF INT)
StrCopy(t, s) /* Defaults to ALL */
ListCopy(m, l) /* Defaults to ALL */
CopyMem(x, y, SIZEOF myobj)
CopyMem(a, b, 4*SIZEOF INT)
Notice that you need to supply the size (in bytes) of the data being
copied when you use @{b }CopyMem@{ub }. The parameters are also given in a slightly
different order to the E-string and E-list copying functions (i.e., the
source must be the first parameter and the destination the second). The
@{b }CopyMem@{ub } function does a byte-by-byte copy, something like this:
PROC copymem(src, dest, size)
DEF i
FOR i:=1 TO size DO dest[]++:=src[]++
ENDPROC
Of course, you can use string constants and lists to give initialised
arrays, but in this case you should be initialising an appropriately typed
pointer. You must also be careful not to run into a static data problem
(see @{"Static data" Link "Types.guide/Static data" }).
DEF s:PTR TO CHAR, l:PTR TO LONG, x:PTR TO myobj, a:PTR TO INT
s:='Some text in a string'
l:=[-6,4,-9]
x:=[1,2,3]:myobj
a:=[1,-3,8,7]:INT
@ENDNODE
@NODE "Pointers and Memory Allocation" "Pointers and Memory Allocation"
@Next "String and List Misuse"
@Prev "Assignment and Copying"
@Toc "main"
Pointers and Memory Allocation
==============================
Another common error is to declare a pointer (usually a pointer to an
object) and then use it without the memory for the target data being
allocated.
/* You don't want to do this */
DEF p:PTR TO object
p.element:=99
There are two ways of correcting this: either dynamically allocate the
memory using @{b }NEW@{ub } or, more simply, let an appropriate declaration allocate
it. See @{"Memory Allocation" Link "Memory.guide/main" }.
DEF p:PTR TO object
NEW p
p.element:=99
DEF p:object
p.element:=99
@ENDNODE
@NODE "String and List Misuse" "String and List Misuse"
@Next "Initialising Data"
@Prev "Pointers and Memory Allocation"
@Toc "main"
String and List Misuse
======================
Some of the string functions can only be used with E-strings.
Generally, these are the ones that might extend the string. If you use a
normal string instead you can run into some serious (but subtle) problems.
Commonly misused functions are @{b }ReadStr@{ub }, @{b }MidStr@{ub } and @{b }RightStr@{ub }. Similar
problems can arise by using a list when an E-list is required by a list
function.
String constants and normal lists are static data, so you shouldn't try
to alter their contents unless you know what you're doing (see
@{"Static data" Link "Types.guide/Static data" }).
@ENDNODE
@NODE "Initialising Data" "Initialising Data"
@Next "Freeing Resources"
@Prev "String and List Misuse"
@Toc "main"
Initialising Data
=================
Probably one of the most common mistakes that even seasoned programmers
make is to forget to initialise variables (especially pointers). The
rules in the `Reference Manual' state which declarations initialise
variables to zero values, but it is often wise to make even these explicit
(using initialised declarations). Variable initialisation becomes even
more important when using automatic exceptions.
@ENDNODE
@NODE "Freeing Resources" "Freeing Resources"
@Next "Pointers and Dereferencing"
@Prev "Initialising Data"
@Toc "main"
Freeing Resources
=================
Unlike a Unix operating system, the Amiga operating system requires the
programmer to release or free any resources used by a program. In
practice, this means that all windows, screens, libraries, etc., that are
successfully opened must be closed before the program terminates. Amiga E
provides some help, though: the four most commonly used libraries (Dos,
Exec, Graphics and Intuition) are opened before the start of an E program
and closed at the end (or when @{b }CleanUp@{ub } is called). Also, memory allocated
using any of @{b }List@{ub }, @{b }String@{ub }, @{b }New@{ub }, @{b }NEW@{ub }, @{b }NewR@{ub }, @{b }NewM@{ub } and @{b }FastNew@{ub } is
automatically freed at the end of a program.
@ENDNODE
@NODE "Pointers and Dereferencing" "Pointers and Dereferencing"
@Next "Mathematics Functions"
@Prev "Freeing Resources"
@Toc "main"
Pointers and Dereferencing
==========================
C programmers may think that the @{b } ^@{ub }@{fg shine }var@{fg text }@{b }@{ub } and @{b }{@{ub }@{fg shine }var@{fg text } @{b } }@{ub } expressions
are the direct equivalent of C's @{b } &@{ub }@{fg shine }var@{fg text }@{b }@{ub } and @{b } *@{ub }@{fg shine }var@{fg text }@{b }@{ub } expressions.
However, in E dereferencing is normally achieved using array and object
element selection, and pointers to large amounts of data (like E-strings
or objects) are made by declarations. This means that the @{b } ^@{ub }@{fg shine }var@{fg text }@{b }@{ub } and
@{b }{@{ub }@{fg shine }var@{fg text } @{b } }@{ub } expressions are rarely used, whilst @{b }@{ub }@{fg shine }var@{fg text }@{b }[]@{ub } is very
common.
@ENDNODE
@NODE "Mathematics Functions" "Mathematics Functions"
@Next "Signed and Unsigned Values"
@Prev "Pointers and Dereferencing"
@Toc "main"
Mathematics Functions
=====================
The standard mathematical operators @{b }/@{ub } and @{b }*@{ub } do not use full 32-bit
values in their calculations, as noted previously (see
@{"Maths and logic functions" Link "BuiltIns.guide/Maths and logic functions" }). A common problem is to forget this and use
them where the values will exceed the 16-bit limit. A typical example is
the position calculations used with proportional gadgets. See
@{"Signed and Unsigned Values" Link "Signed and Unsigned Values" }.
@ENDNODE
@NODE "Signed and Unsigned Values" "Signed and Unsigned Values"
@Prev "Mathematics Functions"
@Toc "main"
Signed and Unsigned Values
==========================
This is a quite advanced topic, but might be the cause of some strange
bugs in your programs. Basically, E does not have a way of
differentiating signed and unsigned values from, say, the @{b }LONG@{ub } type. That
is, all values from the 32-bit, @{b }LONG@{ub } type are considered to be signed
values, so the range of values is from -2,147,483,648 to 2,147,483,647.
If the values from this type were taken to be unsigned then no negative
values would be allowed but more positive values would be possible (i.e.,
the range of values would be from zero to 4,294,967,295). This
distinction would also affect the mathematical operators.
In practice, though, it is not the @{b }LONG@{ub } type that can cause problems.
Instead, it is the 16-bit, @{b }INT@{ub } type, which again is considered to be
signed. This means that the range of values is -32,768 to 32,767.
However, the Amiga system objects contain a number of 16-bit, @{b }INT@{ub } elements
which are actually interpreted as unsigned, ranging from zero to 65,535.
A prominent example is the proportional gadget which forms a part of a
scroll-bar on a window (for example, a drawer window on Workbench). This
works with unsigned 16-bit values, which is at odds with the @{b }INT@{ub } type in E.
These values are commonly used in calculations to determine the position
of something displayed in a window, and if the @{b }INT@{ub } type is used without
taking into account this signed/unsigned problem the results can be quite
wrong. Luckily it is very simple to convert the signed @{b }INT@{ub } values into
unsigned values if they are part of some expression, since the value of
any expression is taken from the @{b }LONG@{ub } type (and unsigned @{b }INT@{ub } values fit
well within the range of even signed @{b }LONG@{ub } values).
PROC unsigned_int(x) IS x AND $FFFF
The function @{b }unsigned_int@{ub }, above, is very specific to the way the Amiga
handles values internally, so to understand how it works is beyond the
scope of this Guide. It should be used wherever an unsigned 16-bit value
is stored in an @{b }INT@{ub } element of, say, an Amiga system object. For example,
the position of the top of a (vertical) proportional gadget as a
percentage (zero to one hundred) of its size can be calculated like this:
/* propinfo is from the module 'intuition/intuition' */
DEF gad:PTR TO propinfo, pct
/* Set up gad... */
/* Calculate percentage (MAXPOT is from 'intuition/intuition') */
pct:=Div(Mul(100,unsigned_int(gad.vertpot)),MAXPOT)
Notice that the full 32-bit functions @{b }Div@{ub } and @{b }Mul@{ub } need to be used since
the arithmetic may be well over the normal 16-bits used in the @{b }/@{ub } and @{b }*@{ub }
operators.
The remaining type, @{b }CHAR@{ub }, is not, in practice, a problem. It is the
only unsigned type, with a range of values from zero to 255. There is a
fairly simple way to convert these values to signed values (and again this
is particular to the way the Amiga stores values internally). One good
example of a signed @{b }CHAR@{ub } value is the priority value associated with a
node of an Amiga list (i.e., the @{b }pri@{ub } element of an @{b }ln@{ub } object from the
module @{b }exec/nodes@{ub }).
PROC signed_char(x) IS IF x<128 THEN x ELSE x-256
@ENDNODE
@NODE "Other Information" "Other Information"
@Next "EIndex.guide/main"
@Prev "main"
@Toc "Contents.guide/main"
Other Information
*****************
This Appendix contains some useful, miscellaneous information.
@{" Amiga E Versions " Link "Amiga E Versions" }
@{" Further Reading " Link "Further Reading" }
@{" Amiga E Author " Link "Amiga E Author" }
@{" Guide Author " Link "Guide Author" }
@ENDNODE
@NODE "Amiga E Versions" "Amiga E Versions"
@Next "Further Reading"
@Toc "Other Information"
Amiga E Versions
================
As I write, the current version of Amiga E is version 3.2e (which is
minor update of v3.2a). This edition of the Guide is based primarily on
that version, but the majority still applies to the older versions,
including the last Public Domain version (v2.1b). Version 3.3 is
imminent, and the new `Reference Manual' will contain details of the new
features and changes.
Please note that, as of v3.0a, Amiga E is a commercial product so you
must pay a fee to get a version of the full compiler (which will be
registered to you). The Public Domain distribution contains only a
demonstration version of the compiler, with limited functionality. See
the `Reference Manual' for more details.
@ENDNODE
@NODE "Further Reading" "Further Reading"
@Next "Amiga E Author"
@Prev "Amiga E Versions"
@Toc "Other Information"
Further Reading
===============
`Amiga E Language Reference'
Referred to as the `Reference Manual' in this Guide. This is one of
the documents that comes with the Amiga E package, and is essential
reading since it was written by Wouter (the author of Amiga E). It
contains a lot of extra information.
`Rom Kernel Reference Manual' (Addison-Wesley)
This is the official Commodore documentation on the Amiga system
functions and is a must if you want to use these functions properly.
At the time of writing the Third Edition is the most current and it
covers the Amiga system functions up to Release 2 (i.e., AmigaDOS
2.04 and KickStart 37). Because there is so much information it
comes in three separate volumes: `Libraries', `Includes and
Autodocs', and `Devices'. The `Libraries' volume is probably the
most useful as it contains many examples and a lot of tutorial
material. However, the examples are written mainly in C (the
remainder are in Assembly). To alleviate this problem I have
undertaken to re-code them in E, and Part One and Part Two of this
effort should be available from Aminet or good PD houses (the archive
names will be something like @{b }JRH-RKRM-1@{ub } and @{b }JRH-RKRM-2@{ub }).
(Unfortunately, it seems that the actual manuals may be hard to find
since there are now out-of-print.)
`The AmigaDOS Manual' (Bantam Books)
This is the companion to the `Rom Kernel Reference Manual' and is the
official Commodore book on AmigaDOS (both the AmigaDOS programs and
the DOS library functions). Again, the Third Edition is the most
current.
Example sources
Amiga E comes with a large collection of example programs. When
you're familiar with the language you should be able to learn quite a
bit from these. There are a lot of small, tutorial programs and a
few large, complicated programs.
@ENDNODE
@NODE "Amiga E Author" "Amiga E Author"
@Next "Guide Author"
@Prev "Further Reading"
@Toc "Other Information"
Amiga E Author
==============
In case you didn't know the author and creator of Amiga E is Wouter van
Oortmerssen (or @{b }$#%!@{ub }). You can reach him by normal mail at the following
address:
Wouter van Oortmerssen (@{b }$#%!@{ub })
Levendaal 87
2311 JG Leiden
HOLLAND
However, he much prefers to chat by E-mail, and you can reach him at the
following addresses:
@{b }Wouter@alf.let.uva.nl@{ub } (E-programming support)
@{b }Wouter@mars.let.uva.nl@{ub } (personal)
@{b }Oortmers@gene.fwi.uva.nl@{ub } (other)
Better still, if your problem or enquiry is of general interest to Amiga E
users you may find it useful joining the Amiga E mailing list. Wouter
regularly contributes to this list and there are a number of good
programmers who are at hand to help or discuss problems. To join send a
message to:
@{b }amigae-request@bkhouse.cts.com@{ub }
Once you're subscribed, you will receive a copy of each message mailed to
the list. You will also receive a message telling you how you can
contribute (i.e., ask questions!).
@ENDNODE
@NODE "Guide Author" "Guide Author"
@Prev "Amiga E Author"
@Toc "Other Information"
Guide Author
============
This Guide was written by Jason Hulance, with a lot of help and
guidance from Wouter. The original aim was to produce something that
might be a useful introduction to Amiga E for beginners, so that the
language could (rightly) become more widespread. The hidden agenda was to
free Wouter from such a task so that he could concentrate his efforts on
improving Amiga E.
You can reach me by normal mail most easily at the following (work)
address:
Jason R. Hulance
Formal Systems (Europe) Ltd.
3 Alfred Street
Oxford
OX1 4EH
ENGLAND
Alternatively, you can find me on the Amiga E mailing list, or E-mail me
directly at one of the following addresses:
@{b }jason@fsel.com@{ub }
@{b }m88jrh@ecs.oxford.ac.uk@{ub }
If you have any changes or additions you'd like to see then I'd be very
happy to consider them. Criticism of the text is also welcome, especially
if you can suggest a better way of explaining things. I am also keen to
hear from people who can highlight areas that are particularly confusing
or badly worded!
@ENDNODE