@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