MISCELLANEOUS Statements Updated: July 10, 2007 BYTESWAP MyVar BYTESWAP i, where i is a 32-bit, non-floating value (INTEGER, LONG, etc) reverses the byte order of variable i. Among other things, BYTESWAP can be used to convert back and forth from little-endian to big-endian representations. BYTESWAP is also a Numeric Function: j = BYTESWAP(i). DEC(MyVar[,amount]) INC(MyVar[,amount]) Can use real numbers and fractional values for INC/DEC amount. The second optional operand in INC/DEC statements (amount) can be a numeric expression. Thus, we can write: INC(i, j+k) or INC(i, INSTR(s$,t$)) INC and DEC are optimized to autodetect non-float values. INC(i,10): DEC(j,2): INC(k) is faster than i = i + 10: j = j - 2: k = k + 1 IADD(int1, int2) int1 = int1 + int2. Similar to INC(). Examples: IADD(i,20) 'i = i + 20 IADD(i,j) 'i = i + j IAND(int1, int2) int1 = int1 AND int2. Examples: IAND(i,20) 'i = i AND 20 IAND(i,j) 'i = i AND j IDIV(int1, int2) int1 = int1 / int2. Examples: IDIV(i,20) 'i = i / 20 IDIV(i,j) 'i = i / j IMOD(int1, int2) int1 = remainder of int1 / int2. Examples: IMOD(i,20) 'i = remainder of i / 20 IMOD(i,j) 'i = remainder of i / j IMUL(int1, int2) int1 = int1 * int2. Examples: IMUL(i,20) 'i = i * 20 IMUL(i,j) 'i = i * j IOR(int1, int2) int1 = int1 OR int2. Examples: IOR(i,20) 'i = i OR 20 IOR(i,j) 'i = i OR j ISHL(int1, immediate) int1 = int1 SHL immediate. Multiply by a power of 2: ISHL(i,4) 'i = i * 16 where 2^4 = 16 ISHL(i,2) 'i = i * 4 where 2^2 = 4 ISHR(int1, immediate) int1 = int1 SHR immediate. Divide by power of 2: ISHR(i,4) 'i = i / 16 where 2^4 = 16 ISHR(i,2) 'i = i / 4 where 2^2 = 4 Note: immediate values above are 1 to 31. Your code, where prudent, should check for overflow (incorrect result) with IMUL and ISHL. For the "I" integer functions, HotBasic error checks that the int1 argument is a dimensioned INTEGER (alias LONG) variable. ISUB(int1, int2) int1 = int1 - int2. Similar to DEC(). Examples: ISUB(i,20) 'i = i - 20 ISUB(i,j) 'i = i - j IXOR(int1, int2) int1 = int1 XOR int2. Examples: IXOR(i,20) 'i = i XOR 20 IXOR(i,j) 'i = i XOR j DOEVENTS + processes pending messages in $APPTYPE GUI. Used primarily in event procedures which generate messages or which require multiple time slices to complete. END terminates program; same as Application.Terminate; not same as end of source code. If you have GOSUB routines (LABEL ... RETURN), place them after END so your main program code will not "fall into" a routine. ENVIRON string; string is {variable}={value}; ENVIRON "TEMP=C:\temp" FREECONSOLE "frees console window". Typically used in GUI applications after SHOWCONSOLE, if no more console display or PRINT's are wanted. GOTO label; jumps to code at label. IF {conditional expression} THEN GOTO Finished INITARRAY array; clears array data. DIM dat(99) As LONG 'code INITARRAY dat INITARRAY is *not* needed at program startup for any array. LPRINT string; sends string expression to lpt1 LPRINT "hello world"+crlf 'prints one line mystring.loadfromfile("myfile.txt") LPRINT mystring 'prints entire file MyVar = RETFUNC 'optionally retrieve number of bytes sent to lpt1 If LPRINT is used, HotBasic internal variable hbPrinter = port IO handle. Note: LPRINT supported in PentHouse registered version. OUT addr, integer; write byte value integer to I/O port address. OUTW addr, integer; write word value integer to I/O port address. Note: OUT and OUTW are not used for recent Windows versions. POPUP integer + displays popup menu where integer is a POPUPMENU handle. POPUP MyPopUpMenu.handle 'POPUPMENU is an alias for MAINMENU POPUP may show a POPUPMENU under program control or in GUI event procedures, as response to user input or other event (hotpopup.bas). POPUP menus may be placed under any FORM object (e.g., EDIT, LABEL) except FORM itself, in which case, it is rendered as a form menu bar. RANDOMIZE integer; sets RND function seed value; e.g., RANDOMIZE TIMER To regenerate the same pseudo-random number sequence repeatedly, use a constant argument: e.g., RANDOMIZE 100 REDIM array(subscripts); redefine subscript usage and/or size of an array. Decreasing overall array size will not erase previous data or reduce its ram allocation. Array item size or type cannot be changed. DIM dat(99) As LONG 'code REDIM dat(9,19) For FORM objects, REDIM will not destroy, recreate or create additional objects if overall array size is changed. If a FORM object array size is increased, REDIMEX (Statements > Advanced Techniques) is used after REDIM to initialize the new array items. RUN {command line string}; with executable pathname and optional arguments; does not block application. SHELL {command line string}; with executable pathname and optional arguments; blocks application while shelled program runs. If pipe symbols are used in string, then "command.com /c" or "cmd.exe /c" may have to be added as a prefix to the command line string. The VERSION object may be used to determine which prefix to use. SHELL1 {command line string}; with executable pathname and optional arguments; same as SHELL but starts executable at a higher priority level. Use for CPU-instensive child processes, such as a compiler or linker, but not for GUI apps, which can cause problems if run at a higher CPU priority. Application.ErrorLevel after SHELL/SHELL1 retrieves error level value. SHELL and SHELL1 may also be used as Numeric Functions to retrieve error level. E.g., ErrLvl = SHELL "myprog" 'ErrLvl gets exit code of myprog SHOWCONSOLE Please see description in CONSOLE section. SHOWMESSAGE {single or multi-line message string} SHOWMESSAGE "Star on your chart for using this application" SLEEP number number is seconds with millisecond resolution; suspends application. Use SLEEP to save CPU time if application is waiting for an input or event. SLEEP 0.05 '50 milliseconds for 20/second frame rate. SWAP MyVar1, MyVar2; exchanges values for 2 or 4 byte variables. MyVars should be the same size: WORD, SHORT, SINGLE, DWORD, LONG, INTEGER THIS + THIS facilitates access to UDT/Custom Objects by pointer. With THIS syntax, code blocks may process data from different Objects. Example: $apptype console TYPE MyUDT item1 as LONG item2 as LONG END MyUDT DECLARE SUB ProcessData (x as LONG, y as LONG) SUB ProcessData this.item1 = x this.item2 = y print this.item1 + this.item2 END SUB DIM abc as MyUDT DIM xyz as MyUDT THIS = abc: ProcessData (10, 20) THIS = xyz: ProcessData (30, 40) pause end Notice that the SUB code block using this.SomeProperty syntax appears after the UDT to which THIS will refer. Thus, at compile-time, the proper offsets to .item1 and .item2 will be used. At run-time, the SUB will use the pointer obtained from a THIS = statement. THIS syntax is based on the BYREF() and BYREF$() keywords and has the same limitations, such as 8-byte numbers are not supported. HotBasic internal variable hbThis is associated with THIS syntax. E.g., THIS = abc results in two actions: (1) hbThis = OBJPTR(abc) and (2) code using this.SomeProperty will use MyUDT item offsets. THIS = NOTHING 'set THIS to undefined state If THIS is used for multiple UDT's, it is suggested that procedures using THIS to refer to a particular UDT be located after its TYPE ... END TYPE block and before the next TYPE ... END TYPE block. Alternatively, one can force a code block using this.SomeProperty to compile with proper offsets by preceding it with a THIS = even where such statement is never executed at run-time. The Commander Keene download shows an example of THIS usage. WITH {object or type name} WITH FPU: .load x: .load y: .mul: END WITH WITH may be used with destination values located first in a statement or preceding an "=" character. That is, source values are not referenced using WITH syntax. + Penthouse (registered) version Copyright 2003-2012 James J Keene PhD Original Publication: Oct 8, 2003