Appendix A Converting ProgramsIntroduction This Appendix is intended for use by programmers wishing to convert various forms of BASIC into HiSOFT BASIC. It starts with general notes about all conversions, then is sub-divided into sections for particular common BASIC implementations. It finishes with some hints and tips on writing programs that can easily be ported to the IBM PC, Macintosh and Amiga General Conversions Most BASICs share a certain core of the language, no matter how different they seem to be. PRINT always does the same thing, so does INPUT and so forth. BASICs can differ by being machine specific, ANSI standard, or conforming to a certain style (Microsoft's QuickBASIC and Borland's Turbo Basic are notable examples). Whichever BASIC you are trying to convert a program from, you will need to get the source into ASCII. Some BASICs use ASCII for their programs anyway, but most interpreters use a tokenised form that will come out as gibberish if loaded into the editor. You should save your program from your BASIC interpreter using an ASCII option, if possible. Some things stand very little chance of being the same from one BASIC to another, in particular internal floating point representations and random-access file formats. One thing to be aware of particularly is that string length limitations found in other BASICs do not exist in HiSOFT BASIC. In particular the LEN function can return a long integer as a result, not just an integer as in other BASICs. HiSOFT BASIC 1The following is a summary of some potential incompatibilities between HiSOFT BASIC 1 and version 2; don't panic at the size of this list as the majority of HiSOFT BASIC and its baby sister, Power BASIC, programs will compile without change. We have listed these under headings of facilities used. LIBRARY statement If you have used a path to the BMAP file without a colon or leading / you will need to change this; the best way is to remove the path and use the HiSOFT BASIC Library Path option (LIBPATH). REDIM/ERASE of arrays If you dimension an array using just a number or a constant (e.g. DIM A(1000) you can't ERASE or REDIM it in HiSOFT BASIC 2 unless you add REM $DYNAMIC before the DIM statement. If the DIM expression is a non-constant expression e.g. array_size=100 DIM A(array_size) then there is no need for this change. As well as enabling the compiler to produce faster code for static arrays, this change also brings HiSOFT BASIC in line with the Microsoft QuickBASIC usage. ERL function If no logical line numbers have been used, this function will now return the physical line number that caused the error. If your ON...ERROR routine is testing to see if ERL is 0 (perhaps to see if you are still in your initialisation code) then you'll need to insert a line number at the start of your program and test for this value instead. This feature was introduced so that modern programs that need to use an ON...ERROR to ensure safe termination (freeing operating system resources for example) can give an indication of the source of the error. This facility is however not available in Microsoft BASIC on the PC. LOC on COM1: The LOC statement when used on files opened with COM1: now returns the number of characters waiting rather than just a 1 if there are any characters waiting. So use something like this: DO chars%=LOC(3) IF chars% THEN a$=INPUT$(a%,3) PRINT a$ END IF LOOP rather than DO IF LOC(3) THEN a$=INPUT$(1,3) PRINT a$ END IF LOOP New reserved words The following are now reserved words: BEGINIO, BYVAL, CURDIR$, FORMATD$, FORMATI$, FORMATL$, FORMATS$, FREEFILE, INITHOOK, IS, LTRIM$, MAX, MIN, PEEK$, PRESERVE, RINSTR, RTRIM$, TAGLIST and so can no longer be used as names for user variables, sub-programs and labels. If you are in a hurry to compile your existing HiSOFT BASIC 1 program then you can include HBAm1.BH at the start of your program and then these reserved words will be disabled. AmigaBASIC In the dim, distant past AmigaBASIC was supplied free with all the Amiga computers and therefore we endeavoured to make HiSOFT BASIC 1 as compatible as we could with it. However despite all the extensions to the language, HiSOFT BASIC 2 will run many existing AmigaBASIC programs unchanged. Note that all references to AmigaBASIC refer to version 1.2, the final version. De-tokenising Before trying to compile any program from the interpreter, the source must be converted to ASCII instead of the special tokenised form that the interpreter uses to store its files. To do this , load the interpreter, then load your program. Select the Output window then type a line such as SAVE "filename.bas",a where "filename.bas" should be changed as required. The ,a at the end is important - it tells the interpreter to save the file as ASCII. We strongly recommend that source files follow the .bas naming convention, so you can tell them apart from compiled versions, for example. The file so created can then be used by HiSOFT BASIC and you can load it back into the interpreter at any time without conversion because HiSOFT BASIC only uses ASCII files and the interpreter can read them directly. Unimplemented Features The following features of AmigaBASIC are not implemented in HiSOFT BASIC: COMMON, RESUME NEXT, OBJECT.PRIORITY In addition, interpreter only statements such as LOAD, SAVE etc are not implemented as they make no sense in a compiler environment. Compatibility Issues We have tried wherever possible to be compatible with the interpreter in both source syntax and run-time emulation. In terms of source syntax, HiSOFT BASIC accepts practically all legal AmigaBASIC syntax, except that you may be using a variable which has the same name as one of the additional reserved words, such as SYSTAB. If you are in a hurry to compile an existing AmigaBASIC program then you can include AmBas.BH at the start of your program and then these reserved words will be disabled. When trying to compile existing programs that seemed to run perfectly under the interpreter, the compiler may find errors the interpreter missed, normally in a section of code that seldom gets executed. Note that HiSOFT BASIC does not allow a variable to be the same name as a program label, but this is unlikely to cause problems. Some AmigaBASIC programs use LOOP as a variable name: this is not possible with HiSOFT BASIC as this is a reserved word used for the general loop structure. In terms of run-time emulation, we have tried to emulate the exact actions of the interpreter, where it made sense to do so. We discovered several undocumented features of the interpreter during the development of the compiler (e.g. FRE(-3)) and emulated those found. However there are bound to be circumstances that we did not try and if you rely on an undocumented feature it may not work the same under the compiler. There are some features of the run-time system we decided not to emulate, such limiting the maximum window size to non-PAL sized screens and various guru-type bugs. Under the interpreter you can use DECLARE...LIBRARY for library sub-programs/functions before you have used the LIBRARY statement; the DECLARE statements must be after the LIBRARY statement in HiSOFT BASIC. Multi-dimensional arrays are stored in a different order to that used by AmigaBASIC; generally this isn't a problem except when the graphics GET and PUT statements are used with such an array. Note that double-precision variables are stored in a different order in memory between the compiler and the interpreter, but this will only effect programs doing rather nasty things with VARPTR. In addition, single-precision numbers are stored in a completely different format (though are still 4 bytes in size) which has less range than that used by the interpreter. When reading and writing random-access files (using MKD, MKS, CVD and CVS) we are as compatible as possible with the interpreter though, except for the range limit on single-precision numbers. Also note that VARPTR returns a pointer to a string descriptor, but the string descriptors themselves are very different under the interpreter and the compiler. Programs that use VARPTR to directly adjust string descriptors will not work without modification. Old-Style Microsoft BASICs Microsoft BASIC is the closest to a world standard for the BASIC language and is the one around which we designed HiSOFT BASIC. For this reason most versions of Microsoft BASIC should not present problems converting to HiSOFT BASIC. Programs written in the old-style BASICs, such as those found in Commodore 64s and under CP/M should require little or no work to convert, as long as machine-specific PEEKs and POKEs are avoided. You can also save typing by not entering the line numbers that aren't needed. Most BASIC interpreters from other vendors are at least in part based on the same principles as Microsoft so should also convert reasonably easily. New-Style Microsoft BASICs The new style of Microsoft BASIC is defined by QuickBASIC, Visual BASIC and the Microsoft BASIC PDS and running on IBMs and compatibles. By new-style we mean support for structured programming such as sub-programs and parameter passing, CASE, , DO etc. HiSOFT BASIC supports almost all the features of QuickBASIC 2 and 3 and most of the features of QuickBASIC 4.0, 4.5 and has some additional features from the PDS 7.1 system. The main advantages of HiSOFT BASIC that you can exploit when converting programs from the IBM world, are the large memory and greater graphic support. In addition, recursive programming techniques can be used. When converting QuickBASIC programs there are a few things which are not supported by HiSOFT BASIC by reason of operating system or hardware differences. Missing statements under this category are: COM, CVSMBF,CVSMBF,DRAW, ERDEV, ERDEV$, FILEATTR IOCTL$, IOCTL, KEY, , LOCK, MKDMBF$,MKSMBF$, ON various, PAINT, PEN, PLAY, PMAP, SETMEM, SHELL, UEVENT, UNLOCK, VARPTR$, VARSEG, VIEW, and WAIT Obviously PEEKs and POKEs are completely different, as are machine-code calling conventions. There are also slight differences in the following commands: CIRCLE, CLEAR, CLS, COLOR, FILES, LINE, LOCATE, OPEN, PCOPY, POINT, SCREEN, SEEK, SOUND, STICK, and WINDOW. HiSOFT BASIC does not at this time support the following Microsoft BASIC statements: COMMON , DOUBLE, INTEGER, LONG, RESUME NEXT, SINGLE, TYPE...END TYPE In addition to this high degree of Microsoft compatibility, HiSOFT BASIC also compiles many of the additional features found in Borland's Turbo Basic compiler and Spectra Publishing's Power BASIC for the PC. HiSOFT BASIC 2 on the Atari The main area of incompatibility here is in graphics commands. The Amiga version does not support the following HiSOFT BASIC Atari commands: BAR, CLEARW, CLOSEW, ELLIPSE, ENVIRON, ENVIRON$, FILL, FULLW, GB, GEMSYS, GETCOOKIE, LINEF, OPENW, PCIRCLE, SPOKB, SPOKEW, SPOKEL, SPEEKB, SPEEKW, SPEEKL, VDISYS The following commands are implemented on both machines but differ in their action: CIRCLE, COLOR, FRE, PALETTE, SCREEN, SOUND, SYSTAB, WAVE, WINDOW. The following are reserved words in HiSOFT BASIC 2 Amiga but may be used as variables on the Atari; either change the variable names or use the HBST2.BH include file - this will prevent you from accessing the following BASIC Amiga commands: AREA, AREAFILL, BEGINIO, BREAK. COLLISION, CVFFP, INITHOOK, LIBRARY, MENU, MKFFP$, OBJECT.various, ON... various, PAINT, PEEK$, PTAB, SAY, SCROLL, TAGLIST, TRANSLATE$ In addition, we also supply HBST1.BH which also excludes the reserved words that were introduced in version 2 of HiSOFT BASIC for the Atari. Writing for compatibility We are often asked which compiler you should purchase to make it easy to port a program that you've written in HiSOFT BASIC on the Amiga if you want to move it to another system. At the time of writing we recommend the following: For the PC, MicroSoft's BASIC PDS 7.1 or the much cheaper, but less sophisticated, QuickBASIC 4.5 or QBASIC that is supplied with MSDOS. For the Macintosh, Microsoft QuickBASIC. For the Atari ST/TT/Falcon, HiSOFT BASIC of course. If you want to write your program so that it is easy to port to other systems, here are a few hints: * Isolate your use of system specific features to a few sub-programs. If you can, try porting these to other machines before you use them extensively; you may find that you are relying on something that is easy on the Amiga, but different on another machine. * If you are porting to a non-HiSOFT product be wary of limitations on the sizes of strings and arrays. QuickBASIC 4.5 doesn't allow more than 64K of strings total for example and many BASICs won't let you have more than 32767 elements in an array. * Use the forms of statement that we recommend in the Command Reference section. For example, use EXIT DO rather than EXIT LOOP and REDIM PRESERVE rather than REDIM APPEND. Appendix B Hints and Tips This chapter shows how you can get the most out of programs written with the HiSOFT BASIC compiler. It is not necessarily intended only for the advanced programmer. Using HiSOFT BASIC Making a more efficient program requires knowledge of the features of HiSOFT BASIC. The following suggestions are intended to give you a firmer understanding of what can be done; we also hope that you will use this information as the basis for a more detailed exploration of HiSOFT BASIC. defint a-z It is a good idea to have this line in your program, it makes the default variable type a short integer. The main benefit from using ints is speed. The source becomes more understandable when &, !, and # are used explicitly. rem $VARCHECKS This forces variable checks on. The primary benefit of this is that you can avoid unnecessary bugs caused by undefined variables in sub-programs and functions. This is especially important when programming using the operating system include files. STATIC variables in SUBs and FNs STATIC variables retain their values when a SUB or FUNCTION is exited and re-entered. There is a speed benefit in using STATICs as opposed to LOCALs: STATICs are only allocated once, whereas LOCALs must be allocated every time a SUB or FUNCTION is invoked. If your SUB or FUNCTION is recursive then LOCAL variables must be used. INCR and DECR These two statements respectively increment and decrement the value of a variable by one. When used on array elements they are considerably faster than e.g. Arr(1)=Arr(1)+1. == The double-equals comparison operator has a different meaning depending on the type of value compared. When comparing strings, a case-independent comparison is made. It is considerably faster than using UCASE$ or LCASE$ and then comparing, or doing something like IF fred$="A" or fred$="a" THEN... When comparing numeric values, == is used as Ôalmost equals'; rounding errors can thus be avoided. There is a performance degradation when using == on numeric values. Note that this is a HiSOFT extension. ! as opposed to # When using floating point maths, it is a good idea to know exactly how much accuracy is actually necessary. Single-precision is much faster than double-precision, due to the degree of accuracy required. If you want floating point, but do not need such a high degree of precision, single-precision is the variable type to use. The exception to this is if you have a maths co-processor fitted to your system where doubles may actually be faster than singles. The reason for this is that our double routines use the system libraries that will automatically use an FPU if installed whereas the single routines are software only. Use pre-tokenised files If you are using our operating system include (.bh and .bc) files then it is well worth building a pre-tokenised file containing those include files that you are using - you will get much faster compilations as a result. VARPTR, SADD and PEEKtype When using VARPTR and SADD, you must be very careful. The reason for this is quite simple: owing to the dynamic heap allocation and the blindingly-fast garbage collection of HiSOFT BASIC, strings are prone to move around without any prior notice. This is normally completely transparent to the user, but when using these functions it becomes a factor to be reckoned with. If you are going to use them, call the functions just before accessing the variable or array. In addition the address of any array will be invalid if a REDIM or ERASE statement has been executed since VARPTR was used to find the address. After using these functions, a PEEK or POKE is usually inflicted upon the data at the returned address. HiSOFT BASIC has faster varieties of PEEK and POKE and they are type-specific. The can be used to great effect e.g. when parsing a string. Let us suppose an entire file has been loaded into a single string using INPUT$; this is quite possible because strings in HiSOFT BASIC are only limited by available memory. SADD is called to determine where the string is. To go through the file at high speed, all you need is to remember your place in the string and PEEKB from the location that you need. Do not use PEEKW or PEEKL because strings can be on odd boundaries and an address exception will occur if you try to read a word or long from an odd address. Making Your Programs "NoLimits" If you have been used to programming in more primitive versions of BASIC or in Pascal or C, avoiding arbitrary restrictions on the size and type of data that your program can manipulate can be hard work. For example, having a limit on the length of names that you can type into a business application can sometimes be very annoying. Similarly avoiding limits on the lengths of files and in line lengths can save you a lot of time, if say the file in question has odd end-of-line markers that mean that your program treats the whole file as one line. The following hints should help to avoid this sort of problem: When reading in or adding to arrays, have code to make the array larger if need be. In general adding a few elements at a time is not a good idea because the program may start spending all its time moving arrays. Normally it is a good idea to start off an array with the size as just larger than a typical requirement, but if an array is only used occasionally then the dimension can start off small. For example, if writing a cross-reference program for HiSOFT BASIC programs, it would probably a good idea to start by assuming that the number of line numbers is small (say 10) and then if the program turns out to be a horrible old-fashioned program with a line number on every line then the arrays used for holding them can be grown using REDIM PRESERVE at, say, 100 elements at a time. When using byte or record numbers in files or strings use long integer variables (terminated with &). This should remove automatically many 32k or 64k limits on programs that are designed with 16-bit integers in mind. Appendix C Reserved Words On the following page is a complete list of the reserved words that are included within HiSOFT BASIC. Normally, these words may not be used as sub-program or label names or as variable names; you can, however, remove a particular reserved word using the $DISABLE compiler option. This is included for maximum compatibility with other versions of the BASIC language. See Chapter 4: The Compiler for more details. of removing and re-naming HiSOFT BASIC reserved words. Most of these words are built-in HiSOFT BASIC language features and, as such, are described in the Command Reference chapter; you should note, however, that not all these words will be described directly in this chapter. For example, TO is a reserved word but will not have an entry in the Command Reference since it is part of the FOR...NEXT syntax. In addition, there may be some words that are included for compatibility with other languages that are not described in Command Reference. ABS ACCESS ALIAS AND APPEND AREA AREAFILL AS ASC ATN AUTO BASE BEEP BEGINIO BIN$ BLOAD BREAK BSAVE BYVAL CALL CALLS CASE CDBL CDECL CHAIN CHDIR CHR$ CINT CIRCLE CLEAR CLNG CLOSE CLS COLLISION COLOR COMMAND$ COMMON CONST COS CSNG CSRLIN CURDIR$ CVD CVFFP CVI CVL CVS DATA DATE$ DECLARE DECR DEF DEFDBL DEFINT DEFLNG DEFSNG DEFSTR DIM DO ELLIPSE ELSE ELSEIF END ENVIRON ENVIRON$ EOF EQV ERASE ERL ERR ERROR EXIT EXP FEXISTS FIELD FILES FIX FOR FORMATD$ FORMATI$ FORMATL$ FORMATS$ FRE FREEFILE FUNCTION GET GOSUB GOTO HEX$ IF IMP INCR INITHOOK INKEY$ INPUT INPUT$ INSTR INT IS KEY KILL LBOUND LCASE$ LEFT$ LEN LET LIBRARY LINE LOC LOCAL LOCATE LOF LOG LOG10 LOG2 LOOP LPOS LPRINT LSET LTRIM$ MAX MENU MID$ MIN MKD$ MKDIR MKFFP$ MKI$ MKL$ MKS$ MOD MOUSE NAME NEXT NOT OBJECT.AX OBJECT.AY OBJECT.CLIP OBJECT.CLOSE OBJECT.HIT OBJECT.OFF OBJECT.ON OBJECT.PLANES OBJECT.SHAPE OBJECT.START OBJECT.STOP OBJECT.VX OBJECT.VY OBJECT.X OBJECT.Y OCT$ OFF ON OPEN OPTION OR OUTPUT PAINT PALETTE PATTERN PCIRCLE PCOPY PEEK PEEK$ PEEKB PEEKL PEEKW PELLIPSE POINT POKE POKEB POKEL POKEW POS PRESERVE PRESET PRINT PSET PTAB PUT RANDOM RANDOMIZE READ REDIM REM REMAINDER REPEAT RESET RESTORE RESUME RETURN RIGHT$ RINSTR RMDIR RND RSET RTRIM$ RUN SADD SAY SCREEN SCROLL SELECT SGN SHARED SIN SLEEP SOUND SPACE$ SPC SQR STATIC STEP STICK STOP STR$ STRIG STRING$ SUB SWAP SYSTAB SYSTEM TAB TAGLIST TAN THEN TIME$ TIMER TO TRANSLATE$ TROFF TRON UBOUND UCASE$ UNTIL USING VAL VARPTR VARPTRS WAIT WAVE WEND WHILE WIDTH WINDOW WRITE XOR Appendix D Compiler Options The table on the next page gives the complete set of options, with the new name, the old HiSOFT BASIC 1 form, a description and the requester in which they appear. The new names shown in this table are the names to use to override the standalone compiler's defaults. New Old Description Requester ADDICON Add default Icon Compile ARRAY A Array Checks Advanced NOAUTODIM Auto-DIM arrays Compile BATCH C Continue on Compiler Errors Advanced BREAK B Break Checks Compile CHECK Check Source code Other COMPILE Compile Source file Other DEBUG S Add Debug information Compile DISABLE Remove reserved words Other ERRORS E Add Error Messages Compile EVENT Event checks Compile EXPORTS Export Variables Advanced FROM Compile from File HCLNDEBUG Compressed Line Debug Compile HEAPDYNAMIC Heap Size Advanced ICONS G Create Icons Other INCPATH Include Path File NOJUMPS Remove inter-sub-program jumps Advanced KEEP K Old Heap Size Advanced LABELS H Label Table Advanced LIBPATH Library Path Files NOLIBRARY L Don't use Shared Library Compile LINEDEBUG Standard Line Debug Compile LINES N Add Error Line Numbers Compile MATHSTACK M Maths Stack Size Compile MINSTACK Minimum Stack Advanced OVERFLOW O Overflow Checks Compile QUIET Suppress Compiler Titles Other STACK X Stack Checks Advanced STRINGS T String Descriptors Advanced TO F Output To Files TOKENISE Tokenise Other TOKENS Token File Files UNDEFSUBS Allow undefined sub-programs Advanced UNDERLINES U Underlines in Names Compile VARCHECKS V Variable Checks Compile NOWARN W Suppress Compiler Warnings Advanced NOWINDOW Y Suppress Default Window Compile WITH Take options from file Other Appendix E The ASCII TableHere is the 8-bit ASCII representation of the Amiga character set: The most significant four bits of the ASCII representation are shown down the left side (in hexadecimal) whereas the least four significant bits are across the top so that, for example: 4C (4*16+12=76 decimal) represents L 7B (7*16+11 = 123 decimal represents { Note that the Amiga has no printable characters between values 0 and 31 (1F hex) and 128 (80 hex)& 159(9F hex). Appendix F Error Messages AmigaDOS Error Codes This section details the numeric AmigaDOS errors and their meanings. You may also use the AmigaDOS FAULT command followed by an error number to obtain the meaning. 103 insufficient free store out of memory. 105 task table full limit of 20 CLIs. 114 bad template 115 bad number 116 required argument missing 117 keyword requires argument 118 too many arguments 120 argument line invalid or too long when using CLI commands. 121 file is not an object module trying to execute non-executable file. 122 invalid resident library during load 201 no default directory 202 object in use such as a file by another program. 203 object already exists 204 directory not found 205 object not found most commonly a file. 206 invalid window in name specification. 207 object too large 208 invalid action 209 packet request type unknown 210 invalid stream component name name too long or contains control chars. 211 invalid object lock 212 object not of required type such as directory name instead of file 213 disk not validated disk is still being validated, or bad. 214 disk write-protected 215 rename across devices attempted 216 directory not empty when trying to delete it. 217 too many levels 218 device not mounted after specifying a volume name. 219 seek error 219 seek error 220 comment too big file comments must be less than 80. 221 disk full 222 file is protected from deletion 223 file is protected from writing 224 file is protected from reading 225 not a DOS disk 226 no disk in drive 232 no more entries in directory 233 object is soft linked 234 object is linked 235 bad hunk 236 not implemented 240 record not locked 241 lock collision 242 lock timeout 243 unlock failed 303 Buffer overflow in internal or user buffer. 304 break received 305 file not executable E bit is cleared. Runtime Errors A run-time error is an error produced by a running program; they are distinct from errors produced by the compiler while compiling your program which are detailed later in this Appendix. There are two types of run-time error: fatal errors, produced when something goes seriously wrong, and ordinary errors. As a substantial part of the compiler is written in HiSOFT BASIC it is possible for the compiler to generate these errors, the most common of which is Out of memory. Fatal Run-time Errors These are shown in a similar way to a Guru in a red box at the top of the screen, with these ominous words HiSOFT BASIC fatal error: <,#line> Don't panic - press left mouse button The <#line> part of the message will contain the last physical line number, if the line number option was on. Pressing the left mouse button should terminate the program. These are known as fatal errors because ON ERROR cannot trap them - the problem is considered too serious to continue running the program. Fatal errors that can occur are as follows: Cannot create HB.mainport Very unlikely, this means the program's main message port cannot be allocated, normally because memory is extremely low. Cannot open mathieeedoubbas.library This library is required for double-precision maths. Cannot open mathieeedoubtrans.library This library is required for double-precision transcendental routines, including trig functions. Memory List Corrupt Either there is a bug in the run-time system, or something has corrupted BASICs memory list. It is likely that the machine will crash shortly after you left click, if not sooner. No hbasic2.library This occurs if a shared library-type program has been run and cannot find the library file. It must be in the LIBS: directory. Stack overflow The machine stack has overflowed; see the MINSTACK option. String space corrupt Either something has corrupted the string space (i.e. the heap) or the garbage collector has failed. If this occurs in a repeatable fashion please contact us. Unexpected Exception The operating system has tried to put up a Software error - task held System Requester, but BASIC intercepts this. This can be caused by many things, but most common on a 68000 is an address error, caused by accessing odd-aligned memory (e.g. PEEKL(45)) and illegal exceptions, caused by stack overflow or memory corruption. If the line number is not a big enough clue as to the cause the debugger can be used to catch the exact cause of the exception. Non-fatal Run-time Errors Non-fatal run-time errors are reported in a System Requester, with a message, module name, line number and channel number, together with an Abort program gadget. Some fields will not appear in messages, depending on the compiler options used. These errors are listed in numeric order for easy reference when messages are not included in the compiled program and for the ERR function. Following the numeric list there is an alphabetic list with explanations as to their meaning. 3 RETURN without GOSUB 4 Out of data 5 Illegal function call 6 Overflow 7 Out of memory 9 Subscript out of range 10 Redimensioned array 11 Division by zero 13 Type mismatch 16 String formula too complex 20 RESUME without error 23 Line buffer overflow 31 Wrong number of dimensions 49 Volume not found 50 FIELD overflow 51 Internal error 52 Bad channel number 53 File not found 54 Bad file mode 55 File already open 57 Device I/O error 61 Disk full 62 Input past end 63 Bad record number 64 Bad file name 67 Too many files 68 Device function unavailable 70 Disk write protected 75 Path/file access error 76 Path not found 77 BREAK pressed 80 Array not dimensioned 81 Sub-program not present Run-time Errors Alphabetically Array not dimensioned You have used an array that has not been dimensioned. This only occurs when the Auto-DIM arrays option is disabled. In generally means that you have misspelt the array name here or have forgotten to DIMension it. Bad channel number Valid channel numbers are from 1 to 255 inclusive, plus 256 for the default printer channel that is used by LPRINT. In addition windows use channel numbers 257 upwards. Bad file mode You are trying open a channel with an invalid mode string, or trying an input/output operation on a channel that cannot support it, e.g. PRINTing to a file opened for INPUT. Bad file name The filename is invalid, either because it is too long or because it contains invalid characters. Bad record number A record number of 0 is not valid in a PUT or GET statement. BREAK pressed Ctrl-C or A-.was pressed. This error cannot be trapped by ON ERROR but can with ON BREAK - if you wish Ctrl-C to be ignored then turn the break checks option off. Device I/O error A physical error has occurred during an input/output operation or the operation cannot be performed because of lack of memory. Device unavailable You are trying an operation on a device that cannot support it, such as drawing a circle on a disk file. Disk full Disk write protected Division by zero FIELD overflow A FIELD statement has attempted to use more space than specified in the record size when OPENed, or PRINT# to a random file has filled the current record. File already open Another program has probably opened the file. File not found Illegal function call This error can be caused by a multitude of things and means a parameter was not in the range required by a function. The module name and line number can be used to track down the error. Input past end You have tried to read past the end of a file. Internal error This should never happen. It almost certainly means that your program has destroyed part of the heap or the program itself. Line buffer overflow A text line in a file is too long for the current line buffer. You can increase the size of this buffer by modifying the long word at SYSTAB+68. Out of data A READ has been attempted when no more DATA is available. Out of memory If you are using the Old Heap option this means the heap is full, which is the area of memory used for storing strings and arrays. You should use either the new heap or increase the size of the old heap. See Chapter 4: The Compiler. Overflow A result of a numeric calculation is too large to fit into the required type. This can occur when you don't expect it, for example the line test!=32767+1 will produce it, as two integers are added together using integer arithmetic. The correct result can be obtained by forcing single-precision arithmetic: test!=32767!+1 Path not found An invalid path was specified in a DOS command. Path/file access error You are not permitted to do that operation with that file, such as trying to KILL a read-only file. Redimensioned array An existing array must be ERASEd before DIMmed for a second time. Alternatively use REDIM. RESUME without error A RESUME command will only work from within an ON ERROR handler. RETURN without GOSUB A RETURN statement was executed but not from a section of the program which had been called with GOSUB. This error will only occur with the stack checks option turned on (see Chapter 4: The Compiler). String formula too complex String operations use temporary descriptors for intermediate results, and it is remotely possible to run out and produce this error. You can use the String Descriptors (STRINGS) compiler option to increase this. Sub-program not present The means that you have called an un-defined sub-program or function. Normally this is checked by the compiler so this error will only occur if you have used the Allow undefined sub-programs option (UNDEFSUBS) has been used. Subscript out of range An array subscript used is larger than that specified in the dimensioned statement, negative, or 0 if OPTION BASE 1 is used. Too many files A maximum of 255 channels may be opened at once from BASIC. Type mismatch A READ was attempted into a numeric variable but the data was found to be a string. Volume not found Wrong number of subscripts An array has been referenced with a different number of dimensions to the number last DIMmed. Unlike other compilers this is a run-time error as dynamic HiSOFT BASIC arrays can be REDIMmed with different numbers of dimensions. Compilation Errors When the integrated compiler detects an error or something that may be an error (a warning) it generates a message, like this: Where possible, the editor will load and activate the appropriate source file, ensuring that the line containing the error is on the screen. If you click on Stop (or press S) then you will be returned to the editor and you can then fix the error. Clicking on OK (or pressing O) will make the compiler continue and it may find other errors. Sometimes one error may cause the compiler to generate other, so-called knock-on errors. If you find this confusing you should always select Stop and fix your bugs one at a time. If you click on Continue to End (C), the compiler will attempt to compile the entire program without displaying any further error messages. If you have a large number of errors then you will probably get the message Too Many Errors. When you return to be editor you can use Ctrl-E (or the Next sub-item from Errors sub-menu on the Program menu) to move to the next error with the error message displayed in the window title bar. To go to a previous error use Shift-Ctrl-E (or the Next sub-item from Errors sub-menu on the Program menu). The editor takes account of any insertions or deletions automatically so that unless one error (like a mistake in a definition) has caused multiple errors you should only need to compile once. Normally the error message should be fairly obvious. The following list gives some extra hints for some of the error messages. Occasionally the compiler will spot errors somewhat later than you might expect. This is usually because the text up to the point it has read is allowed in certain contexts. If you have missed something out at the end of a line, then the error may be detected at the beginning of the next line. Note that, except in the case of missing sub-programs, line numbers or labels, the error in your program can not be after the point where the error was detected. On occasions the compiler will generate more than one error message as a result of a single error in your program; do not be put off by this. If you get confused, just re-compile. If you have a very badly formed source file, the compiler may slow down considerably. It is probably a good idea to click on the Stop button. It is possible that some error messages may have been added to the compiler; only if an error is generated without an error message is this a possible bug in the compiler. If you do get an error number without a message, please tell us. When using the compiler directly rather than from the editor, the error messages are prefaced by the error number and followed by the line and file in which the error was detected. In the case of warnings the compiler will continue automatically. After an error it will ask you if you wish to continue. If you type n or N (for no) compilation will stop; if you hit any other key compilation will continue. To avoid this prompting use the BATCH option. Compiler Error Messages In the following list many of the messages give an identifier, reserved word or symbol, this is displayed instead of the % in the message. 2 ON... should be followed by GOTO/GOSUB May occur if the expression is misformed. 3 Undefined identifier % Occurs within sub-programs and functions if the VARCHECKS option is on. See Chapter 4: The Compiler. 4 Unterminated string in data 5 Line number/label missing in GOTO/GOSUB % found instead This also occurs in ON GOTO/GOSUB/ERROR and RESUME statements if a line number or label is missing. 6 END DEF assumed 7 END SUB assumed Error messages 6 and 7 both occur if you attempt to nest sub-program or function definitions. 8 END DEF/FUNCTION where END SUB expected 9 END SUB /FUNCTION where END DEF expected Error messages 8 and 9 are both warnings. 10 Letter expected after DEFINT etc 11 Letter expected after - in DEFINT etc 13 Extra END / NEXT / LOOP This error is generated in two different contexts, either when you have too many ENDs or NEXTs or sometimes when omitting one of the operands to a dyadic operator (e.g. *) in an expression. 14 Numeric expression expected (not string) Many possible causes. 15 ) expected instead of % Many possible causes. 16 Unterminated string 17 Unexpected character in source This is a warning, the offending character will be ignored. 18 FN must be followed by a name. You can't use FN on its own as a function name. 19 Bad line number (% is not positive) Or 0 not allowed in this context. 20 Bad line number (% is too large) 21 Bad line number (% has fraction/ exponent) Or is far too large. 22 Line number % not found 23 Line number % not found 24 Parameter (%) may not be used as FOR loop identifier Use a local variable instead. 25 Name (not %) expected in parameter list Have you used a reserved word? 26 Options file % not found When using the WITH option. 27 CDECL may only be used in DECLAREd sub-programs But you have tried to use it in a SUB/FUNCTION definition. 28 ) expected at end of parameter list. % found instead Can also be caused by missing out the comma. 29 Name expected instead of % Many possible causes. 30 Statement only allowed in sub-program or function These statements are LOCAL, SHARED, STATIC, EXIT DEF/FUNCTION/SUB. 32 Label % defined twice 33 COMMON must be followed by SHARED HiSOFT BASIC does not allow any other form of COMMON statement. 34 Line number/label expected instead of % Can occur if an expression is badly formed in an ON...GOTO/GOSUB. 35 WIDTH statement badly formed HiSOFT BASIC does not support WIDTH string_expression. 37 Constant % may not be used in parameter definition. You have tried to use a constant that you've already defined as a formal parameter in a SUB, DEF FN or FUNCTION definition. Use another name either for the constant or the parameter. 38 Too many lines in program You may not have more than 16383 lines in a single program. See Chapter 6 : Concepts for other compiler limits. 39 Internal Error (bad source on pass 2) Can occasionally be generated by very badly formed source. 40 Expression mismatch Normally caused by missing operands. 41 END FUNCTION expected before here You have attempted to nest a sub-program or function definition inside a FUNCTION. 42 Expression too complex (too many operators) More than twenty operators pending. 43 Expression mismatch 44 Expression too complex More than twenty operands pending. 45 Expression syntax 46 Expression syntax Normally caused by missing out an entire expression. 47 FUNCTION or SUB expected after DECLARE 48 FUNCTION or SUB declared but not present You have used a DECLARE statement for this function but not actually defined with the corresponding SUB or DECLARE statement. If you think you have, check the spellings carefully. 49 SUB name % used in expression 50 Expression mismatch: % is not a unary operator 51 Expression mismatch: No unary string minus 52 Expression mismatch 53 Illegal type combination Two strings used with arithmetic operators other than +. 54 Illegal type combination (not string) A string expression and a numeric expression have been used with an operator. 55 Parameter % appears twice 56 Illegal type combination (not string) String could not be coerced to numeric type. 57 % is not a variable or the current function Using other function names is not allowed on the left hand side of assignments. 58 Variable is wrong type For example, if you pass a double array instead of an integer array to a sub-program. 59 Open bracket expected instead of % Many possible causes. 60 Comma expected instead of % Many possible causes. Could be that an expression is mis-typed. 61 Semi-colon expected instead of % Many possible causes. 62 Extra characters at end of statement % is first Perhaps you didn't expect the statement to be over so soon. Check your expressions. 63 END DEF assumed at the end of program 64 END SUB assumed at the end of program 65 END DEF / SUB where END FUNCTION expected This is a warning. 67 Bad option specified 68 ( expected in CALL statement instead of % When using the CALL statement for a sub-program with parameters, you must follow the sub-program name with an open parenthesis. 69 Subroutine % not found To CALL a variable use CALL LOC. 70 Can only disable reserved words from within a program or pre-tok file You can't use the DISABLE option on the command line. 71 DECLARE..LIBRARY must be after LIBRARY statement Move this statement to after the corresponding LIBRARY or LIBRARY DECLARE statement. 72 = expected instead of % Many possible causes. 73 LIBRARY routine % mis-used The library routine has been used as a function when it is a sub-program or vice versa. 74 Unknown meta-command % This error means that you have used a meta-command (after rem $) that is not supported by HiSOFT BASIC. If you are writing a new program check that you have spelt it correctly; if you are porting a program from another compiler, check to find out what it does! 75 Structure table full The internal table used by the compiler to store the details of parameter lists, SHARED and local variables is full. If you are importing a lot of global variables many times, make them DIM SHARED. 76 LIBRARY expected instead of % This sub-program/function is part of a library so you must declare it as a library sub-program/function. 77 Tokens file too old The pre-tokenised .T file that you are using was compiled with an older version of the compiler. Re-make the .T file with this compiler. 78 FOR variables must be simple variables (not % which is an array) 79 FOR variable % can't be a string 80 TO not % expected in FOR statement Is your initial assignment to the FOR variable correct? 81 Tokens file too new The pre-tokenised .T file that you are using was compiled with a newer version of the compiler. Re-make the .T file with this compiler. Why are using an old version of the compiler? 82 Tokens file corrupt 83 BASE not % expected after OPTION 84 OPTION BASE must be followed by the number 0 or 1 not % 85 Tokens file % not found 86 Cannot delete % as a reserved word As it isn't a reserved word. 88 % cannot start a statement 89 Extra ELSE 90 ELSEIF must be followed by THEN not % 91 % not allowed after END 92 Mismatched NEXT should be % 93 END IF expected before here 94 END REPEAT expected before here 95 NEXT expected before here 96 END SELECT expected before here 97 WEND expected before here 98 LOOP/WEND expected before here Errors 93 to 98 may occur if you have omitted the start of the structured statement in the error line. 99 Name required after SUB or DEF. % found instead Is it a reserved word? See Appendix C. 100 Identifier % redefined In sub-program or function definition. 101 Option value too large 102 Name expected after LET (not %) 103 GOTO, THEN or end of line expected after IF expression not % 105 Unexpected END SUB or END DEF or END FUNCTION Occurs when not in a function or sub-program definition. 106 CALL missing at start of statement This is a warning. For more information see Chapter 6: Concepts. 107 Unterminated control constructs Occurs at the end of sub-programs, user-defined functions and sub-programs. 108 Function or sub-program redefined in LIBRARY % This is a warning. You probably have two libraries that have functions with the same name; the Extend library provides access to some of the system libraries for example. 109 Unknown REPEAT loop in EXIT 111 Semi-colon or comma expected Many possible causes. 112 REDIM PRESERVE of arrays of more than one dimension not allowed 113 AS or , expected instead of % in OPEN statement Occurs in OPEN, NAME and FIELD statements. Perhaps an expression is wrong. 114 CONSTants must be integers not % 115 CONST % can not be assigned to 116 - expected instead of % in graphics statement. Co-ordinates are specified as (x1,x2)-(y1,y2). 118 % is not a label Your source is probably severely malformed. 119 ( expected instead of % in graphics GET or PUT 120 Array expected but ordinary variable % found 121 Argument to VARPTRS must be a subroutine name not % 122 Too many LIBRARY statements 123 INCLUDE file % not found 124 LIBRARY % not opened You have used the LIBRARY function on a library that you haven't use LIBRARY or LIBRARY DECLARE for. Perhaps you have misspelt the library name either here or where it is declared. 125 Value parameter must not be array 127 Library /ALIAS must be string literal not % Have you remembered the quotation marks? 128 Cannot open library % 129 Library % badly formed The .bmap file is probably corrupt. 130 Too many parameters in statement 131 Sub-program % not found To CALL a variable use CALL LOC. 132 GOTO expected after ON ERROR not % 134 SELECT variable must only be a simple variable not % 135 LOOP/WEND expected before here 137 ON/OFF expected not % This will be given for badly formed COLLISION, CLOSE, MENU, MOUSE, TIMER, BREAK and $REM EVENT statement. Note that STOP may also be used in all but $REM EVENT and that MENU RESET is also allowed. 150 Branch too far You probably have a FOR or SELECT CASE statement with more than 32K of code. 151 Label table full Use the Label Table item in the Advanced Options requester (or use the LABELS option from the command line). The default is 3000. 153 Invalid library The compiler's executable file in memory is corrupt. 154 Cannot create output file % Perhaps because of an invalid path or full disk. 155 Disk Full 156 Not enough memory for program's code. 157 Internal error EOF 158 Internal error BADRT 159 Internal error BADMOD 162 Overflow When the code generator is optimising code. 163 Internal bad type 164 Internal bad pseudocode size 165 Internal unbalanced stack 166 Internal label not found 167 Internal bad opcode 168 Internal double definition 169 Internal phasing error 170 Internal stack underflow 171 Internal precheck error 172 Internal missing VOM 173 Internal phasing error These internal errors should not occur under normal circumstances - try again after re-booting your machine in case the compiler has been corrupted in memory. If this still occurs re-install the compiler from your master disk. If the problem persists please send us the smallest program that will show the problem. Appendix G Linking with C and Assembler This Appendix is intended for assembly-language and C programmers and details linkage with these languages, together with the memory maps and register usage of compiled programs. It is also for users with some knowledge of assembly language who wish to use the debugger. Code Generation A BASIC source program is converted into true machine-code, there are no P-codes or interpretative run-times. The code produced distinguishes between the program area and the data area. The program area is what is written to the disk or to memory and is position dependent code, relocated either by the AmigaDOS loader in the case of disk files or the code generator itself with programs compiled directly to memory. All program code executes in user mode and is compatible with 68010, 68020, 68030 and 68040 processors. Figure F-1 shows the overall memory map of a compiled program. Note that the heap and the machine stack are not shown here. Register Usage Several registers are committed to special purposes within a compiled program. These are: A3 - Library Pointer In order to minimise the space and time taken for run-time library calls, register A3 is dedicated to point to either a run-time jump block (if using the shared library( or to the run-time library code hunk itself, with a $8000 offset to allow a maximum of 64k for the whole library. Library calls from within the compiled code are of the form JSR -offset(A3) Library calls from within the library itself do not use A3, they use BSR statements and are resolved by the code generator during compilation. A4 - Local Variable Stack Frame At the very beginning of functions and sub programs a LINK instruction is done to allocate space on the stack for local variables (and function results) and to establish a register that can be used for accessing parameters. Only space for numeric variables are immediately allocated using LINK; arrays and string descriptors are allocated afterwards using a library call. For example a sub-program which has one local integer variable starts with the instruction LINK #-2,A4 Functions and sub programs finish with a corresponding UNLK A4 RTS A5 - Data Area Pointer The startup code of a compiled program sets up A5 to point to the data area of the program which of course is always RAM. At the start of the area are the run-time globals, followed by the descriptor table (descriptors are described later). Next is the global variable area, used for storing numeric variables. There is a 32k limit on the total size of these globals, but is would take a massive unstructured BASIC program to require such a number of globals. The static arrays follow this; there is no 32K limit on these, but those within this array are accessed more quickly. A6 - Maths Stack This is a special stack used for storing intermediate results of numeric calculations. A7 - Machine Stack The regular machine stack used for return addresses and local variables (using A4). It is left at the place provided by the calling program unless the stack is not as large as the MINSTACK option value when it will be allocated its own memory. D7- Top of Stack This register is used to hold the current value from an intermediate expression, be it a single precision numeric value (in the ST version), a long or short integer. For strings D7 is used to hold a pointer to the descriptor for that string. D6 - Top of Stack Extension This register is used in conjunction with D7 to hold long results of type double on the ST version. Code Hunk 1 Compiled Program Code Hunk 2 or hbasic2.library Run-time Library Global Area A5 Run-time Globals Descriptor Table Global Variables Static Arrays Maths Stack The Heap and Descriptors Crucial to the operation of HiSOFT BASIC compiled programs is the area of memory known as the heap. BASIC is one of two common languages (the other is LISP) that requires dynamic garbage collection. Owing to the way strings in the language work it is necessary to allocate memory for them as required, then, when it runs out, to re-use all the memory no longer needed. This re-allocation is known as garbage collection. Many compilers and even some interpreters do not garbage collect and, as a result, certain operations can cause out-of-memory errors even though there is a lot of unused memory left. HiSOFT BASIC has a very advanced memory management system (which is hidden from the user normally) whereby any memory allocation request can cause a garbage collect to occur in order to satisfy the request. There are two schemes, the old heap (KEEP) option and the new dynamic heap option. With the Old Heap, the heap itself is a single large block of memory from which allocations for string variables and arrays take their memory. At the bottom of the heap (low memory) are all the string variables, while at the top are all the arrays. Strings work their way upwards, while arrays grow downwards. Should they ever meet, a garbage collect occurs which deletes all unused strings and moves existing ones around as required. It is important to note that arrays never move in memory as a result of a garbage collect; a dynamic array can only move when you REDIM or ERASE any other array; static arrays don't move at all. With the new dynamic heap, arrays are stored in their own areas of memory. Large dynamic arrays have their memory individually allocated from the operating system and small dynamic array allocations are pooled together. Initially strings are allocated on a heap like the one used by the Old Heap scheme but if this fills up further mini-heaps may be allocated. As items on the heap are liable, without warning, to move about, ordinary pointers are useless. For this reason strings and arrays are accessed via descriptors, which exist normally in the global area and which themselves contain actual pointers to the data on the heap. As the memory manager knows where all the descriptors are it can update their pointers when a garbage collect occurs. Incidentally, the garbage collector itself is very fast; for example it can compact around 350k of fragmented heap in under 2 seconds on a standard 8MHz 68000, so there is never any noticeable delay in the running of a program should it have to garbage collect. Memory Formats Single-precision Floating Point These use the Motorola Fast Floating Point (FFP) format. The format is unusual by most standards, but was designed solely with the 68000 architecture in mind, and is as a result very fast. It is the same format as used by ST BASIC, so random access files created with the interpreter should be directly usable within the compiler. Single Precision The sign bit is 0 for positive numbers and 1 for negative numbers. The mantissa has an implied binary point at bit 32 and thus ranges in value from 0.5 to <1.0. The exponent is held in excess -64. The number zero is represented with 32 bits of zero. Double-precision Floating Point These use the IEEE format double-precision floats, each occupying 8 bytes, i.e. two longs. Double Precision Format The sign bit is 0 for positive numbers and 1 for negative numbers. The mantissa has an assumed bit of 1; if present it would be at bit 52. The exponent is held in excess-1023. The number zero is represented with 64 bits of zero. Linkable code Although this version of BASIC has many powerful features and extensions, occasionally there is a command or function that is not part of standard BASIC. Additionally, a specific task can be very time critical and need all the speed it can get. For these reasons, HiSOFT BASIC has the ability to call C or assembly language subroutines. BASIC has a much more complex environment and initialisation procedure than C, so it is only possible for a BASIC program to call C functions; it is not possible for C programs to call BASIC code. In addition there are certain conventions which make this process more complex, so calling assembly-language code allows much more flexibility. External Definition In order to call C or assembly-language the compiler allows a program to use a special sort of DECLARE statement to indicate that a function or sub-program is written in C or assembler. Using this will automatically cause the compiler to produce linkable (rather than executable) code. If you haven't used the Output to (TO) compiler option, the name of the output file with have .o added to it (minus the .bas extension). The DECLARE...CDECL statement The special form of the DECLARE statement is as follows: DECLARE {SUB|FUNCTION} subname CDECL [ALIAS "externalname"] [(param_list)] The ALIAS clause is optional. The string following indicates the exact external name for the function. If an ALIAS clause is not specified the name (without any type specifier) is made lower-case and an under-score (_) character inserted at the front. This is suitable for linking with SAS/C compilers. Thus a function called cname% or a sub-program called CNAME will both use the name _cname, if there is no ALIAS clause. The parameter list is like that of a BASIC sub-program or function. That is, it specifies the types of the parameters, how many parameters there are, and whether the parameters are passed by value or reference. Normally the BYVAL keyword should be used to indicate that the parameter is passed by value (or VAL for compatibility with HiSOFT BASIC 1). It is possible that the name of your external routine will clash with a symbol in the BASIC run-time system. None of the BASIC routines start with an underscore character so we recommend their use on your external names to avoid possible clashes. The use of such a DECLARE statement will automatically produce linkable code without the need for a compiler option. Compiling a linkable program to memory will give an error message Calling C Functions C and assembler functions are called in a very similar way to the way standard BASIC sub-programs are called. If you are using C, call the function or sub-program in the same way as you would in C. Make sure that the types of the parameters in the BASIC DECLARE statement match the sizes of the parameters in the C code (taking particular care with integer sizes). The parameters should be in the same order in both languages. If a parameter is a pointer and you normally use the C & operator when calling the function, omit the BYVAL keyword in the parameter list. The address of the BASIC variable will then be passed to the C code. Calling Assembly Language Functions For assembly language, any parameters are coerced to the appropriate type and pushed on the machine stack in reverse order (i.e. C order). Registers A3-A6 must be preserved and any return value should be in D0 (or D0 and D1 if a double, D0=high longword). A string return value should be in D0 and be a pointer to a null-terminated string. You will need to ensure that your routine Ôlooks like' a C function. This involves reading parameters from the stack and using an RTS to return. You must leave the parameters on the stack. The code should be assembled to linkable code and the necessary routines exported using XDEF. We recommend that you use the ALIAS facility in the DECLARE statement; otherwise you must use case sensitive code and ensure that the names you export are lower case and start with an underscore. Parameters If numeric parameters are passed by value then their value (16-, 32- or 64-bits) is pushed on the stack. Double-precision parameters are passed in HiSOFT BASIC 2 order as required by SAS/C; not in the same order as when using the BASIC library. If variable parameters are passed then the address of the variable is pushed. Strings and arrays are passed as the address of their descriptor. The descriptor format is private and subject to change so utility routines are provided to convert them into a more useful form. Linking You should end up with a linkable file from the BASIC compiler and a linkable file from the C compiler or assembler. They should be linked together using an Amiga format linker such as Slink, Blink or even Alink. You may also need to specify C compiler libraries if your C functions have referred to any. With SAS/C 6 you should use the compiler options: nosdata noscode nostkchk parameters=stack which forces 32-bit variable references, 32-bit code and disables stack checking, and ensures that parameters are passed on the stack. If when you link there are undefined symbols this normally means your C is calling on a library routine. You will then have to specify the required C library when you link again, but take care that the library code does not assume any register values (e.g. for base-relative globals) or initialisation code (e.g. the Unix file system). C-callable Utility Routines All utility routines may be called from assembly-language but only a few may be called from C, due to register requirements. The C-callable routines can be found in the file hbcutil.o on disk 2 which should be linked with your other code. You must generate stand-alone code to be able to use these routines. long getbasicstr(d,&length) long d; long length; This should be passed a string descriptor address and the address of where the length should be stored (note that strings may be >64k). The return result is the address of the string which will not be null-terminated and you are not allowed to write to the string area. long getbasicarray(d,dims,&length) long d; short dims; long length; This should be passed an array descriptor, the expected number of dimensions and the address of where the length should be stored. The return result is the address of the start of the array contents, guaranteed to be even. The length will be the total length in bytes taken up by the array elements. You are allowed to write to the array area. Assembler utility routines The file hbasm.i in the linking directory contains various definitions for use by code called from BASIC. Your code has to decide whether it is being used by a stand-alone program or a shared-library program; if it is the latter than the symbol HBLIB should be defined before INCLUDEing hbasm.i. Most BASIC runtimes need register A5; this is why C code cannot call them. If using a shared-library program then A3 is also required. The macro CALLBAS is provided to call a BASIC runtime. Available routines are as follows: get_array takes: A0 the array descriptor D0.W the number of dimensions the passed array should have returns: A2 the address of the first element in the array D4.L the total length in bytes taken up by the array elements registers used: D0,D4, A1,A2 get_string takes: A0 the string descriptor returns: A1 the address of the string D4.L the length of the string registers used: A0,A1,D4 make_string takes: A0 the string descriptor of a string-variable; the descriptor of a string value will have no effect if passed to make_string A1 the address of your copy of the string D4.L the length of the string to be created registers used: D0-D4, A0-A2 This call allows a string parameter passed by variable to be safely modified by the caller. A value string parameter passed to make_string will have no effect. safe_malloc takes: D0.L bytes required D1.L type of memory (cf. AllocMem) returns A0 allocated area registers used: D0/D1/A1 This is a safe way to allocate any type of memory and chain it to BASICs memory list, so it will be de-allocated on program termination (if not already de-allocated). safe_free takes: A0 result from safe_malloc registers used: D0-D1/A0-A1 Re-Entrant Code If you wish a compiled program to remain Pure (in the AmigaDOS sense) then it is your responsibility for your external routines to follow the necessary rules. We've done our bit... Accessing BASIC global variables from assembly Using the Export Variables names option from the Advanced Options requester (or via the EXPORTS option) the names of your global variables will be exported as absolute symbols so that you can access them via the global register. As the BASIC variable terminators (%&!#$) are not allowed as parts of normal assembly language names, the terminators are changed to I, L, F, D and S respectively. The names are prefixed with _ for normal variable and @ for arrays. The variable names are forced to upper case. Conversely sub-program and function names are forced to lower case. Here are some BASIC names are the corresponding name to use in assembly language: i% _II fred& _FREDL mary! _MARYF john%() @JOHNI MARY!() @MARYF Linked Examples Here is an artificially simple example of the process, starting with the BASIC program which uses an external function to compare two short integers: DECLARE FUNCTION cequal% CDECL (BYVAL p1%,BYVAL p2%) PRINT cequal%(1,2),cequal%(10,10) Now the C function: short cequal(a,b) short a,b { return (a==b) } and the equivalent (Devpac) assembly-language: opt l+ xdef _cequal _cequal move.w 4(sp),d0 cmp.w 6(sp),d0 seq d0 ext.w d0 rts Appendix H Technical Support HiSOFT BASIC 2 comes with 30 days free technical support, starting from the date of registration; therefore you should send in your registration card quickly. Technical support is available by telephone during our Technical Support Hour, by letter or by fax. Should you wish to receive extended technical support, please complete the relevant sections on the registration card, indicating whether you would like to take up the Silver or the Gold service. In addition to your name, address and postcode (very important for UK customers), we need payment details before we can accept your extended registration. You can pay by credit card (Mastercard, Eurocard, Access, Visa etc.), UK debit card (Switch, Connect etc.), Eurocheque, UK cheque or Postal Order. You may have already registered another HiSOFT product under our Gold or Silver service; in this case, there is no need to fill out the payment section. Appendix I New Features Here is a list of most of the features of HiSOFT BASIC 2 that are additional to our Power BASIC and HiSOFT BASIC 1. Existing programmers may well find this list useful in making the most out of the package. * New, multi-window editor with Workbench 2 and 3 support, bookmarks, mouse block-marking, macros and flexible user configuration options. * Standard Compilation up to 50% faster; pre-tokenised files make development even faster. * Faster and more compact code. * New Multi-tasking friendly dynamic heap option - if your program is only using a little RAM it'll only use a little but it can expand to use more if needed. * .bmap files are supplied for version 3.1 of the Operating System so you can access new features of the OS. These are backward compatible with older machines. * .bh and .bc files are supplied so you don't need to look up constants and structure offsets in the the ROM Kernel Manuals. Again these cover the new version 3.1 features. * Medium level debugger with the ability to view BASIC source code and use line numbers in debugging. * STATIC arrays are now supported for faster array accesses. * SCREEN and PALETTE statements support the AGA chipset. * The running program can automatically warn you if you auto-dimension an array. * Named compiler options rather than cryptic letters * Compiler and Debugger Ôunderstand' about include files so that, for example, run-time error messages tell you in which file the error occurred. * Support for multiple serial ports and better control for hardware handshaking etc. * << and >> are unsigned shift operators which operate on both integers and longs (between addition and comparison in priority). * Long integer CONSTants. * IS is allowed in SELECT CASE for compatibility with Microsoft BASIC. * REDIM PRESERVE is a synonym for REDIM APPEND as per Microsoft 7.1. * RINSTR searches backwards in strings. * Options to search paths for include and .bmap files. * Option to read options from a file. * You can now access BASIC global variables directly from your linked assembly language. * The compiler can remove inter-sub program jumps giving more compact programs. * Reserved words may be disabled make it easier to quickly port programs from other systems and to help check that code is portable. * Option to suppress compiler output apart from error messages * CURDIR$ returns the current directory * BLOAD and BSAVE can now be used to channels. * PEEK$ converts C-strings to BASIC strings. * FORMATx$ for the flexibility of PRINT USING but to a string rather than directly to a channel. * FREEFILE for writing file handling sub-programs that you can slot in anywhere. * LTRIM$ and RTRIM$ for trimming spaces from strings. * MIN and MAX functions * ON...CLOSE to take control when a user closes a window, * TAGLIST statement to make calling the new operating system features easy. * Improved control over opening, closing of libraries. Devices, resources etc. may now be called direct from BASIC. * BEGINIO routine to make possible to start * Amiga.lib functions supplied. * System and compiled code works on all processors from 68000 to 68040. * Programs compatible with all versions of the operating system from Workbench 1.3 to Workbench 3.1. Some new facilities are restricted under Workbench 1.3. Appendix J Bibliography This bibliography contains our suggestions for further reading on the subject of the Amiga's operating system, the BASIC language and programming in general. As with all reference books there is no substitute for looking at the books in a good bookshop before making a decision. We can supply a number of the books listed, especially the AmigaDOS titles. The BASIC books that we recommend here are based around the AmigaBASIC interpreter so that although they are a little out of date and do not take advantage of the new features of HiSOFT BASIC they do give a good description of the built-in Amiga commands. Books on QuickBASIC and QBASIC for the PC can be of more help with the BASIC language in general. BASIC AmigaBASIC Inside and Out RŸgheimer, Spanik [1988] ISBN 0-916439-87-9, Abacus, Inc Advanced AmigaBASIC Tom R. Halfhill and Charles Brannon [1986] ISBN 0-87455-045-9, Compute Publications, Inc Amiga The AmigaDOS Manual, 3rd Edition Bantam Books [1991] ISBN 0-553-35403-5, Bantam Books, London. Amiga User Interface Style Guide Commodore-Amiga, Inc. [1991] ISBN 0-201-57757-7, Addison-Wesley Publishing Company, Inc. Amiga ROM Kernel Reference Manual: Includes & Autodocs, 3rd Edition Commodore-Amiga, Inc. [1991] ISBN 0-201-56773-3, Addison-Wesley Publishing Company, Inc. Amiga ROM Kernel Reference Manual: Libraries, 3rd Edition Commodore-Amiga, Inc. [1991] ISBN 0-201-56774-1, Addison-Wesley Publishing Company, Inc. Amiga ROM Kernel Reference Manual: Devices, 3rd Edition Commodore-Amiga, Inc. [1991] ISBN 0-201-56775-X, Addison-Wesley Publishing Company, Inc. Amiga Hardware Reference Manual, 3rd Edition Commodore-Amiga, Inc. [1991] ISBN 0-201-56776-8, Addison-Wesley Publishing Company, Inc. Native Developer Update Kit Commodore-Amiga, Inc. [1993] Not a book, but rather a set of disks. This contains the only documentation on programming the new Workbench 3.0 and 3.1 that was available to the general public at the time of writing. A must if you want to take full advantage of the new OS features. Algorithms & Data Structures Algorithms Sedgewick, Robert [1988] ISBN 0-201-06673-4, Addison-Wesley Publishing Company, Reading, MA, USA. Compilers: Principles, Techniques and Tools Aho, Alfred V, Ravi Sethi and Jeffrey D. Ullman [1986] ISBN 0-201-10194-7, Addison-Wesley Publishing Company, Reading, MA, USA. Data Structures and Algorithms Aho, Alfred V, John E. Hopcroft and Jeffrey D. Ullman [1983] ISBN 0-201-00023-7, Addison-Wesley Publishing Company, Reading, MA, USA. Fundamental Algorithms Knuth, Donald E. [1973] ISBN 0-201-03809-9, Addison-Wesley Publishing Company, Reading, MA, USA. Seminumerical Algorithms Knuth, Donald E. [1981] ISBN 0-201-03822-9, Addison-Wesley Publishing Company, Reading, MA, USA. Sorting and Searching Knuth, Donald E. [1973] ISBN 0-201-03803-X, Addison-Wesley Publishing Company, Reading, MA, USA.