T H E P R O T O N P R O G R A M M I N G L A N G U A G E R E F E R E N C E M A N U A L Written by Brian Campbell Proton Programming Language Reference Manual For Apple II Computer Systems Apple, Apple IIGS, and ProDOS are registered trademarks of Apple Computer, Inc. Copyright 1993 Brian D. Campbell. All rights reserved. No part of this manual may be reproduced, transmitted, or stored in a data retrieval system in any form or by any means, electronic, mechanical, or otherwise, including photocopying or recording without the written permission of Brian D. Campbell. Printed in the United States of America. Page - 2 Proton Programming Language Reference Manual Table of Contents Chapter 1: A Description of the Proton Programming Language General Overview Data Declarations Subroutines and Function Declarations Executable Statements Expressions Chapter 2: Description of Predefined Operations Overview of Argument Types Arithmetic Operations for Regular Signed Numbers Relational and Logical Operaters Operations for Unsigned Numbers Input Operations Output Operations Memory Access Operations Screen Control Operations Miscellaneous Operations ProDOS MLI Operations Chapter 3: Description of Errors Compilation Errors Run Time Errors ProDOS Errors Chapter 4: Summary of the Proton Language Page - 3 Proton Programming Language Reference Manual Chapter 1: A DESCRIPTION OF THE PROTON PROGRAMMING LANGUAGE GENERAL OVERVIEW A Proton program is made up of Proton statements. Each statement starts with a key word, is sometimes followed by one or more arguments, and is always terminated by a carriage return. A Proton program always begins with a START statement and ends with a STOP statement. Thus, the simplest Proton program is: START STOP It does nothing. But to do something useful, you put one or more statements between START and STOP. For example, the statement OUTSTR prints out a string of text, and OUTCHAR 13 prints out a carriage return. So a program that prints: Hello, Everybody. Looks like: START OUTSTR "Hello, Everybody." OUTCHAR 13 STOP Before the START statement, you can insert a variety of Data Declaration statements, Subroutine Definitions, and Function Definitions. These can occur in any order. Data Declarations are used to declare constants, variables and arrays; they must be declared before they can be used between START and STOP, or in subroutines, or in functions. But no matter how many statements occur before a START statement, a program always starts running at START. Executable statements are statements that do something, like OUTSTR which outputs a string of characters to the screen, or a file. These occur between START and STOP, and inside subroutine and function definitions. Statement key words, and user defined identifiers, are not case sensitive. That is, you can capitalize them or not, as you wish. For example, START, start, Start, and StArT are all the same statement. The only time capitalization matters is in a quoted string, as in the above OUTSTR argument. When a statement has more than one argument, separate them with commas. You can use spaces (blanks) freely between statement key words, identifiers, and other symbols -- one space, two spaces, or as many as you like; or none at all, as long as you don't run identifiers and key words together. Page - 4 Proton Programming Language Reference Manual You can place a comment wherever you can put a space. Comments are delimited by curly braces, that is, they begin with { and end with }. Between the braces you may enter any descriptive text you want. In fact, comments are like spaces; they are totally ignored and have no effect when your program is run. This example is equivalent to the one above: START {The program starts running here} OUTSTR {output a string} "Hello, Everybody." OUTCHAR {output a character} 13 {ASCII code for a carriage return} STOP {the buck, ahem, program stops here} Suppose you have statement that won't fit on one line? Break the statement on to two or more lines, but break them where ever a space can be used, and put each carriage return in a comment. In other words, at every break, put a { (left brace) at the end the line, and a } (right brace) at the start of the next. Comment text, including blanks, may appear between the braces. Example: SET REFUND, WITHHELD - ((INCOME - DEDUCTIONS) * { } TAX.RATE) + TAX.CREDITS Strings of characters are allowed in several contexts, like on OUTSTR. They start with " and end with ". For example: OUTSTR "Enter a number from 1 to 10:" What if you want " inside the string? Use \34\ or \$22\ in the string. For example: OUTSTR "She said, \34\Double 'em up!\34\\13\" Prints the following with a carriage return: She said, "Double 'em up!" You can represent any character in a string by putting its ASCII code (in decimal or hex form) in between back slashes. For example, to enter back slashes themselves, us \92\ or \$5C\; to enter a carriage return, use \13\ or \$D\. You need not have your entire program in one text file. You can put portions of your program in one or more other files. In your main program file, where ever a portion would go, put INCLUDE pathname where pathname is the name of the file that has that portion. The compiler will compile the statements in pathname's file, just as though they were inserted in the main program file. The pathname is restricted to 32 characters. Included files can also have INCLUDE statements too, but not more than about three levels deep. DATA DECLARATIONS A data declaration is any one of the following statements: Page - 5 Proton Programming Language Reference Manual CONSTANT identifier constant INTEGER identifier ARRAY INTEGER identifier constant ARRAY BYTE identifier constant DATA ADDRESS identifier DATA BYTE constant In the above, an identifier is a name that you invent. It must start with a letter, and can be followed by letters, numbers, and periods. An identifier can be as short as one character or as long as 32 characters. A constant is a simple number such as 1, 100, 1492, or negative numbers such as -1 or -33. A constant can be the ASCII code of a character by preceding the character with an apostrophe. For example, the ASCII code of the letter P can be denoted as 'P. And for you advanced programmers, it can even be a hexadecimal number such as $A9, $C000, or $3F0. CONSTANT defines identifiers that have constant values, that is, values that do not change during the execution of a program. It essentially allows you to substitute names for numbers. For example, if you use the same number lots of times in program, you only have to define it once, and then you can use the identifier throughout your program. That way, if you need to change the number in a future version of your program, you only need change it in one place in your program rather than in many places. Examples: CONSTANT MAX.X 279 CONSTANT MY.BALANCE -100 CONSTANT KEY.PRESS.ADDRESS $C000 INTEGER defines identifiers that are variables, that is, they have values that might change one or more times in the program. An integer can hold a value from -32768 to 32767. Use the SET statement to give a variable a value in the executable portion of your program. Example: INTEGER X START SET X,100 STOP ARRAY BYTE and ARRAY INTEGER defines array variables. An array is a variable that can take on many values at once. How may values? As much as the constant value plus one. For example: ARRAY INTEGER A 10 This defines A to be an array that has 11 elements, that is, it can store 11 different values. You use an index in brackets to differentiate the elements. For example, in Page - 6 Proton Programming Language Reference Manual your program, A[0] refers to the first one, A[1] refers the second one, and so on, and A[10] refers to the last one. The constant 10 refers to the largest index that can be used. The only difference between ARRAY BYTE and ARRAY INTEGER is the size of the value that can be stored. In an integer array, each element can store a value from -32768 to 32767. In a byte array, each element can store a value from 0 to 255. If your array need only store small numbers, use byte arrays; they use half as much of computer memory. A byte array that has a maximum index of 255 or less, can, in some contexts, be used as a string of characters. The term "string variable" will refer to such arrays. The element with index 0 contains the length of the string, the element with index 1 has the first character, the element with index 2 has the second character, and so forth. Some pre-defined subroutines described in a later section have strings as arguments. Either literal strings (bounded by ") or byte arrays can be used in such contexts. IIGS Tool Box programmers: Proton strings have the same format as "Pascal strings". You can define more than one identifier on any of the above data declaration statements. Just list the definitions with commas in between. For example: CONSTANT MAX.X 279 CONSTANT MAX.Y 191 Can be written as: CONSTANT MAX.X 279, MAX.Y 191 These are also valid statements: INTEGER X, Y, SUM, TOTAL ARRAY BYTE VOLUME 15, PATHNAME 63, PREFIX 63 The statements DATA ADDRESS, DATA INTEGER, and DATA BYTE are intended for advanced programmers and are intended to be used in combination. DATA ADDRESS is like CONSTANT, except that the identifier takes the value of a memory address -- the address of the DATA that follows. DATA INTEGER puts one or more integer (two-byte) values in memory. DATA BYTE puts one or more single byte values directly in memory. The PEEKW or PEEK function can be used to retrieve these values. A DATA INTEGER or DATA BYTE statement allows any combination of constants and strings separated by commas. A string is equivalent to having each character listed as a separate constant, preceded by an additional constant which is the length of the string. Example: DATA ADDRESS LIST DATA BYTE 1,10,100 DATA BYTE 'A,'B,'C,"XYZ",'E {same as 'A,'B,'C,3,'X,'Y,'Z,'E} With the above statements, then: OUTCHAR PEEK[LIST+3] Page - 7 Proton Programming Language Reference Manual {1,1,100 are at offsets 0,1,2; 'A is next} OUTCHAR PEEK[LIST+7] {3 is at offset 6; 'X is next} OUTCHAR PEEK[LIST+6 + PEEK[LIST+6] + 1] {skip over "XYZ" to get 'E} Prints: AXE Warning: the built in function UPLUS is recommended over the use of "+" when adding values to memory addresses such as the identifier LIST above. The following avoids overflow errors if LIST is near the address $8000: OUTCHAR PEEK[UPLUS[LIST,3]] {Prints 'A} SUBROUTINE AND FUNCTION DEFINITIONS The SUBR statement allows you define a subroutine. Subroutines are often used to encapsulate portions of a large program into manageable pieces. This strategy is based on the old adage "Divide and Conquer". Subroutines are also used to define recurring or repetitive portions of one's program; that is, you define the portion once in a subroutine, then refer to the subroutine as often as you need throughout the program. Everything between the SUBR statement and it's RETURN statement is part of the subroutine definition. A subroutine definition has the following structure: SUBR identifier ARG type identifier executable statements RETURN The SUBR identifier can be used (i.e. called) among other executable statements, that is, between START and STOP, or in other subroutine or function definitions. Where ever it is called, the program flow is momentarily interrupted to execute the statements in the subroutine. The arguments on the calling statement are passed and substitute for the identifiers listed in the ARG statements, in the same order that they are listed. After the subroutine statements are executed, control returns back to the statement following the original call. The ARG statements define how many arguments you want to pass to the subroutine when it is used. They define the type of each argument, and how the argument will be referred in the subroutine's executable statements. The ARG statement can be repeated as often as needed, one each for each subroutine argument. Omit the ARG statements if the subroutine is to have no arguments. All ARG statements must occur before any other definition statements or executable Page - 8 Proton Programming Language Reference Manual statements. The argument type can either be EXPR, or one of the variable types INTEGER, ARRAY INTEGER, or ARRAY BYTE. If you have more than one consecutive ARG with the same type, you can combine the identifiers in one statement, such as: ARG EXPR X,Y,COLOR Consider the following simple definition for a subroutine called ADD.TO: SUBR ADD.TO ARG INTEGER X ARG EXPR A SET X,X+A RETURN It has two arguments and one executable statement (not counting RETURN). If you added this to your program, you would have a new executable statement at your disposal. This example adds the second argument to the first. Calling examples: ADD.TO B, 1 ADD.TO V, Z * 2 + 10 In the first example, 1 gets added to B. In the subroutine, B takes the place of X, and 1 takes the place of A. It performs the equivalent operation SET B,B+1. The second example illustrates the key difference between ARG INTEGER and ARG EXPR. An argument that takes the place of an ARG INTEGER identifier must be an integer variable, no more, no less. Any operations that take place to the ARG identifier (like X above), even a SET, actually take place to the integer variable passed in (like B or V above). An argument for an ARG EXPR identifier (like A above) can be any arbitrary numeric expression, such as 1 or Z*2+10. However an ARG EXPR identifier can not be modified (with SET, for example). Should you define an argument to be ARG INTEGER or ARG EXPR? If you want your subroutine to change the value of a variable, pass the variable to the subroutine, and define it's ARG statement to be ARG INTEGER. If you want the flexibility to pass any arbitrary numeric expression as an argument, define it's ARG statement to be ARG EXPR. Use ARG ARRAY INTEGER or ARG ARRAY BYTE when you want to the argument to take the place of an ARRAY. For example, with: Page - 9 Proton Programming Language Reference Manual SUBR ADD.IT ARG ARRAY INTEGER A ARG EXPR INDEX,VALUE SET A[INDEX],A[INDEX]+VALUE RETURN Causes this statement: ADD.IT LIST,3,89 To do this: SET LIST[3],LIST[3]+89 Functions are generally used to calculate a number. The calculation should be based on the arguments passed to the function. Function definitions are like subroutine definitions in most ways, but differ in four important respects: + The key word FUNCTION is used instead of SUBR. + The RETWITH statement is used instead of RETURN. + Functions may be called in the midst of any numeric expression. + Function arguments, if any, are enclosed in square brackets. The general structure of a function definition is: FUNCTION identifier ARG type identifier executable statements RETWITH expression Consider the following example that returns the arithmetic square of any argument given to it: FUNCTION SQUARE ARG EXPR E RETWITH E*E This function has no executable statements (and that's OK) because the result in this example can be evaluated with a simple numeric expression. A more sophisticated function might require executable statements to arrive at intermediate results before calculating the final answer on the RETWITH statement. The function SQUARE might be used in a variety of ways: SET X,SQUARE[X] SET X,SQUARE[V+9] SET X,2*SQUARE[Y]+Y+4 In the first example, if X had the value 3, then SQUARE would return 9 and then SET would change the value of X to 9. In the second example, if V had the value 1, then X gets Page - 10 Proton Programming Language Reference Manual the value 100. In the third example, if Y is 5, then X gets the value 59. Advanced programmers may want to define subroutines that are coded in assembly language. The BINSUBR statement provides a convenient means to access such routines. The general form of BINSUBR is: BINSUBR identifier number The identifier gives you a name to call the subroutine (like SUBR), and the number is the number of arguments to pass to the subroutine. Immediately following SUBR, you should have DATA BYTE or DATA INTEGER statements containing executable machine code. When a BINSUBR subroutine is called, arguments are placed in memory starting at $A0 in the zero page. The first argument is put in the word at $A0, the second argument is put at $A2, the third at $A4, etc. Up to 15 arguments may be passed in. All arguments are passed as though they are defined as ARG EXPR. If you want the subroutine to update the value of a variable, you must pass its address; this is done by prefixing a variable with the "get address" symbol, which is & (ampersand). For example, if you have a machine language subroutine that has three arguments, and want to refer to the subroutine as FIXMEM, the definition would look like: BINSUBR FIXMEM 3 DATA BYTE {LDY #0} $A0,0 DATA BYTE {LDA ($A0),Y} $B1,$A0 DATA BYTE {STA ($A4),Y} $91,$A4 DATA BYTE {LDA $A2} $A5,$A2 DATA BYTE {STA ($A0),Y} $91,$A0 DATA BYTE {RTS} $60 and would be called like: FIXMEM $10FE, 80, &ORIGBYTE The example illustrates a subroutine that expects the third argument to be the address of a variable, so it can return a value to the calling program. Advanced programmers on the Apple IIGS may make use of the another subroutine definition statement called TOOL. It allows access to the IIGS tool box stored in the IIGS ROM. By accessing the tool box, a user may make use of various tools that draw on the SHR (Super High Resolution) screen, accept input from the mouse, or perform advanced mathematical operations with SANE (Standard Apple Numerics Environment). You will need a tool statement for each tool function you plan to use in your program. A Tool statement looks like: Page - 11 Proton Programming Language Reference Manual TOOL identifier constant number The identifier is the name that you will use to reference the tool function. Recommendation: use the same name as provided in the tool documentation. The constant is the tool number, with the tool function number in the high byte and the tool set number in the low byte. The number refers to the number of word arguments (not bytes) that need to be passed to the tool. A long word argument counts as two words. It is important to get this number right to avoid your program from crashing! Below is are examples of definitions for the QDStartUp and QDShutDown Tools. They start and stop the Quick Draw II Tool Set for super high resolution graphics (set number $04, function numbers $02 and $03): TOOL QDStartUp $0204 4 TOOL QDShutDown $0304 0 The first tool function has four word arguments: an address to three pages of memory that it can use (you can use the pre-defined PAGE function for this), the master SCB (0 for 320 wide graphics), the pixel map size (0 for the default), and the application User ID (we'll assume it was put in an integer variable by the MMStartUp tool). The second tool has no arguments. Here's how each would be called in a program: QDStartUp Page[3,0], 0, 0, UserID QDShutDown If a tool returns a word value (i.e. pulls a word off the stack), you will need to pass the address of an integer variable to the tool. For example: INTEGER UserID TOOL MMStartUp $0202 1 START MMStartUp &UserID STOP If you need to pass a long word to a tool, you will need to pass it as two consecutive arguments. The upper word is passed in the first argument and the lower word is passed in the second argument. If a tool requires a long word address of a variable, again, two arguments are required. The bank is passed in the first argument (0 for Proton variables), and the bank address is passed in the second. For example: TOOL SetRect $4A04 6 ARRAY INTEGER Rectangle 3 {4 words long} SetRect 0 {bank}, &Rectangle, 0, 0, 20, 30 {min x,y & max x,y} Page - 12 Proton Programming Language Reference Manual You can access the tool sets in ROM (sets $01 through $0C) using the TOOL statement. You can obtain a tool's error return code through the function TOOLERR; for more information refer to TOOLERR in the section for predefined functions. Refer to Apple's IIGS Tool Box Reference set for more information about these tools. Another excellent book for beginners is "Mastering the Apple IIGS Tool box" by Dan Gookin and Morgan Davis (some assembly knowledge is required to understand their examples). EXECUTABLE STATEMENTS Executable statements are statements that do something. All statements between START and STOP are executable statements, as well as statements in SUBR and FUNCTION definitions (after the ARG statements). Executable statements include the SET statement, statements that make up the IF, LOOP, and FOR constructs, a host of predefined subroutines, as well as calls to subroutines you define yourself with SUBR, BINSUBR, and TOOL. The SET statement stores the value of a numerical expression in an integer variable (or an integer variable argument), or an array element. These forms of the SET statement look like: SET variable, expression SET array[expression], expression Example program (which doesn't do anything useful, I'll admit): INTEGER X ARRAY INTEGER A 10 START SET X, 2 {Store 2 in X} SET X, 3 * X {Store 6 (3 * 2) in X} SET A[2], X {Store 6 in the 2nd element of A} SET A[X+1], A[2]+3 {Store 9 (6+3) into the 7th (6+1) element of A} STOP The IF construct allows for conditional execution. In its simplest form, it looks like: IF expression executable statements END If the expression is true, then statements between IF and END are executed. Otherwise, they are skipped. Here's an example: Page - 13 Proton Programming Language Reference Manual IF X > 10 SET X, 0 END The following version of IF allows for alternative execution: IF expression executable statements ELSE executable statements END If the expression is true, the statements between the IF and ELSE are executed, but those between the ELSE and END are skipped. If the expression is false, the opposite happens; the statements between IF and ELSE are skipped, but those between ELSE and END are executed. If you have a several mutually exclusive alternatives, use the general form of the IF construct, as shown below: IF expression executable statements ELSEIF expression executable statements ELSE executable statements END You can have any number of ELSEIF statements in the IF construct. The ELSE part is optional. Each expression on the IF and ELSEIF statements are evaluated in the order that they appear. As soon an expression evaluates to true, the executable statements under that expression are executed up to the construct's next ELSEIF, ELSE, or END statement. Then any remaining statements in the construct (if any) are skipped. If all expressions are false, then the statements under the ELSE statement (if there is one) are executed. Here's an example: IF OPTION = 1 SET X,X+1 ELSEIF OPTION = 2 SET X,X-1 ELSEIF OPTION = 3 SET Y,Y+1 ELSEIF OPTION = 4 SET Y,Y-1 ELSE OUTSTR "Not a valid option.\13\" END Page - 14 Proton Programming Language Reference Manual The LOOP construct allows executable statements to be executed repetitively. It looks like: LOOP executable statements EXIT expression executable statements CONTINUE The executable statements above EXIT or below exit are optional. You can have an arbitrary number of EXIT statements inside the LOOP. All executable statements between the LOOP and CONTINUE statement are executed over and over again (as in a loop) until an expression on any EXIT statement is evaluated to be true. When the expression is true, then execution of the LOOP stops. Any remaining statements in the LOOP construct are skipped, and execution resumes after the CONTINUE statement. Example: LOOP OUTSTR "Enter a Number from 1 to 10:" SET N, INPNUM EXIT (N >= 1) AND (N <= 10) OUTSTR "Number out of range. Try again.\13\" CONTINUE Your LOOP construct needs to have at least one EXIT statement, and it must eventually evaluate to TRUE. Otherwise, the loop will go on forever unless one of the following happens: Your computer wears out (this could take years). Your electric company has a power outage. You turn off the computer. You reboot the computer. You press the RESET key (while holding the Control key). The FOR statement is similar to the LOOP statement. Its executable statements are also executed over and over again. It looks like: FOR variable, expression, expression executable statements NEXT When the statements are executed for the first time, the value of the first expression is stored in the variable. Before executing the statements each time again, 1 is added to the variable. The FOR construct executes for the last time when the variable becomes equal to the second expression. You may freely use the variable in the executable statements. For example, to print the numbers 1 through 10: Page - 15 Proton Programming Language Reference Manual FOR N, 1, 10 OUTNUM N,0 {print the value in the variable N} OUTCHAR 13 {print a carriage return} NEXT In the examples for the IF, LOOP, and FOR constructs above, the executable statements are indented inside the constructs. Indentation is not required, but it is a good habit to get into. It helps you identify where the constructs begin and end. You can have many statements between each part of an IF construct, or inside a LOOP or FOR construct -- up to several dozen. The exact number depends on the complexity of the statements. The statements inside a construct can even include other IF, LOOP, or FOR constructs. A call to a subroutine is an executable statement. The Proton language has many predefined subroutines that you can call; they are described later. Or you can define your own subroutine with SUBR, BINSUBR, or TOOL, and then call it. Either way, the call looks like: subroutine argument , argument , ... In other words, you give the subroutine name and list the arguments separated by commas (if you need to provide more than one argument). For subroutines with one argument, it's just: subroutine argument And for no arguments: subroutine Subroutine arguments must be one of several different types. It can be either an numeric expression, and integer variable, or a string (or string variable, that is, a byte array). If in doubt, for your own SUBR subroutines consult your subroutine's argument definition for the appropriate type. For BINSUBR and TOOL, the arguments must all be numeric expressions. For the predefined subroutines, use the descriptions listed in the next chapter to determine the appropriate argument type. Examples: OUTSTR "Hi, everyone." {OUTSTR requires a string, or byte array} OUTNUM X*10+5,2 {2 expressions, a number to print and its width} DATETIME Date,Time {Requires 2 integer variables} In rare situations, you may find that you need to pass an integer variable or string (i.e. byte array) to a subroutine, but you have it's address instead. You can convert any numerical expression (that represents an Page - 16 Proton Programming Language Reference Manual address) into a variable by preceding it with an ampersand (&). For example, if you are sure that a string exists at address $300, then you could print it with: OUTSTR &$300 Or, with the following definition: DATA ADDRESS S DATA BYTE "Look at me!" You could print the string in the DATA statement with: OUTSTR &S EXPRESSIONS Numeric expressions are commonly used as arguments to Proton Statements. What is a numeric expression? It's either a lone numeric term, or a numeric term, followed by pairs of infix operators and numeric terms. A number is an example of a numeric term, and the plus sign (+) for addition is an example of an infix operator. So all of the following are numeric expressions: 23 23 + 1 23 + 1 + 44 23 + 1 + 44 + -7 23 + 1 + 44 + -7 + 9 When a Proton program runs, numeric expressions are evaluated, creating one number which is then passed to the subroutine as a argument, where presumably it will be used. Below is a list of infix operators available in the Proton language. The operation of each is described in the next chapter. + - * / AND OR = < > <= >= <> The first four (for add, subtract, multiply, and divide) produce ordinary arithmetic results, as you would expect. Well, divide produces a result with no fraction or remainder (you can use the pre-defined MOD function to find a remainder). The remaining operators are relational operators and produce one of two special results: TRUE or FALSE. If you must know, in the Proton language, TRUE is equivalent to the number -1, and FALSE is equivalent to the number 0. When AND and OR is applied to TRUE and FALSE terms, they produce TRUE or FALSE. Advanced programmers: When AND and OR are applied to arbitrary numeric terms, they produce assembly like bit-wise results. Ok, now what is a numeric term? Any of the following: A literal number, such as 5, 10000, or -200. Page - 17 Proton Programming Language Reference Manual The ASCII code of a character such as 'A, '$, or 'b. A hexadecimal number such as $C000 or $EF. A constant, i.e. an identifier defined on a CONSTANT statement. An address identifier defined on a DATA ADDRESS statement. A variable, i.e. an identifier defined on an INTEGER statement. An array element, i.e. an array identifier followed by an index. An EXPR or INTEGER argument defined on an ARG statement. An ARG ARRAY element, i.e. an ARG ARRAY identifier with an index. A function call followed by the functions arguments (if needed). An address of a variable or array, i.e. & followed by an identifier. An expression enclosed by parentheses. An array index is a numeric expression enclosed by square brackets. Function arguments (if any are required) are just like subroutine arguments, except that the entire argument list is enclosed in a pair of square brackets. Given the following definitions: CONSTANT C 3 DATA ADDRESS ADDR INTEGER X ARRAY INTEGER A 10 ARRAY BYTE B 255 FUNCTION F ARG G,H RETWITH (G+1)*(H+1) The following are valid numeric terms: C ADDR X A[5] B[100] G {when used inside function F} F[3,5] F[22+X-C,2*A[5]] &X &A (100 + C) (F[3,5] - A[2] + X + C - 2) Any of the above terms by themselves is a numeric expression. Or combining any of the above terms with infix operators will create a numeric expression. Page - 18 Proton Programming Language Reference Manual When an expression contains two or more numeric operators, their operations are performed strictly from left to right. There is no operator precedence as there is in some other programming languages. Consider the numeric expression: 2 * 3 + 4 * 5 Proton would evaluate that as 2 times 3 is 6, plus 4 is 10, times 5 is 50. To evaluate the 4 * 5 before the addition, use: 2 * 3 + (4 * 5) Which is evaluated as 2 times 3 is 6, 4 * 5 is 20, and then 6 + 20 is 26. If in doubt, always use parenthesis to enclose the operations that must be performed first. It never hurts to add parenthesis when they are not needed. For example, the result is still 26 for: (2 * 3) + (4 * 5) Parenthesis may be nested as in: 2 * 3 + (4 * (5 + 10)) Which produces 66. After 2 * 3, the (5 + 10) is added, then multiplied by 4 to get 60. Finally, 6 is added to 60. Parenthesis are particularly important when mixing arithmetic operations with relational operations. Consider the following which might appear on an IF statement: X = (2 + 3) It checks to see if the number in the variable X is equal to 5. The expression evaluates to TRUE if it is, and FALSE if it isn't. However, this will probably produce an unintended result: X = 2 + 3 It evaluates to 2 or 3, depending on whether X contains 2 or not. For example, if X contains 2, then X = 2 evaluates to TRUE (-1) and then -1 + 3 is 2. The moral: use parenthesis if ever in doubt. Page - 19 Proton Programming Language Reference Manual Chapter 2: DESCRIPTION OF PREDEFINED OPERATIONS This chapter lists all operations that are pre-defined. That is, you can use them in your executable statements without providing any definition for them. All operations listed is this chapter are one of the following three types: Infix operators have the form "term1 op term2" where "op" is an operator symbol. For example, the "+" in "3 + 5" is an infix operator. Infix operators are used to form expressions that have more than one term. Function calls have the form "func[expr1, expr2,...]" where "func" is the name of the function. Function calls can be used as a term in an expression. The number of expressions in the brackets must match the number of arguments required for the predefined function. If none are required, omit the brackets. Subroutine calls have the form "subr expr1, expr2,..." where "subr" is the name of the subroutine. Subroutine calls must appear on a line by itself. The number of expressions after the SUBR name must match the number of arguments required for the predefined subroutine. OVERVIEW OF ARGUMENT TYPES For the descriptions that appear in this chapter: The symbols t1, t2, t3 are terms resulting in signed numbers from -32768 to 32767. The symbols e1, e2, e3 are expressions resulting in signed numbers from -32768 to 32767. The symbols u1, u2, u3 are expressions resulting in unsigned numbers from 0 to 65535. The symbols b1, b2, b3 are expressions resulting in byte values, that is, numbers from 0 to 255. The symbols a1, a2, a3 are expressions representing addresses, that is, the location of something in the computer's memory. In most situations, you may not need to know the specific address of something, but you may need to get an address from one subroutine or function, put it in a variable, and pass it to another subroutine or function. The symbols i1, i2, i3 represent integer variables. In this context, only the name of an integer variable may be used. The symbols s1, s2, s3 are string variables or string literals. A string variable is a byte array variable Page - 20 Proton Programming Language Reference Manual declared with ARRAY BYTE, where the 0th element has the length, and the 1st, 2nd, 3rd, etc. elements contain the characters. A literal string is a series of characters, surrounded by quotation marks, e.g. "HELLO". Thus, s1 could be the name of a byte array variable, or a literal string. The symbols ai1, ai2, ai3 are the names of integer array variables declared with the ARRAY INTEGER or ARG ARRAY INTEGER statement. The symbols ab1, ab2, ab3 are the names of byte array variables declared with the ARRAY BYTE or ARG ARRAY BYTE statement. The symbols ab1, ab2, and ab3 are like s1, s2, and s3, except that they do not represent literal strings. ARITHMETIC OPERATIONS FOR REGULAR SIGNED NUMBERS Below are operations for signed numbers, and are either infix operators or functions. t1 + t2 - Results in the sum of t1 plus t2. t1 - t2 - Results in the difference of t1 minus t2. t1 * t2 - Results in the product of t1 multiplied by t2. t1 / t2 - Results in the division of t1 divided by t2. The remainder, if any, is discarded. Example: 23 / 5 is 4. NEG[e1] - Negate "e1", that is, change the sign of e1. Examples: NEG[3] is -3, NEG[-2] is 2. MOD[e1,e2] - Modulus of e1 and e2. That is, return the remainder of e1 divided by e2. Example: Mod[23,5] is 3. MIN[e1,e2] - Returns e1 or e2, whichever is less. Example: MIN[5,2] is 2. MAX[e1,e2] - Returns e1 or e2, whichever is greater. Example: MAX[5,2] is 5. WORD[b1,b2] - Returns the word formed by the byte values b1 and b2 where b1 is the high order byte and b2 is the low order byte. Examples: Word[1,44] is 300 and Word[4,0] is 1024. HIBYTE[e1] - Returns the high order byte of the word value e1. Examples: HiByte[300] is 1, and HiByte[1024] is 4. LOBYTE[e1] - Returns the low order byte of the word value e1. Examples: LoByte[300] is 44, and LoByte[1024] is 0. Page - 21 Proton Programming Language Reference Manual RELATIONAL AND LOGICAL OPERATORS For the operations below, true is equivalent to the expression -1, and false is equivalent to 0. The relational operations are infix operators (i.e., have the form "t1 op t2") where op is one of six operators. The operator returns true if the relationship is true, false if not. The operators are: t1 = t2 - equal t1 <> t2 - not equal t1 < t2 - less than t1 <= t2 - less than or equal t1 > t2 - greater than t1 >= t2 - greater than or equal Examples: A < 3, 5 >= X, G = (X+2) NOT[e1] - This function returns true if e1 is false, and vice versa. Also returns the binary complement of e1, for any value of e1. For example: NOT[-1] is 0, NOT[0] is -1, NOT[1] is -2. (Same as -1 - e1.) t1 OR t2 - This infix operator returns true if either t1 or t2 is true. Returns false only if both t1 and t2 are false. Also returns a bit for bit binary OR between t1 and t2 for any values of t1 and t2. t1 AND t2 - This infix operator returns true only if both t1 and t2 are true. Returns false if either t1 or t2 is false. Also returns a bit for bit binary AND between t1 and t2 for any values of t1 and t2. OPERATIONS FOR UNSIGNED NUMBERS The relational operators = and <> work fine for unsigned numbers as well as signed numbers. Below are all operations intended specifically for unsigned numbers, and all are functions. If the result of an arithmetic function exceeds 65535 (the maximum for an unsigned number) or is negative, it does not cause a run time error. UPLUS[u1,u2] - The sum of u1 plus u2. UMINUS[u1,u2] - The difference of u1 minus u2. UMULT[u1,u2] - The product of u1 multiplied by u2. UDIV[u1,u2] - The result of u1 divided by u2. Page - 22 Proton Programming Language Reference Manual UMOD[u1,u2] - The modulus of u1 and u2. ULT[u1, u2] - Returns true if u1 is less than u2, false otherwise. UGT[u1, u2] - Returns true if u1 is greater than u2, false otherwise. SHIFTL[u1, b1] - Shifts the bits in u1 to the left by b1 bits. The result is the same as multiplying u1 by 2 raised to the b1 power. SHIFTR[u1, b1] - Shifts the bits in u1 to the right by b1 bits. The result is the same as dividing u1 by 2 raised to the b1 power. CARRY - Returns 0 if no overflow occurred in the most recent UPLUS or UMULT function call. If an overflow did occur, 1 is returned for UPLUS, and the high order word of the multiplication result is returned for UMULT. For the most recent UMINUS, 1 is returned if no underflow occurred, and 0 is returned if it did. For SHIFTL and SHIFTR, all bits shifted beyond the left or right edge of the word are returned. INPUT OPERATIONS These read values from the current input file or device. See also the section for ProDOS MLI routines. INPCHAR - This function returns a single character from the current input. INPNUM - This function reads a decimal number (in ASCII character form) from the input file or device and returns its integer value. INPHEX - This function reads a hexadecimal number (in ASCII character form) from the input file or device and returns its integer value. SYNERR - This function returns true if the syntax of the number previously input by INPNUM or INPHEX is invalid, false if the syntax was correct. INPSTR s1, b1 - This subroutine reads a line of text from the input and puts it into string s1. The value b1 is the maximum number of characters INPSTR will put in s1. INPFILE b1 - This subroutine instructs subsequent calls to the above Input routines to read their input from file b1. If b1 is 0, then input will come from the current input device, usually the keyboard (this is the default when your Page - 23 Proton Programming Language Reference Manual programs begins). Otherwise, b1 should be the file number obtained on the ProDOS OPEN call. OUTPUT OPERATIONS These write values to the current output file or device. See also the section for ProDOS MLI routines. They are all subroutines. OUTCHAR b1 - Treats b as an ASCII code and writes the corresponding character. Example: OUTCHAR 65, or OUTCHAR 'A produces the letter "A", OUTCHAR 32 produces a blank, and OUTCHAR 13 produces a carriage return. OUTNUM e1, b1 - Writes the integer e1 in ASCII decimal form using the number of characters given by b1. If number of digits in e1 is smaller than b1, then blanks are added to the left of the digits. Otherwise, b1 is ignored. The value for b1 cannot exceed 16. OUTHEX e1,b1 - Same as OUTNUM except that e1 is written in hexadecimal form. OUTSTR s1 - Prints out the characters in the string s1. OUTSTR does not print out a carriage return, unless the string actually contains one. OUTFILE b1 - Instructs subsequent calls to the above output routines to print their output in file b1. If b1 is 0, then output will go to the current output device, usually the screen (this is the default when your programs begins). Otherwise, b1 should be the file number obtained on a ProDOS OPEN call. MEMORY ACCESS OPERATIONS The following operation allow direct access to the computers memory. They are all subroutines unless otherwise noted. &variable - The & function (brackets are not used with this special symbol) returns the address of the given variable, whether it be a simple integer variable or complex variable such as a byte array or integer array. Only defined names may be used with this function. PEEK[a1] - This function returns the byte located at the memory address specified by a1. PEEKW[a1] - This function returns the word located at the memory address specified by a1. Page - 24 Proton Programming Language Reference Manual POKE a1,b1 - Puts the byte value b1 at the memory address a1. POKEW a1,e1 - Puts the word value e1 at the memory address a1. CALL a1 - Jumps to the machine language subroutine located at memory address a1. The subroutine must end with an RTS opcode, and need not save or restore any register values. MOVEASC a1,a2,e1 - Move the memory block starting at address a1 to the memory address a2. The number of consecutive bytes moved is given by e1. The bytes are moved byte by byte in ascending order; that is, the first byte of the block is moved first. For example: MOVEASC $800,$900,45 moves 45 bytes from address $800 to address $900. MOVEDES a1,a2,e1 - Like MOVEASC, except that a1 and a2 define the ends of the memory blocks and the bytes are moved in descending order, that is, the last byte of the block is moved first. For example, MOVEDES $844,$944,45 has the same result as the MOVEASC example above. MOVEASC and MOVEDES will have different results when the memory blocks overlap. SEARCHPOS[s1,a1,u1] - This function searches for a string within an area of memory. S1 defines the string, a1 is a non-zero address that defines the beginning of the memory area, and u1 is length (in bytes) of the memory area. SEARCHPOS returns the address of the first occurrence of s1 in the memory area. If s1 can not be found, 0 is returned. PAGE[b1,b2] - If b2 is 0, this function returns an address to the beginning of block of memory for you to use. The size of the block is specified in pages given by b1 (a page is 256 bytes long). The pages found by this function are page-aligned. Consecutive calls to this routine will return addresses to new and unique pages. If there are not enough pages left, then the address 0 is returned. The address 0 is for reporting such an error; do not use it as a real address in your program. If b2 is not zero, then the address to page b2 is returned, if possible. That is, the address is returned if the number of pages given by b1 is free, starting with page b2. If not, then 0 is returned. Example: Page[4,0] returns an address to area of free memory that is 4 pages long (1024 bytes long). Page[32,32] returns the address to the 1st High Resolution Graphics Display area, if the memory area is free. If it is not free then 0 is returned, and that means that area was previously reserved by another page function call, or is reserved and in use by the Proton execution environment. Note for ProDOS experts: PAGE does its memory management independent of the ProDOS system bit map. Page - 25 Proton Programming Language Reference Manual SCREEN CONTROL OPERATIONS These operations manipulate attributes that are special to the computer's screen. They are all subroutines. GRAPHICS b1 - Puts the screen in graphics mode, where b1 defines one of many modes. If b1 is 0, you will get a low resolution graphics screen that is cleared and has no provision for displaying text. A low resolution screen is 40 pixels across and 48 pixels up and down. If you want something different, choose which attributes you want below and add up each associated number. Use the sum for b1. 1 - Don't clear the graphics screen. 2 - Mixed text mode, i.e., put 4 text lines at the bottom of the screen. 4 - High Resolution Screen (280 x 192, starts at page 32 for 32 pages). 8 - Without the Double Resolution attribute, this displays the alternate graphics area (starts at page 8 for low res for 4 pages, or at page 64 for high res for 32 pages). With the Double Resolution attribute, this does not affect the display; instead, it causes PEEK or POKE to access the second graphics area in the alternate memory bank (starting at page 4 for low res for 4 pages, or at page 32 for high res for 32 pages). 16 - Double Resolution, i.e., double the number of pixels across the screen. This mode combines graphics areas in the main and alternate memory banks to acheive the doubling effect. Tip: Use PAGE to reserve a high resolution area or the alternate low res graphics area. Warning: When using the High Resolution mode and the Double Resolution mode together (to get double high res), avoid using the /RAM volume ram disk. The /RAM volume disk overlaps with the alternate memory bank. Or, you can use /RAM, if the very first file created on /RAM is 8K long, and is not subsequently modified. PLOT e1,e2,b1 - Plot a point of the color given by b1 to screen position given by the X-Y coordinates e1 and e2. Currently, only the low resolution screen is supported. The color range for b1 is 0-15, the range for e1 is 0-39, and the range for e2 is 0-47 (0-39 for the mixed text mode.) PIXEL[e1,e2] - This function returns the color of the pixel at coordinates e1,e2. For example, if you specify PLOT 10,20,3 then PIXEL[10,20] will return 3. Currently, only the low resolution screen is supported. Page - 26 Proton Programming Language Reference Manual TEXT b1 - Puts the screen in the 80-column text mode if it is not already. If b1 is 0, it will clear the screen and print characters in normal mode. If you want something different, choose which attributes you want below and add up each associated number. Use the sum for b1. 1 - Don't clear the text screen. 2 - Display characters in Inverse mode. 4 - Display a 40-column screen. GOTOXY b1,b2 - Positions the cursor on the screen to the column given by b1 and the line given by b2. The value b1 must lie in the range 0-39 (0-79 for 80 column text) and b2 must lie in the range 0-23. MISCELLANEOUS OPERATIONS PARM[b1] - This function returns the address of strings that were typed on the command line that invoked your program (not including the program name). PARM[n] returns the address of the n-th string. PARM[0] returns the number of strings on the command line. To use PARM as a string argument, precede it with a @, e.g. use @PARM[1] to pass the first argument. TOOLERR - This function returns the error code generated by the most recent call to a IIGS Tool Box function. A value of 0 means no error occurred. Refer to Apple's Tool Box Reference for a list of tool box error codes, and what they mean. Tool Box functions are accessed by defining a tool using the TOOL definition statement. CONVNUM[s1,e1] - This function converts the numerical digits in the string s1 to its equivalent number. E1 is an index into the string where the digits begin. For example, CONVNUM ["Do 34 tricks.",4] returns 34. The function SYNERR returns true if a valid number was not found in the string, false if it was valid. CONVHEX[s1, e1] - Like CONVNUM, except the function converts hexadecimal digits. For example, CONVHEX ["FF",1] returns 255. SYNERR returns the status of CONVHEX, like it does for CONVNUM. PRODOS MLI OPERATIONS The following routines provide a subroutine interface to every MLI call in the ProDOS MLI (Machine Language Interface). They are all subroutines unless otherwise noted. Refer to Apple's ProDOS Technical Reference if you need more information. Page - 27 Proton Programming Language Reference Manual The routine descriptions refer to these types of values: Date and Time: Each of these is an integer word value. To obtain the hours and minutes from the time word value, use HIBYTE[time] and LOBYTE[time] respectively. To obtain the Year, month, and day from the date word value, use UDIV[date, 512], (UDIV[date, 32] AND 15), and (date AND 31), respectively. To create the time word value use WORD[hour,min], and to create the date word value use (UMULT[year,512] + (month*32) + day). In all cases, the month value is a number from 0 to 11, representing January to December, respectively. Access parameter: 227 ($E3) is for unlocked files, and 33 ($21) is for locked files. If the file does not need to be backed up via a back up tool, then the values are 195 ($C3) and 1. In general, add the following numbers associated with each attribute to get the access parameter you want: 128 (file can be deleted), 64 (file can be renamed), 32 (file needs to be backed up), 2 (file can be written to), 1 (file can be read). File Type: Some common values - 4 is TXT, 6 is BIN, 15 is DIR, 252 is BAS, 253 is VAR, 255 is SYS. Auxiliary File Type: Normally zero, but for TXT files used for random access it is the record length, and for BIN files it is the start address of the binary data. Storage Type: ProDOS stores regular files in one of 3 ways (Type 1, 2, or 3) depending on its size. ProDOS stores directories as type 15. Unit Number: Location of Disk Drive obtained by the formula ((D-1) * 128) + (S * 16), where S is the slot number of the disk (1-7) and D is the drive number (1 or 2). To convert a unit number to the slot and drive use (unit/16 AND 7), and (unit/128)+1, respectively. File Number: ProDOS assigns a number to each open file on the OPEN call. It is used by subsequent MLI routines to identify which file your program wants to operate on. File Position: Marks the position in a file that READ or WRITE will read or write data. A file position is a "long word" and is stored as 2 words in an INTEGER ARRAY variable (maximum entry of 1), with the least significant word in entry 0. When specified as an argument on a MLI call, it is the name of an INTEGER ARRAY variable. And Now for the MLI routines: ALLOC.INTERRUPT i1,a1 - Installs an interrupt handler that resides at the address a1. This routine will assign the Page - 28 Proton Programming Language Reference Manual handler a priority and put the value in the integer variable i1. DEALLOC.INTERRUPT b1 - Removes an interrupt handler. The value b1 is the priority assigned by ALLOC.INTERRUPT and identifies the handler to be removed. READ.BLOCK b1,a1,e1 - Reads a 512 byte block from a ProDOS disk. The value b1 is the unit number. Address a1 is a 512 byte block in memory to receive a copy of the disk block, and e1 is the block number on the disk. WRITE.BLOCK b1,a1,e1 - Like READ.BLOCK, except this routine writes 512 bytes located at address a1 to block number e1. Use this routine with CAUTION. If you do not understand the consequences of this routine, you may destroy portions of the disk in the slot and drive specified by b1. GET.TIME i1,i2 - Returns the date and time as word values and places them into the integer variables i1 and i2, respectively. CREATE s1,b1,b2,e1,b3,e2,e3 - Creates a disk file using the path name in string s1. The remaining values define properties of the file as follows: b1 - The access number b2 - The file type e1 - The auxiliary file type b3 - The storage type e2 - Current date e3 - Current time You can always use 0 for the storage type; ProDOS will automatically adjust this value when needed. The date and time word values may be obtained from GET.TIME. DESTROY s1 - Deletes a disk file using the path name in string s1. RENAME s1,s2 - Renames a disk file defined by the path name in string s1. The new name is in string s2. SET.FILE.INFO s1, ai1 - Changes the descriptive information associated with the file whose name in string s1. Argument ai1 is an integer array with maximum entry of at least 6. The array should contain the new information in entries 0 through 6 as follows: 0 - Access parameter 1 - File Type 2 - Auxiliary File Type 3 - (Value not used) 4 - (Value not used) 5 - Date of last modification 6 - Time of last modification Page - 29 Proton Programming Language Reference Manual GET.FILE.INFO s1,ai2 - Obtains the descriptive information that is currently associated with the file name in string s1. Argument ai2 is an integer array (with a maximum entry of at least 8) which receives the information. After this call, the array will contain information in each of the entries as follows: 0 - Access number 1 - File Type 2 - Auxiliary File Type (or number of blocks on volume if s1 has a volume name) 3 - Storage Type 4 - Blocks used by File (or Volume) 5 - Date of last modification 6 - Time of last modification 7 - Date File was created 8 - Time File was created After calling GET.FILE.INFO, you may use the same array for SET.FILE.INFO, after making desired changes in the array. ONLINE b1,ab1 - Returns the names of one or all volumes currently active in the byte array ab1. If b1 is a unit number, then ab1 simply receives the drive's volume name (up to 15 characters). If b1 is 0, then a list of all online volumes will be returned in the byte array in the following fashion: The first name goes at index 0, the second at index 16, the third at index 32, etc. A string length of zero in the list indicates the end of the list. The array should have a maximum index of 255 to accommodate up to 16 names. In all cases the unit number will be imbedded in the upper half of the string's length value and should be removed before the string is used. Example (s is declared as BYTE ARRAY s 255): ONLINE 0, s FOR i,0,15 SET s[i*16], s[i*16] AND 15 {Get rid of Unit number info from lengths} NEXT The drive and slot may be also extracted from the length value (at every sixteenth index) as described for unit numbers. SET.PREFIX s1 - Modifies the current ProDOS prefix using a new path name in string s1. If the string starts with /, then the current prefix is changed. Otherwise the name in s1 is added to the current prefix. GET.PREFIX ab1 - Obtains the current path name and puts it into the byte array variable. Page - 30 Proton Programming Language Reference Manual OPEN s1,a1,i1 - Opens a file whose path name is in string s1. Address a1 can refer to any 4 available pages; ProDOS needs 4 pages of page aligned memory for each open file and uses it to buffer file data between your program and the disk. Usually, you may find it convenient to use the function PAGE[4,0] for a2. ProDOS also assigns a file number to each open file and is required for other ProDOS calls that operate on the file being opened. OPEN puts the file number in integer variable i1. After opening a file, your program may read or write to the file, or perform other operations that require a file number. NEWLINE b1,b2,b3 - Tells the READ routine to only read up to a new line character each time it is called, for the file given by file number b1. The mask value b2 masks bits when searching for a new line character (e.g. 255 means compare each character exactly as is, 127 means ignore the high bit of each input character, etc). The new line character b3 defines the character to search for (usually you want 13 for the carriage return character). To turn off this feature use 0 for b2. READ b1,a1,e1,i1 - Reads data from a file given by file number b1 at the current file position. READ will copy data from the file to the address a1 (e.g. the address of a byte array). The number of bytes to read is given by e1 (and should not exceed the length of a byte array). The integer variable i1 receives the value of the actual number of bytes that was read. The actual number of bytes read will differ from e1 if an end of file was encountered during the read, or if the NEWLINE feature was active and a new line was encountered. WRITE b1,a1,e1,i1 - Writes data to a file given by file number b1 at the current file position. WRITE will copy data from the file to the address a1 (e.g. the address of a byte array). The number of bytes to write (starting at a1) is given by e1. The integer variable i1 receives the value of the actual number of bytes that was written. The actual number written might be different than e1 if an error occurred such as the disk being full. CLOSE b1 - Closes the file given by the file number b1. If the file was written to, it also flushes out any pending data that might be in the file buffer (see FLUSH for more information). FLUSH b1 - Flushes data (if any exists) in the file buffer for the file number b1. When you write to a file, some of the data may not go to the disk right away; it may be stored in its file buffer for awhile. If you want to guarantee that the data gets written out at any point in time, call this routine. It's a particularly good idea when your Page - 31 Proton Programming Language Reference Manual program is writing to a floppy disk and your program pauses for a while (for example, while waiting for user input). SET.MARK b1,ai1 - Sets or moves the current file position for the file given by file number b1. It sets it to the "long word" value stored in the integer array ai1. Before calling this routine, set the 0th element to the lower word and set the 1st element to the upper word. For example, if the desired file position is less than 64K bytes into the file, put the desired byte offset in the 0th element, and put 0 in the first element. To reset the file position to the beginning of the file, use 0 for both elements. GET.MARK b1,ai1 - Gets the current file position of the file given by file number b1. The file position is a 2 word "long word" value. The 0th element of the integer array ai1 receives the lower word of the file position, and the 1st element receives the upper word. For example, if the file position is less than 64K, the 0th element will contain the current byte offset into the file, and the 1st element will contain 0. The file position is automatically adjusted after read (input) and write (output) operations. SET.EOF b1,ai1 - Expands or shrinks a file by defining a new size (in bytes) for the file (given by the file number b1). It sets the new size to the file position stored in the integer array ai1. Set the array values in the same format as that for SET.MARK. GET.EOF b1,ai1 - Returns the size (in bytes) of a file given by the file number b1. The integer array variable ai1 receives the size in the same format as GET.MARK receives the file position. SET.BUF b1,a1 - Changes the file buffer address that was originally specified on the OPEN call to a new address. The file number is given by b1, and a1 is the new address. GET.BUF b1,i1 - Returns the file buffer address as defined on the OPEN or changed on a SET.BUF call. The file number is given by b1, and i1 is the integer variable that receives the value of the file buffer address. DOSERR - This function returns a number that describes the result of the most recent ProDOS MLI routine call. It also applies to calls to the input and output routines starting with INP... and OUT..., if operating on a file. A list of possible returned numbers and their meanings are described in the next chapter. Page - 32 Proton Programming Language Reference Manual Chapter 3: DESCRIPTION OF ERRORS COMPILATION ERRORS When a Proton Program is compiled with the PUE COMP command, a listing is created and is either copied to a file, or is displayed to the screen. The compiler command COMP can detect a variety of errors. If an error is found, the listing shows where the error is in your program and labels it with a compiler error code. Below is a list of all possible error codes and their meaning. Keep in mind that one actual error in your program may cause several error codes to be generated. 1 - Text follows end of program. 2 - ELSE encountered without associated IF. 3 - END encountered without associated IF, ELSE, or ELSEIF. 4 - Executable statement is located outside of SUBR, FUNCTION, or START block. 5 - Start encountered inside of SUBR block. 6 - EXIT is not located inside LOOP/CONTINUE block. 7 - CONTINUE encountered without associated LOOP. 8 - NEXT encountered without associated FOR. 9 - Too many EXIT statements in LOOP; or FOR, LOOP, or IF blocks are too deeply nested. 10 - No START statement in program. 11 - Body of LOOP or FOR block is too large. 12 - Body of IF, ELSEIF, ELSE, or LOOP block is too large. 13 - Identifier was not previously declared. 14 - FOR control variable is not of type INTEGER. 15 - Total storage required by all variables up to this point is too large. 16 - RETWITH encountered without associated FUNCTION statement. 17 - RETURN encountered without associated SUBR statement. 18 - ARRAY size specification is not a CONSTANT identifier or a number. 19 - START statement occurs more than once in the program. 20 - This particular statement key word or SUBR call should have no arguments. 21 - One or more numeric expressions are expected after statement key word. 22 - Too many identifiers declared in program. 23 - Not enough memory storage to compile program. 24 - Statement does not begin with statement key word or SUBR identifier. 25 - A comma is expected. 26 - An identifier to be declared is expected. 27 - Identifier is already declared. 28 - DATA BYTE value has invalid syntax or is out of range. 29 - A comma (when valid) or end of line is expected. 30 - A left square bracket expected after the array or function identifier. 31 - Constant, variable, or function expected. Page - 33 Proton Programming Language Reference Manual 32 - Expression is too complex. 33 - Too many arguments on the pre- or user-defined subroutine or function call. 34 - Too few arguments on the pre- or user-defined subroutine or function call. 35 - Either a binary operator or the end of the expression is expected. 36 - An identifier is expected after the "&" symbol. 37 - To many characters in identifiers; use fewer identifiers or shorter names. 38 - Literal value is too big or too small. 39 - Program ends prematurely -- no matching STOP statement for START. 40 - Statement line is incomplete; more code is required to complete it. 41 - Extraneous code encountered on the statement line. 42 - The "]" symbol was expected. 43 - The ")" symbol was expected. 44 - The size specification is too big for an integer array. 45 - The " double quote characters is expected before the end of line. 46 - SET variable is not an integer or an array element. 47 - Character expected after "'" apostrophe. 48 - Minus "-" not allowed in front of "'" literal character or "$" hex number. 49 - Literal integer value expected for TOOL or BINSUBR description. 50 - Hex digit 0-9, or A-F expected after "$". 51 - Type of variable does not match type required for this argument position. 52 - Argument declaration does not occur inside routine declaration 53 - Too many arguments are declared. 54 - Argument or data declaration occurs after executable code begins. 55 - No declarations are allowed after START. 56 - Argument declaration occurs after data declaration. 57 - Data declaration not supported inside of SUBR, FUNCTION, or START block. 58 - Invalid number or constant between delimiters \n\ in literal string. 59 - INCLUDE statements nested too deeply. 60 - INCLUDE file name too long or file can not be opened. RUN TIME ERRORS As your Proton program is running, the Proton execution environment will check for certain types of errors. If it detects an error at this time, it is called a run time error. When such an error is found, your program is immediately halted, and a program offset is displayed. You can determine which statement produced the run time error by Page - 34 Proton Programming Language Reference Manual matching the offset to the nearest offset displayed in your Proton compiler listing. There are no specific error code numbers for run time errors. However, any of the following error situations can produce a run time error: An overflow has occurred in an arithmetic operation such as +, -, *, or /. An overflow can occur if the result exceeds 32767, or is less than -32768, or if a number is divided by zero. An attempt is made to assign a byte array element a value that is out of range, that is, greater than 255, or less than zero. This can also happen when passing an out of range value as an argument to a pre-defined operation that only accepts byte values. A subroutine or procedure overflow. This can happen at any statement, when too many subroutines or function calls are nested. By nesting, that means a subroutine or function calls another subroutine or function, which calls another subroutine or function, and so on. Nesting up to a dozen subroutine or function calls (meaning a dozen subroutines or functions are simultaneously active) should never create a problem. And unless each function or subroutine has a large number of arguments, you should be able to nest many more calls than that. PRODOS ERRORS When your Proton program is running, and ProDOS is accessed, one of several errors can potentially occur. ProDOS will return a ProDOS error code and which accessible through Proton's predefined function DOSERR. Below is a list of ProDOS error codes and their meaning. 0 - No Error, call was successful. 37 - Interrupt table is full. 39 - I/O Error, disk is damaged or not in drive. 40 - Disk Drive not installed, that is, a specified unit does not have a disk drive. 43 - Disk Write is Protected, that is, the disk's write protect notch is covered or switch is enabled. 46 - Disk Volume was switched, that is, a disk with an open file was removed from its drive and replace with another disk. 64 - Path name syntax is invalid, the path name should only have letters, numbers, periods, and slashes. 66 - Too many files are open, at most eight files can be open at one time. 67 - File number is invalid, that is, the file reference number is not a number returned by the OPEN call. Page - 35 Proton Programming Language Reference Manual 68 - Specified Path does not exist, that is, one of the directory names in the path does not exist. 69 - Specified Disk Volume is not in drive, that is, the volume name in the path name does not match that in any drive. 70 - Specified File does not exist, that is, the file name in the path name does not exist in the specified directory. 71 - File Name already exists, that is, an attempt was made to create or rename a file that already exists. 72 - Disk Volume is full; there is no more room to add files or write data. 73 - Volume Directory is full, that is, an attempt was made to create a file or directory in the volume directory which was full. A limited number of files and directories are allowed there. 74 - Incompatible ProDOS file, that is, a file was created using a later version of ProDOS which happens to be incompatible with an earlier version now in use. 75 - Storage Type is Invalid; a storage type can only be 1,2,3, or 15. 76 - End of File was reached during a read operation. 77 - Specified Position larger than file, that is, an attempt was made to set the file position beyond the end of the file. 78 - Cannot perform operation because the file is locked. 80 - File is already open, that is, an attempt was made to OPEN, DESTROY, or RENAME a file that is already open. 81 - Directory is damaged, based on an audit of internal file count data. 82 - Disk is not a ProDOS volume. 83 - Argument passed to MLI call was out of range. 85 - Cannot do operation when 8 volumes are open, that is, an operation was requested that would have required ProDOS to open another file. 86 - Bad buffer address passed to OPEN, or SET.BUF, that is, the address overlaps area(s) of memory reserved by ProDOS. 87 - Same volume name found in two different drives; each disk drive must have volumes with unique names. 88 - Bit Map on volume is damaged; the bit map is used to store data regarding which blocks on a disk are free or in use. Page - 36 Proton Programming Language Reference Manual Chapter 4: SUMMARY OF THE PROTON LANGUAGE This section summarizes the Proton programming language in a notation known as Backus-Naur Form (BNF). The following symbols are part of the BNF notation and are not meant to represent characters in the Proton language: {} Braces are used to indicate items that may be absent, present once, or present multiple times. | The bar is used to separate a list of items, of which only one is selected. <> Angle brackets are used to enclose names of items defined elsewhere. ::= This symbol means the name at the left is defined to be the construction on the right. In other words, the name at the left side of the symbol, if used elsewhere, is simply a short hand notation for what occurs on the right hand side. Uppercase letters and other symbols are characters that you actually type in as part of your program. ::= ::= a carriage return, a.k.a. a newline ::= any displayable character ::= A | B | C | ... | Z ::= 0 | 1 | 2 | ... | 9 ::= | A | B | C | D | E | F ::= { | } START STOP ::= CONSTANT { , } | INTEGER { , } | ARRAY { , } | DATA ADDRESS | DATA { , } ::= ::= ::= ::= ::= ::= ::= Page - 37 Proton Programming Language Reference Manual ::= { | | . } ::= INTEGER | BYTE ::= | ::= " { } " ::= | - | ' | $ { } ::= { } ::= SUBR RETURN | FUNC RETWITH | BINSUBR { DATA , { } } | TOOL ::= { ARG { , } } ::= EXPR | INTEGER | ARRAY BYTE | ARRAY INTEGER ::= { } ::= | | IF { ELSEIF } END | LOOP { EXIT } CONTINUE | FOR , , NEXT | SET , Page - 38 Proton Programming Language Reference Manual ::= | ELSE ::= | { , } ::= | [ ] ::= { } ::= | | | | | & | ( ) ::= | [ { , } ] ::= | | | | | @ ::= + | - | * | / | AND | OR | = | < | > | <= | >= | <> *** END OF REFERENCE MANUAL *** Page - 39