_TITLE "QB64"

'$DYNAMIC
DEFLNG A-Z

DIM SHARED os AS STRING
os$ = "WIN" 'use "LNX" under Linux

dim shared extension as string
extension$=".exe"
IF os$ = "LNX" THEN extension$="" 'no extension under Linux

DIM SHARED pathsep AS STRING * 1
pathsep$ = "\"
IF os$ = "LNX" THEN pathsep$ = "/"
'note: QB64 handles OS specific path separators automatically except under SHELL calls

ON ERROR GOTO qberror_test

DIM SHARED tmpdir AS STRING, tmpdir2 AS STRING
IF os$ = "WIN" THEN tmpdir$ = ".\internal\temp\": tmpdir2$ = "..\\temp\\"
IF os$ = "LNX" THEN tmpdir$ = "./internal/temp/": tmpdir2$ = "../temp/"

DIM SHARED tempfolderindex
e = 0
i = 1
OPEN tmpdir$ + "temp.bin" FOR OUTPUT LOCK READ WRITE AS #26
DO WHILE e
    i = i + 1
    IF i = 1000 THEN PRINT "Unable to locate the 'internal' folder": END
    MKDIR ".\internal\temp" + str2$(i)
    IF os$ = "WIN" THEN tmpdir$ = ".\internal\temp" + str2$(i) + "\":tmpdir2$ = "..\\temp" + str2$(i) + "\\"
    IF os$ = "LNX" THEN tmpdir$ = "./internal/temp" + str2$(i) + "/":tmpdir2$ = "../temp" + str2$(i) + "/"
    e = 0
    OPEN tmpdir$ + "temp.bin" FOR OUTPUT LOCK READ WRITE AS #26
LOOP
'temp folder established
tempfolderindex = i
IF i > 1 THEN
    'create modified version of qbx.cpp
    OPEN ".\internal\c\qbx" + str2$(i) + ".cpp" FOR OUTPUT AS #2
    OPEN ".\internal\c\qbx.cpp" FOR INPUT AS #1
    DO UNTIL EOF(1)
        LINE INPUT #1, a$
        x = INSTR(a$, "..\\temp\\"): IF x THEN a$ = LEFT$(a$, x - 1) + "..\\temp" + str2$(i) + "\\" + RIGHT$(a$, LEN(a$) - (x + 9))
        x = INSTR(a$, "../temp/"): IF x THEN a$ = LEFT$(a$, x - 1) + "../temp" + str2$(i) + "/" + RIGHT$(a$, LEN(a$) - (x + 7))
        PRINT #2, a$
    LOOP
    CLOSE #1, #2
END IF
ON ERROR GOTO qberror

DIM SHARED tempfolderindexstr AS STRING 'appended to "Untitled"
DIM SHARED tempfolderindexstr2 AS STRING
IF tempfolderindex <> 1 THEN tempfolderindexstr$ = "(" + str2$(tempfolderindex) + ")": tempfolderindexstr2$ = str2$(tempfolderindex)

dim shared control_chr(255) as integer
control_chr(7)=1
control_chr(9)=1
control_chr(10)=1
control_chr(11)=1
control_chr(12)=1
control_chr(13)=1
control_chr(26)=1
control_chr(28)=1
control_chr(29)=1
control_chr(30)=1
control_chr(31)=1

DIM SHARED crlf AS STRING
crlf = CHR$(13) + CHR$(10)

DIM SHARED chr_tab as string
chr_tab=chr$(9)

dim shared compfailed

'setup optional codepages
dim shared idecpindex
const idecpnum& = 26
dim shared idecpname(1 to idecpnum) as string
dim shared idecp(1 to idecpnum) as string
'
idecpname$(1)="micsft_pc_cp437"
idecp$(1)="000000000000000100000002000000030000000400000005000000060000000700000008000000090000000A0000000B0000000C0000000D0000000E0000000F000000100000001100000012000000130000001400000015000000160000001700000018000000190000001A0000001B0000001C0000001D0000001E0000001F000000200000002100000022000000230000002400000025000000260000002700000028000000290000002A0000002B0000002C0000002D0000002E0000002F000000300000003100000032000000330000003400000035000000360000003700000038000000390000003A0000003B0000003C0000003D0000003E0000003F000000400000004100000042000000430000004400000045000000460000004700000048000000490000004A0000004B0000004C0000004D0000004E0000004F000000500000005100000052000000530000005400000055000000560000005700000058000000590000005A0000005B0000005C0000005D0000005E0000005F000000600000006100000062000000630000006400000065000000660000006700000068000000690000006A0000006B0000006C0000006D0000006E0000006F000000700000007100000072000000730000007400000075000000760000007700000078000000790000007A0000007B0000007C0000007D0000007E0000007F000000C7000000FC000000E9000000E2000000E4000000E0000000E5000000E7000000EA000000EB000000E8000000EF000000EE000000EC000000C4000000C5000000C9000000E6000000C6000000F4000000F6000000F2000000FB000000F9000000FF000000D6000000DC000000A2000000A3000000A5000020A700000192000000E1000000ED000000F3000000FA000000F1000000D1000000AA000000BA000000BF00002310000000AC000000BD000000BC000000A1000000AB000000BB0000259100002592000025930000250200002524000025610000256200002556000025550000256300002551000025570000255D0000255C0000255B0000251000002514000025340000252C0000251C000025000000253C0000255E0000255F0000255A00002554000025690000256600002560000025500000256C00002567000025680000256400002565000025590000255800002552000025530000256B0000256A000025180000250C00002588000025840000258C0000259000002580000003B1000000DF00000393000003C0000003A3000003C3000000B5000003C4000003A600000398000003A9000003B40000221E000003C6000003B50000222900002261000000B100002265000022640000232000002321000000F700002248000000B000002219000000B70000221A0000207F000000B2000025A0000000A0"
idecpname$(2)="micsft_pc_cp737"
idecp$(2)="000000000000000100000002000000030000000400000005000000060000000700000008000000090000000A0000000B0000000C0000000D0000000E0000000F000000100000001100000012000000130000001400000015000000160000001700000018000000190000001A0000001B0000001C0000001D0000001E0000001F000000200000002100000022000000230000002400000025000000260000002700000028000000290000002A0000002B0000002C0000002D0000002E0000002F000000300000003100000032000000330000003400000035000000360000003700000038000000390000003A0000003B0000003C0000003D0000003E0000003F000000400000004100000042000000430000004400000045000000460000004700000048000000490000004A0000004B0000004C0000004D0000004E0000004F000000500000005100000052000000530000005400000055000000560000005700000058000000590000005A0000005B0000005C0000005D0000005E0000005F000000600000006100000062000000630000006400000065000000660000006700000068000000690000006A0000006B0000006C0000006D0000006E0000006F000000700000007100000072000000730000007400000075000000760000007700000078000000790000007A0000007B0000007C0000007D0000007E0000007F0000039100000392000003930000039400000395000003960000039700000398000003990000039A0000039B0000039C0000039D0000039E0000039F000003A0000003A1000003A3000003A4000003A5000003A6000003A7000003A8000003A9000003B1000003B2000003B3000003B4000003B5000003B6000003B7000003B8000003B9000003BA000003BB000003BC000003BD000003BE000003BF000003C0000003C1000003C3000003C2000003C4000003C5000003C6000003C7000003C80000259100002592000025930000250200002524000025610000256200002556000025550000256300002551000025570000255D0000255C0000255B0000251000002514000025340000252C0000251C000025000000253C0000255E0000255F0000255A00002554000025690000256600002560000025500000256C00002567000025680000256400002565000025590000255800002552000025530000256B0000256A000025180000250C00002588000025840000258C0000259000002580000003C9000003AC000003AD000003AE000003CA000003AF000003CC000003CD000003CB000003CE0000038600000388000003890000038A0000038C0000038E0000038F000000B10000226500002264000003AA000003AB000000F700002248000000B000002219000000B70000221A0000207F000000B2000025A0000000A0"
idecpname$(3)="micsft_pc_cp775"
idecp$(3)="000000000000000100000002000000030000000400000005000000060000000700000008000000090000000A0000000B0000000C0000000D0000000E0000000F000000100000001100000012000000130000001400000015000000160000001700000018000000190000001A0000001B0000001C0000001D0000001E0000001F000000200000002100000022000000230000002400000025000000260000002700000028000000290000002A0000002B0000002C0000002D0000002E0000002F000000300000003100000032000000330000003400000035000000360000003700000038000000390000003A0000003B0000003C0000003D0000003E0000003F000000400000004100000042000000430000004400000045000000460000004700000048000000490000004A0000004B0000004C0000004D0000004E0000004F000000500000005100000052000000530000005400000055000000560000005700000058000000590000005A0000005B0000005C0000005D0000005E0000005F000000600000006100000062000000630000006400000065000000660000006700000068000000690000006A0000006B0000006C0000006D0000006E0000006F000000700000007100000072000000730000007400000075000000760000007700000078000000790000007A0000007B0000007C0000007D0000007E0000007F00000106000000FC000000E900000101000000E400000123000000E500000107000001420000011300000156000001570000012B00000179000000C4000000C5000000C9000000E6000000C60000014D000000F600000122000000A20000015A0000015B000000D6000000DC000000F8000000A3000000D8000000D7000000A4000001000000012A000000F30000017B0000017C0000017A0000201D000000A6000000A9000000AE000000AC000000BD000000BC00000141000000AB000000BB0000259100002592000025930000250200002524000001040000010C00000118000001160000256300002551000025570000255D0000012E000001600000251000002514000025340000252C0000251C000025000000253C000001720000016A0000255A00002554000025690000256600002560000025500000256C0000017D000001050000010D00000119000001170000012F00000161000001730000016B0000017E000025180000250C00002588000025840000258C0000259000002580000000D3000000DF0000014C00000143000000F5000000D5000000B50000014400000136000001370000013B0000013C00000146000001120000014500002019000000AD000000B10000201C000000BE000000B6000000A7000000F70000201E000000B000002219000000B7000000B9000000B3000000B2000025A0000000A0"
idecpname$(4)="micsft_pc_cp850"
idecp$(4)="000000000000000100000002000000030000000400000005000000060000000700000008000000090000000A0000000B0000000C0000000D0000000E0000000F000000100000001100000012000000130000001400000015000000160000001700000018000000190000001A0000001B0000001C0000001D0000001E0000001F000000200000002100000022000000230000002400000025000000260000002700000028000000290000002A0000002B0000002C0000002D0000002E0000002F000000300000003100000032000000330000003400000035000000360000003700000038000000390000003A0000003B0000003C0000003D0000003E0000003F000000400000004100000042000000430000004400000045000000460000004700000048000000490000004A0000004B0000004C0000004D0000004E0000004F000000500000005100000052000000530000005400000055000000560000005700000058000000590000005A0000005B0000005C0000005D0000005E0000005F000000600000006100000062000000630000006400000065000000660000006700000068000000690000006A0000006B0000006C0000006D0000006E0000006F000000700000007100000072000000730000007400000075000000760000007700000078000000790000007A0000007B0000007C0000007D0000007E0000007F000000C7000000FC000000E9000000E2000000E4000000E0000000E5000000E7000000EA000000EB000000E8000000EF000000EE000000EC000000C4000000C5000000C9000000E6000000C6000000F4000000F6000000F2000000FB000000F9000000FF000000D6000000DC000000F8000000A3000000D8000000D700000192000000E1000000ED000000F3000000FA000000F1000000D1000000AA000000BA000000BF000000AE000000AC000000BD000000BC000000A1000000AB000000BB0000259100002592000025930000250200002524000000C1000000C2000000C0000000A90000256300002551000025570000255D000000A2000000A50000251000002514000025340000252C0000251C000025000000253C000000E3000000C30000255A00002554000025690000256600002560000025500000256C000000A4000000F0000000D0000000CA000000CB000000C800000131000000CD000000CE000000CF000025180000250C0000258800002584000000A6000000CC00002580000000D3000000DF000000D4000000D2000000F5000000D5000000B5000000FE000000DE000000DA000000DB000000D9000000FD000000DD000000AF000000B4000000AD000000B100002017000000BE000000B6000000A7000000F7000000B8000000B0000000A8000000B7000000B9000000B3000000B2000025A0000000A0"
idecpname$(5)="micsft_pc_cp852"
idecp$(5)="000000000000000100000002000000030000000400000005000000060000000700000008000000090000000A0000000B0000000C0000000D0000000E0000000F000000100000001100000012000000130000001400000015000000160000001700000018000000190000001A0000001B0000001C0000001D0000001E0000001F000000200000002100000022000000230000002400000025000000260000002700000028000000290000002A0000002B0000002C0000002D0000002E0000002F000000300000003100000032000000330000003400000035000000360000003700000038000000390000003A0000003B0000003C0000003D0000003E0000003F000000400000004100000042000000430000004400000045000000460000004700000048000000490000004A0000004B0000004C0000004D0000004E0000004F000000500000005100000052000000530000005400000055000000560000005700000058000000590000005A0000005B0000005C0000005D0000005E0000005F000000600000006100000062000000630000006400000065000000660000006700000068000000690000006A0000006B0000006C0000006D0000006E0000006F000000700000007100000072000000730000007400000075000000760000007700000078000000790000007A0000007B0000007C0000007D0000007E0000007F000000C7000000FC000000E9000000E2000000E40000016F00000107000000E700000142000000EB0000015000000151000000EE00000179000000C400000106000000C9000001390000013A000000F4000000F60000013D0000013E0000015A0000015B000000D6000000DC000001640000016500000141000000D70000010D000000E1000000ED000000F3000000FA00000104000001050000017D0000017E0000011800000119000000AC0000017A0000010C0000015F000000AB000000BB0000259100002592000025930000250200002524000000C1000000C20000011A0000015E0000256300002551000025570000255D0000017B0000017C0000251000002514000025340000252C0000251C000025000000253C00000102000001030000255A00002554000025690000256600002560000025500000256C000000A400000111000001100000010E000000CB0000010F00000147000000CD000000CE0000011B000025180000250C0000258800002584000001620000016E00002580000000D3000000DF000000D4000001430000014400000148000001600000016100000154000000DA0000015500000170000000FD000000DD00000163000000B4000000AD000002DD000002DB000002C7000002D8000000A7000000F7000000B8000000B0000000A8000002D9000001710000015800000159000025A0000000A0"
idecpname$(6)="micsft_pc_cp855"
idecp$(6)="000000000000000100000002000000030000000400000005000000060000000700000008000000090000000A0000000B0000000C0000000D0000000E0000000F000000100000001100000012000000130000001400000015000000160000001700000018000000190000001A0000001B0000001C0000001D0000001E0000001F000000200000002100000022000000230000002400000025000000260000002700000028000000290000002A0000002B0000002C0000002D0000002E0000002F000000300000003100000032000000330000003400000035000000360000003700000038000000390000003A0000003B0000003C0000003D0000003E0000003F000000400000004100000042000000430000004400000045000000460000004700000048000000490000004A0000004B0000004C0000004D0000004E0000004F000000500000005100000052000000530000005400000055000000560000005700000058000000590000005A0000005B0000005C0000005D0000005E0000005F000000600000006100000062000000630000006400000065000000660000006700000068000000690000006A0000006B0000006C0000006D0000006E0000006F000000700000007100000072000000730000007400000075000000760000007700000078000000790000007A0000007B0000007C0000007D0000007E0000007F0000045200000402000004530000040300000451000004010000045400000404000004550000040500000456000004060000045700000407000004580000040800000459000004090000045A0000040A0000045B0000040B0000045C0000040C0000045E0000040E0000045F0000040F0000044E0000042E0000044A0000042A0000043000000410000004310000041100000446000004260000043400000414000004350000041500000444000004240000043300000413000000AB000000BB0000259100002592000025930000250200002524000004450000042500000438000004180000256300002551000025570000255D00000439000004190000251000002514000025340000252C0000251C000025000000253C0000043A0000041A0000255A00002554000025690000256600002560000025500000256C000000A40000043B0000041B0000043C0000041C0000043D0000041D0000043E0000041E0000043F000025180000250C00002588000025840000041F0000044F000025800000042F0000044000000420000004410000042100000442000004220000044300000423000004360000041600000432000004120000044C0000042C00002116000000AD0000044B0000042B000004370000041700000448000004280000044D0000042D00000449000004290000044700000427000000A7000025A0000000A0"
idecpname$(7)="micsft_pc_cp857"
idecp$(7)="000000000000000100000002000000030000000400000005000000060000000700000008000000090000000A0000000B0000000C0000000D0000000E0000000F000000100000001100000012000000130000001400000015000000160000001700000018000000190000001A0000001B0000001C0000001D0000001E0000001F000000200000002100000022000000230000002400000025000000260000002700000028000000290000002A0000002B0000002C0000002D0000002E0000002F000000300000003100000032000000330000003400000035000000360000003700000038000000390000003A0000003B0000003C0000003D0000003E0000003F000000400000004100000042000000430000004400000045000000460000004700000048000000490000004A0000004B0000004C0000004D0000004E0000004F000000500000005100000052000000530000005400000055000000560000005700000058000000590000005A0000005B0000005C0000005D0000005E0000005F000000600000006100000062000000630000006400000065000000660000006700000068000000690000006A0000006B0000006C0000006D0000006E0000006F000000700000007100000072000000730000007400000075000000760000007700000078000000790000007A0000007B0000007C0000007D0000007E0000007F000000C7000000FC000000E9000000E2000000E4000000E0000000E5000000E7000000EA000000EB000000E8000000EF000000EE00000131000000C4000000C5000000C9000000E6000000C6000000F4000000F6000000F2000000FB000000F900000130000000D6000000DC000000F8000000A3000000D80000015E0000015F000000E1000000ED000000F3000000FA000000F1000000D10000011E0000011F000000BF000000AE000000AC000000BD000000BC000000A1000000AB000000BB0000259100002592000025930000250200002524000000C1000000C2000000C0000000A90000256300002551000025570000255D000000A2000000A50000251000002514000025340000252C0000251C000025000000253C000000E3000000C30000255A00002554000025690000256600002560000025500000256C000000A4000000BA000000AA000000CA000000CB000000C800000000000000CD000000CE000000CF000025180000250C0000258800002584000000A6000000CC00002580000000D3000000DF000000D4000000D2000000F5000000D5000000B500000000000000D7000000DA000000DB000000D9000000EC000000FF000000AF000000B4000000AD000000B100000000000000BE000000B6000000A7000000F7000000B8000000B0000000A8000000B7000000B9000000B3000000B2000025A0000000A0"
idecpname$(8)="micsft_pc_cp860"
idecp$(8)="000000000000000100000002000000030000000400000005000000060000000700000008000000090000000A0000000B0000000C0000000D0000000E0000000F000000100000001100000012000000130000001400000015000000160000001700000018000000190000001A0000001B0000001C0000001D0000001E0000001F000000200000002100000022000000230000002400000025000000260000002700000028000000290000002A0000002B0000002C0000002D0000002E0000002F000000300000003100000032000000330000003400000035000000360000003700000038000000390000003A0000003B0000003C0000003D0000003E0000003F000000400000004100000042000000430000004400000045000000460000004700000048000000490000004A0000004B0000004C0000004D0000004E0000004F000000500000005100000052000000530000005400000055000000560000005700000058000000590000005A0000005B0000005C0000005D0000005E0000005F000000600000006100000062000000630000006400000065000000660000006700000068000000690000006A0000006B0000006C0000006D0000006E0000006F000000700000007100000072000000730000007400000075000000760000007700000078000000790000007A0000007B0000007C0000007D0000007E0000007F000000C7000000FC000000E9000000E2000000E3000000E0000000C1000000E7000000EA000000CA000000E8000000CD000000D4000000EC000000C3000000C2000000C9000000C0000000C8000000F4000000F5000000F2000000DA000000F9000000CC000000D5000000DC000000A2000000A3000000D9000020A7000000D3000000E1000000ED000000F3000000FA000000F1000000D1000000AA000000BA000000BF000000D2000000AC000000BD000000BC000000A1000000AB000000BB0000259100002592000025930000250200002524000025610000256200002556000025550000256300002551000025570000255D0000255C0000255B0000251000002514000025340000252C0000251C000025000000253C0000255E0000255F0000255A00002554000025690000256600002560000025500000256C00002567000025680000256400002565000025590000255800002552000025530000256B0000256A000025180000250C00002588000025840000258C0000259000002580000003B1000000DF00000393000003C0000003A3000003C3000000B5000003C4000003A600000398000003A9000003B40000221E000003C6000003B50000222900002261000000B100002265000022640000232000002321000000F700002248000000B000002219000000B70000221A0000207F000000B2000025A0000000A0"
idecpname$(9)="micsft_pc_cp861"
idecp$(9)="000000000000000100000002000000030000000400000005000000060000000700000008000000090000000A0000000B0000000C0000000D0000000E0000000F000000100000001100000012000000130000001400000015000000160000001700000018000000190000001A0000001B0000001C0000001D0000001E0000001F000000200000002100000022000000230000002400000025000000260000002700000028000000290000002A0000002B0000002C0000002D0000002E0000002F000000300000003100000032000000330000003400000035000000360000003700000038000000390000003A0000003B0000003C0000003D0000003E0000003F000000400000004100000042000000430000004400000045000000460000004700000048000000490000004A0000004B0000004C0000004D0000004E0000004F000000500000005100000052000000530000005400000055000000560000005700000058000000590000005A0000005B0000005C0000005D0000005E0000005F000000600000006100000062000000630000006400000065000000660000006700000068000000690000006A0000006B0000006C0000006D0000006E0000006F000000700000007100000072000000730000007400000075000000760000007700000078000000790000007A0000007B0000007C0000007D0000007E0000007F000000C7000000FC000000E9000000E2000000E4000000E0000000E5000000E7000000EA000000EB000000E8000000D0000000F0000000DE000000C4000000C5000000C9000000E6000000C6000000F4000000F6000000FE000000FB000000DD000000FD000000D6000000DC000000F8000000A3000000D8000020A700000192000000E1000000ED000000F3000000FA000000C1000000CD000000D3000000DA000000BF00002310000000AC000000BD000000BC000000A1000000AB000000BB0000259100002592000025930000250200002524000025610000256200002556000025550000256300002551000025570000255D0000255C0000255B0000251000002514000025340000252C0000251C000025000000253C0000255E0000255F0000255A00002554000025690000256600002560000025500000256C00002567000025680000256400002565000025590000255800002552000025530000256B0000256A000025180000250C00002588000025840000258C0000259000002580000003B1000000DF00000393000003C0000003A3000003C3000000B5000003C4000003A600000398000003A9000003B40000221E000003C6000003B50000222900002261000000B100002265000022640000232000002321000000F700002248000000B000002219000000B70000221A0000207F000000B2000025A0000000A0"
idecpname$(10)="micsft_pc_cp862"
idecp$(10)="000000000000000100000002000000030000000400000005000000060000000700000008000000090000000A0000000B0000000C0000000D0000000E0000000F000000100000001100000012000000130000001400000015000000160000001700000018000000190000001A0000001B0000001C0000001D0000001E0000001F000000200000002100000022000000230000002400000025000000260000002700000028000000290000002A0000002B0000002C0000002D0000002E0000002F000000300000003100000032000000330000003400000035000000360000003700000038000000390000003A0000003B0000003C0000003D0000003E0000003F000000400000004100000042000000430000004400000045000000460000004700000048000000490000004A0000004B0000004C0000004D0000004E0000004F000000500000005100000052000000530000005400000055000000560000005700000058000000590000005A0000005B0000005C0000005D0000005E0000005F000000600000006100000062000000630000006400000065000000660000006700000068000000690000006A0000006B0000006C0000006D0000006E0000006F000000700000007100000072000000730000007400000075000000760000007700000078000000790000007A0000007B0000007C0000007D0000007E0000007F000005D0000005D1000005D2000005D3000005D4000005D5000005D6000005D7000005D8000005D9000005DA000005DB000005DC000005DD000005DE000005DF000005E0000005E1000005E2000005E3000005E4000005E5000005E6000005E7000005E8000005E9000005EA000000A2000000A3000000A5000020A700000192000000E1000000ED000000F3000000FA000000F1000000D1000000AA000000BA000000BF00002310000000AC000000BD000000BC000000A1000000AB000000BB0000259100002592000025930000250200002524000025610000256200002556000025550000256300002551000025570000255D0000255C0000255B0000251000002514000025340000252C0000251C000025000000253C0000255E0000255F0000255A00002554000025690000256600002560000025500000256C00002567000025680000256400002565000025590000255800002552000025530000256B0000256A000025180000250C00002588000025840000258C0000259000002580000003B1000000DF00000393000003C0000003A3000003C3000000B5000003C4000003A600000398000003A9000003B40000221E000003C6000003B50000222900002261000000B100002265000022640000232000002321000000F700002248000000B000002219000000B70000221A0000207F000000B2000025A0000000A0"
idecpname$(11)="micsft_pc_cp863"
idecp$(11)="000000000000000100000002000000030000000400000005000000060000000700000008000000090000000A0000000B0000000C0000000D0000000E0000000F000000100000001100000012000000130000001400000015000000160000001700000018000000190000001A0000001B0000001C0000001D0000001E0000001F000000200000002100000022000000230000002400000025000000260000002700000028000000290000002A0000002B0000002C0000002D0000002E0000002F000000300000003100000032000000330000003400000035000000360000003700000038000000390000003A0000003B0000003C0000003D0000003E0000003F000000400000004100000042000000430000004400000045000000460000004700000048000000490000004A0000004B0000004C0000004D0000004E0000004F000000500000005100000052000000530000005400000055000000560000005700000058000000590000005A0000005B0000005C0000005D0000005E0000005F000000600000006100000062000000630000006400000065000000660000006700000068000000690000006A0000006B0000006C0000006D0000006E0000006F000000700000007100000072000000730000007400000075000000760000007700000078000000790000007A0000007B0000007C0000007D0000007E0000007F000000C7000000FC000000E9000000E2000000C2000000E0000000B6000000E7000000EA000000EB000000E8000000EF000000EE00002017000000C0000000A7000000C9000000C8000000CA000000F4000000CB000000CF000000FB000000F9000000A4000000D4000000DC000000A2000000A3000000D9000000DB00000192000000A6000000B4000000F3000000FA000000A8000000B8000000B3000000AF000000CE00002310000000AC000000BD000000BC000000BE000000AB000000BB0000259100002592000025930000250200002524000025610000256200002556000025550000256300002551000025570000255D0000255C0000255B0000251000002514000025340000252C0000251C000025000000253C0000255E0000255F0000255A00002554000025690000256600002560000025500000256C00002567000025680000256400002565000025590000255800002552000025530000256B0000256A000025180000250C00002588000025840000258C0000259000002580000003B1000000DF00000393000003C0000003A3000003C3000000B5000003C4000003A600000398000003A9000003B40000221E000003C6000003B50000222900002261000000B100002265000022640000232000002321000000F700002248000000B000002219000000B70000221A0000207F000000B2000025A0000000A0"
idecpname$(12)="micsft_pc_cp864"
idecp$(12)="000000000000000100000002000000030000000400000005000000060000000700000008000000090000000A0000000B0000000C0000000D0000000E0000000F000000100000001100000012000000130000001400000015000000160000001700000018000000190000001A0000001B0000001C0000001D0000001E0000001F00000020000000210000002200000023000000240000066A000000260000002700000028000000290000002A0000002B0000002C0000002D0000002E0000002F000000300000003100000032000000330000003400000035000000360000003700000038000000390000003A0000003B0000003C0000003D0000003E0000003F000000400000004100000042000000430000004400000045000000460000004700000048000000490000004A0000004B0000004C0000004D0000004E0000004F000000500000005100000052000000530000005400000055000000560000005700000058000000590000005A0000005B0000005C0000005D0000005E0000005F000000600000006100000062000000630000006400000065000000660000006700000068000000690000006A0000006B0000006C0000006D0000006E0000006F000000700000007100000072000000730000007400000075000000760000007700000078000000790000007A0000007B0000007C0000007D0000007E0000007F000000B0000000B7000022190000221A0000259200002500000025020000253C000025240000252C0000251C00002534000025100000250C0000251400002518000003B20000221E000003C6000000B1000000BD000000BC00002248000000AB000000BB0000FEF70000FEF800000000000000000000FEFB0000FEFC00000000000000A0000000AD0000FE82000000A3000000A40000FE8400000000000000000000FE8E0000FE8F0000FE950000FE990000060C0000FE9D0000FEA10000FEA5000006600000066100000662000006630000066400000665000006660000066700000668000006690000FED10000061B0000FEB10000FEB50000FEB90000061F000000A20000FE800000FE810000FE830000FE850000FECA0000FE8B0000FE8D0000FE910000FE930000FE970000FE9B0000FE9F0000FEA30000FEA70000FEA90000FEAB0000FEAD0000FEAF0000FEB30000FEB70000FEBB0000FEBF0000FEC10000FEC50000FECB0000FECF000000A6000000AC000000F7000000D70000FEC9000006400000FED30000FED70000FEDB0000FEDF0000FEE30000FEE70000FEEB0000FEED0000FEEF0000FEF30000FEBD0000FECC0000FECE0000FECD0000FEE10000FE7D000006510000FEE50000FEE90000FEEC0000FEF00000FEF20000FED00000FED50000FEF50000FEF60000FEDD0000FED90000FEF1000025A000000000"
idecpname$(13)="micsft_pc_cp865"
idecp$(13)="000000000000000100000002000000030000000400000005000000060000000700000008000000090000000A0000000B0000000C0000000D0000000E0000000F000000100000001100000012000000130000001400000015000000160000001700000018000000190000001A0000001B0000001C0000001D0000001E0000001F000000200000002100000022000000230000002400000025000000260000002700000028000000290000002A0000002B0000002C0000002D0000002E0000002F000000300000003100000032000000330000003400000035000000360000003700000038000000390000003A0000003B0000003C0000003D0000003E0000003F000000400000004100000042000000430000004400000045000000460000004700000048000000490000004A0000004B0000004C0000004D0000004E0000004F000000500000005100000052000000530000005400000055000000560000005700000058000000590000005A0000005B0000005C0000005D0000005E0000005F000000600000006100000062000000630000006400000065000000660000006700000068000000690000006A0000006B0000006C0000006D0000006E0000006F000000700000007100000072000000730000007400000075000000760000007700000078000000790000007A0000007B0000007C0000007D0000007E0000007F000000C7000000FC000000E9000000E2000000E4000000E0000000E5000000E7000000EA000000EB000000E8000000EF000000EE000000EC000000C4000000C5000000C9000000E6000000C6000000F4000000F6000000F2000000FB000000F9000000FF000000D6000000DC000000F8000000A3000000D8000020A700000192000000E1000000ED000000F3000000FA000000F1000000D1000000AA000000BA000000BF00002310000000AC000000BD000000BC000000A1000000AB000000A40000259100002592000025930000250200002524000025610000256200002556000025550000256300002551000025570000255D0000255C0000255B0000251000002514000025340000252C0000251C000025000000253C0000255E0000255F0000255A00002554000025690000256600002560000025500000256C00002567000025680000256400002565000025590000255800002552000025530000256B0000256A000025180000250C00002588000025840000258C0000259000002580000003B1000000DF00000393000003C0000003A3000003C3000000B5000003C4000003A600000398000003A9000003B40000221E000003C6000003B50000222900002261000000B100002265000022640000232000002321000000F700002248000000B000002219000000B70000221A0000207F000000B2000025A0000000A0"
idecpname$(14)="micsft_pc_cp866"
idecp$(14)="000000000000000100000002000000030000000400000005000000060000000700000008000000090000000A0000000B0000000C0000000D0000000E0000000F000000100000001100000012000000130000001400000015000000160000001700000018000000190000001A0000001B0000001C0000001D0000001E0000001F000000200000002100000022000000230000002400000025000000260000002700000028000000290000002A0000002B0000002C0000002D0000002E0000002F000000300000003100000032000000330000003400000035000000360000003700000038000000390000003A0000003B0000003C0000003D0000003E0000003F000000400000004100000042000000430000004400000045000000460000004700000048000000490000004A0000004B0000004C0000004D0000004E0000004F000000500000005100000052000000530000005400000055000000560000005700000058000000590000005A0000005B0000005C0000005D0000005E0000005F000000600000006100000062000000630000006400000065000000660000006700000068000000690000006A0000006B0000006C0000006D0000006E0000006F000000700000007100000072000000730000007400000075000000760000007700000078000000790000007A0000007B0000007C0000007D0000007E0000007F000004100000041100000412000004130000041400000415000004160000041700000418000004190000041A0000041B0000041C0000041D0000041E0000041F000004200000042100000422000004230000042400000425000004260000042700000428000004290000042A0000042B0000042C0000042D0000042E0000042F000004300000043100000432000004330000043400000435000004360000043700000438000004390000043A0000043B0000043C0000043D0000043E0000043F0000259100002592000025930000250200002524000025610000256200002556000025550000256300002551000025570000255D0000255C0000255B0000251000002514000025340000252C0000251C000025000000253C0000255E0000255F0000255A00002554000025690000256600002560000025500000256C00002567000025680000256400002565000025590000255800002552000025530000256B0000256A000025180000250C00002588000025840000258C0000259000002580000004400000044100000442000004430000044400000445000004460000044700000448000004490000044A0000044B0000044C0000044D0000044E0000044F0000040100000451000004040000045400000407000004570000040E0000045E000000B000002219000000B70000221A00002116000000A4000025A0000000A0"
idecpname$(15)="micsft_pc_cp869"
idecp$(15)="000000000000000100000002000000030000000400000005000000060000000700000008000000090000000A0000000B0000000C0000000D0000000E0000000F000000100000001100000012000000130000001400000015000000160000001700000018000000190000001A0000001B0000001C0000001D0000001E0000001F000000200000002100000022000000230000002400000025000000260000002700000028000000290000002A0000002B0000002C0000002D0000002E0000002F000000300000003100000032000000330000003400000035000000360000003700000038000000390000003A0000003B0000003C0000003D0000003E0000003F000000400000004100000042000000430000004400000045000000460000004700000048000000490000004A0000004B0000004C0000004D0000004E0000004F000000500000005100000052000000530000005400000055000000560000005700000058000000590000005A0000005B0000005C0000005D0000005E0000005F000000600000006100000062000000630000006400000065000000660000006700000068000000690000006A0000006B0000006C0000006D0000006E0000006F000000700000007100000072000000730000007400000075000000760000007700000078000000790000007A0000007B0000007C0000007D0000007E0000007F0000000000000000000000000000000000000000000000000000038600000000000000B7000000AC000000A600002018000020190000038800002015000003890000038A000003AA0000038C00000000000000000000038E000003AB000000A90000038F000000B2000000B3000003AC000000A3000003AD000003AE000003AF000003CA00000390000003CC000003CD00000391000003920000039300000394000003950000039600000397000000BD0000039800000399000000AB000000BB00002591000025920000259300002502000025240000039A0000039B0000039C0000039D0000256300002551000025570000255D0000039E0000039F0000251000002514000025340000252C0000251C000025000000253C000003A0000003A10000255A00002554000025690000256600002560000025500000256C000003A3000003A4000003A5000003A6000003A7000003A8000003A9000003B1000003B2000003B3000025180000250C0000258800002584000003B4000003B500002580000003B6000003B7000003B8000003B9000003BA000003BB000003BC000003BD000003BE000003BF000003C0000003C1000003C3000003C2000003C400000384000000AD000000B1000003C5000003C6000003C7000000A7000003C800000385000000B0000000A8000003C9000003CB000003B0000003CE000025A0000000A0"
idecpname$(16)="micsft_pc_cp874"
idecp$(16)="000000000000000100000002000000030000000400000005000000060000000700000008000000090000000A0000000B0000000C0000000D0000000E0000000F000000100000001100000012000000130000001400000015000000160000001700000018000000190000001A0000001B0000001C0000001D0000001E0000001F000000200000002100000022000000230000002400000025000000260000002700000028000000290000002A0000002B0000002C0000002D0000002E0000002F000000300000003100000032000000330000003400000035000000360000003700000038000000390000003A0000003B0000003C0000003D0000003E0000003F000000400000004100000042000000430000004400000045000000460000004700000048000000490000004A0000004B0000004C0000004D0000004E0000004F000000500000005100000052000000530000005400000055000000560000005700000058000000590000005A0000005B0000005C0000005D0000005E0000005F000000600000006100000062000000630000006400000065000000660000006700000068000000690000006A0000006B0000006C0000006D0000006E0000006F000000700000007100000072000000730000007400000075000000760000007700000078000000790000007A0000007B0000007C0000007D0000007E0000007F000020AC0000000000000000000000000000000000002026000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002018000020190000201C0000201D0000202200002013000020140000000000000000000000000000000000000000000000000000000000000000000000A000000E0100000E0200000E0300000E0400000E0500000E0600000E0700000E0800000E0900000E0A00000E0B00000E0C00000E0D00000E0E00000E0F00000E1000000E1100000E1200000E1300000E1400000E1500000E1600000E1700000E1800000E1900000E1A00000E1B00000E1C00000E1D00000E1E00000E1F00000E2000000E2100000E2200000E2300000E2400000E2500000E2600000E2700000E2800000E2900000E2A00000E2B00000E2C00000E2D00000E2E00000E2F00000E3000000E3100000E3200000E3300000E3400000E3500000E3600000E3700000E3800000E3900000E3A0000000000000000000000000000000000000E3F00000E4000000E4100000E4200000E4300000E4400000E4500000E4600000E4700000E4800000E4900000E4A00000E4B00000E4C00000E4D00000E4E00000E4F00000E5000000E5100000E5200000E5300000E5400000E5500000E5600000E5700000E5800000E5900000E5A00000E5B00000000000000000000000000000000"
idecpname$(17)="micsft_windows_cp1250"
idecp$(17)="000000000000000100000002000000030000000400000005000000060000000700000008000000090000000A0000000B0000000C0000000D0000000E0000000F000000100000001100000012000000130000001400000015000000160000001700000018000000190000001A0000001B0000001C0000001D0000001E0000001F000000200000002100000022000000230000002400000025000000260000002700000028000000290000002A0000002B0000002C0000002D0000002E0000002F000000300000003100000032000000330000003400000035000000360000003700000038000000390000003A0000003B0000003C0000003D0000003E0000003F000000400000004100000042000000430000004400000045000000460000004700000048000000490000004A0000004B0000004C0000004D0000004E0000004F000000500000005100000052000000530000005400000055000000560000005700000058000000590000005A0000005B0000005C0000005D0000005E0000005F000000600000006100000062000000630000006400000065000000660000006700000068000000690000006A0000006B0000006C0000006D0000006E0000006F000000700000007100000072000000730000007400000075000000760000007700000078000000790000007A0000007B0000007C0000007D0000007E0000007F000020AC000000000000201A000000000000201E000020260000202000002021000000000000203000000160000020390000015A000001640000017D000001790000000000002018000020190000201C0000201D0000202200002013000020140000000000002122000001610000203A0000015B000001650000017E0000017A000000A0000002C7000002D800000141000000A400000104000000A6000000A7000000A8000000A90000015E000000AB000000AC000000AD000000AE0000017B000000B0000000B1000002DB00000142000000B4000000B5000000B6000000B7000000B8000001050000015F000000BB0000013D000002DD0000013E0000017C00000154000000C1000000C200000102000000C40000013900000106000000C70000010C000000C900000118000000CB0000011A000000CD000000CE0000010E000001100000014300000147000000D3000000D400000150000000D6000000D7000001580000016E000000DA00000170000000DC000000DD00000162000000DF00000155000000E1000000E200000103000000E40000013A00000107000000E70000010D000000E900000119000000EB0000011B000000ED000000EE0000010F000001110000014400000148000000F3000000F400000151000000F6000000F7000001590000016F000000FA00000171000000FC000000FD00000163000002D9"
idecpname$(18)="micsft_windows_cp1251"
idecp$(18)="000000000000000100000002000000030000000400000005000000060000000700000008000000090000000A0000000B0000000C0000000D0000000E0000000F000000100000001100000012000000130000001400000015000000160000001700000018000000190000001A0000001B0000001C0000001D0000001E0000001F000000200000002100000022000000230000002400000025000000260000002700000028000000290000002A0000002B0000002C0000002D0000002E0000002F000000300000003100000032000000330000003400000035000000360000003700000038000000390000003A0000003B0000003C0000003D0000003E0000003F000000400000004100000042000000430000004400000045000000460000004700000048000000490000004A0000004B0000004C0000004D0000004E0000004F000000500000005100000052000000530000005400000055000000560000005700000058000000590000005A0000005B0000005C0000005D0000005E0000005F000000600000006100000062000000630000006400000065000000660000006700000068000000690000006A0000006B0000006C0000006D0000006E0000006F000000700000007100000072000000730000007400000075000000760000007700000078000000790000007A0000007B0000007C0000007D0000007E0000007F00000402000004030000201A000004530000201E000020260000202000002021000020AC0000203000000409000020390000040A0000040C0000040B0000040F0000045200002018000020190000201C0000201D0000202200002013000020140000000000002122000004590000203A0000045A0000045C0000045B0000045F000000A00000040E0000045E00000408000000A400000490000000A6000000A700000401000000A900000404000000AB000000AC000000AD000000AE00000407000000B0000000B1000004060000045600000491000000B5000000B6000000B7000004510000211600000454000000BB00000458000004050000045500000457000004100000041100000412000004130000041400000415000004160000041700000418000004190000041A0000041B0000041C0000041D0000041E0000041F000004200000042100000422000004230000042400000425000004260000042700000428000004290000042A0000042B0000042C0000042D0000042E0000042F000004300000043100000432000004330000043400000435000004360000043700000438000004390000043A0000043B0000043C0000043D0000043E0000043F000004400000044100000442000004430000044400000445000004460000044700000448000004490000044A0000044B0000044C0000044D0000044E0000044F"
idecpname$(19)="micsft_windows_cp1252"
idecp$(19)="000000000000000100000002000000030000000400000005000000060000000700000008000000090000000A0000000B0000000C0000000D0000000E0000000F000000100000001100000012000000130000001400000015000000160000001700000018000000190000001A0000001B0000001C0000001D0000001E0000001F000000200000002100000022000000230000002400000025000000260000002700000028000000290000002A0000002B0000002C0000002D0000002E0000002F000000300000003100000032000000330000003400000035000000360000003700000038000000390000003A0000003B0000003C0000003D0000003E0000003F000000400000004100000042000000430000004400000045000000460000004700000048000000490000004A0000004B0000004C0000004D0000004E0000004F000000500000005100000052000000530000005400000055000000560000005700000058000000590000005A0000005B0000005C0000005D0000005E0000005F000000600000006100000062000000630000006400000065000000660000006700000068000000690000006A0000006B0000006C0000006D0000006E0000006F000000700000007100000072000000730000007400000075000000760000007700000078000000790000007A0000007B0000007C0000007D0000007E0000007F000020AC000000000000201A000001920000201E000020260000202000002021000002C600002030000001600000203900000152000000000000017D000000000000000000002018000020190000201C0000201D000020220000201300002014000002DC00002122000001610000203A00000153000000000000017E00000178000000A0000000A1000000A2000000A3000000A4000000A5000000A6000000A7000000A8000000A9000000AA000000AB000000AC000000AD000000AE000000AF000000B0000000B1000000B2000000B3000000B4000000B5000000B6000000B7000000B8000000B9000000BA000000BB000000BC000000BD000000BE000000BF000000C0000000C1000000C2000000C3000000C4000000C5000000C6000000C7000000C8000000C9000000CA000000CB000000CC000000CD000000CE000000CF000000D0000000D1000000D2000000D3000000D4000000D5000000D6000000D7000000D8000000D9000000DA000000DB000000DC000000DD000000DE000000DF000000E0000000E1000000E2000000E3000000E4000000E5000000E6000000E7000000E8000000E9000000EA000000EB000000EC000000ED000000EE000000EF000000F0000000F1000000F2000000F3000000F4000000F5000000F6000000F7000000F8000000F9000000FA000000FB000000FC000000FD000000FE000000FF"
idecpname$(20)="micsft_windows_cp1253"
idecp$(20)="000000000000000100000002000000030000000400000005000000060000000700000008000000090000000A0000000B0000000C0000000D0000000E0000000F000000100000001100000012000000130000001400000015000000160000001700000018000000190000001A0000001B0000001C0000001D0000001E0000001F000000200000002100000022000000230000002400000025000000260000002700000028000000290000002A0000002B0000002C0000002D0000002E0000002F000000300000003100000032000000330000003400000035000000360000003700000038000000390000003A0000003B0000003C0000003D0000003E0000003F000000400000004100000042000000430000004400000045000000460000004700000048000000490000004A0000004B0000004C0000004D0000004E0000004F000000500000005100000052000000530000005400000055000000560000005700000058000000590000005A0000005B0000005C0000005D0000005E0000005F000000600000006100000062000000630000006400000065000000660000006700000068000000690000006A0000006B0000006C0000006D0000006E0000006F000000700000007100000072000000730000007400000075000000760000007700000078000000790000007A0000007B0000007C0000007D0000007E0000007F000020AC000000000000201A000001920000201E00002026000020200000202100000000000020300000000000002039000000000000000000000000000000000000000000002018000020190000201C0000201D0000202200002013000020140000000000002122000000000000203A00000000000000000000000000000000000000A00000038500000386000000A3000000A4000000A5000000A6000000A7000000A8000000A900000000000000AB000000AC000000AD000000AE00002015000000B0000000B1000000B2000000B300000384000000B5000000B6000000B700000388000003890000038A000000BB0000038C000000BD0000038E0000038F000003900000039100000392000003930000039400000395000003960000039700000398000003990000039A0000039B0000039C0000039D0000039E0000039F000003A0000003A100000000000003A3000003A4000003A5000003A6000003A7000003A8000003A9000003AA000003AB000003AC000003AD000003AE000003AF000003B0000003B1000003B2000003B3000003B4000003B5000003B6000003B7000003B8000003B9000003BA000003BB000003BC000003BD000003BE000003BF000003C0000003C1000003C2000003C3000003C4000003C5000003C6000003C7000003C8000003C9000003CA000003CB000003CC000003CD000003CE00000000"
idecpname$(21)="micsft_windows_cp1254"
idecp$(21)="000000000000000100000002000000030000000400000005000000060000000700000008000000090000000A0000000B0000000C0000000D0000000E0000000F000000100000001100000012000000130000001400000015000000160000001700000018000000190000001A0000001B0000001C0000001D0000001E0000001F000000200000002100000022000000230000002400000025000000260000002700000028000000290000002A0000002B0000002C0000002D0000002E0000002F000000300000003100000032000000330000003400000035000000360000003700000038000000390000003A0000003B0000003C0000003D0000003E0000003F000000400000004100000042000000430000004400000045000000460000004700000048000000490000004A0000004B0000004C0000004D0000004E0000004F000000500000005100000052000000530000005400000055000000560000005700000058000000590000005A0000005B0000005C0000005D0000005E0000005F000000600000006100000062000000630000006400000065000000660000006700000068000000690000006A0000006B0000006C0000006D0000006E0000006F000000700000007100000072000000730000007400000075000000760000007700000078000000790000007A0000007B0000007C0000007D0000007E0000007F000020AC000000000000201A000001920000201E000020260000202000002021000002C6000020300000016000002039000001520000000000000000000000000000000000002018000020190000201C0000201D000020220000201300002014000002DC00002122000001610000203A00000153000000000000000000000178000000A0000000A1000000A2000000A3000000A4000000A5000000A6000000A7000000A8000000A9000000AA000000AB000000AC000000AD000000AE000000AF000000B0000000B1000000B2000000B3000000B4000000B5000000B6000000B7000000B8000000B9000000BA000000BB000000BC000000BD000000BE000000BF000000C0000000C1000000C2000000C3000000C4000000C5000000C6000000C7000000C8000000C9000000CA000000CB000000CC000000CD000000CE000000CF0000011E000000D1000000D2000000D3000000D4000000D5000000D6000000D7000000D8000000D9000000DA000000DB000000DC000001300000015E000000DF000000E0000000E1000000E2000000E3000000E4000000E5000000E6000000E7000000E8000000E9000000EA000000EB000000EC000000ED000000EE000000EF0000011F000000F1000000F2000000F3000000F4000000F5000000F6000000F7000000F8000000F9000000FA000000FB000000FC000001310000015F000000FF"
idecpname$(22)="micsft_windows_cp1255"
idecp$(22)="000000000000000100000002000000030000000400000005000000060000000700000008000000090000000A0000000B0000000C0000000D0000000E0000000F000000100000001100000012000000130000001400000015000000160000001700000018000000190000001A0000001B0000001C0000001D0000001E0000001F000000200000002100000022000000230000002400000025000000260000002700000028000000290000002A0000002B0000002C0000002D0000002E0000002F000000300000003100000032000000330000003400000035000000360000003700000038000000390000003A0000003B0000003C0000003D0000003E0000003F000000400000004100000042000000430000004400000045000000460000004700000048000000490000004A0000004B0000004C0000004D0000004E0000004F000000500000005100000052000000530000005400000055000000560000005700000058000000590000005A0000005B0000005C0000005D0000005E0000005F000000600000006100000062000000630000006400000065000000660000006700000068000000690000006A0000006B0000006C0000006D0000006E0000006F000000700000007100000072000000730000007400000075000000760000007700000078000000790000007A0000007B0000007C0000007D0000007E0000007F000020AC000000000000201A000001920000201E000020260000202000002021000002C6000020300000000000002039000000000000000000000000000000000000000000002018000020190000201C0000201D000020220000201300002014000002DC00002122000000000000203A00000000000000000000000000000000000000A0000000A1000000A2000000A3000020AA000000A5000000A6000000A7000000A8000000A9000000D7000000AB000000AC000000AD000000AE000000AF000000B0000000B1000000B2000000B3000000B4000000B5000000B6000000B7000000B8000000B9000000F7000000BB000000BC000000BD000000BE000000BF000005B0000005B1000005B2000005B3000005B4000005B5000005B6000005B7000005B8000005B900000000000005BB000005BC000005BD000005BE000005BF000005C0000005C1000005C2000005C3000005F0000005F1000005F2000005F3000005F400000000000000000000000000000000000000000000000000000000000005D0000005D1000005D2000005D3000005D4000005D5000005D6000005D7000005D8000005D9000005DA000005DB000005DC000005DD000005DE000005DF000005E0000005E1000005E2000005E3000005E4000005E5000005E6000005E7000005E8000005E9000005EA00000000000000000000200E0000200F00000000"
idecpname$(23)="micsft_windows_cp1256"
idecp$(23)="000000000000000100000002000000030000000400000005000000060000000700000008000000090000000A0000000B0000000C0000000D0000000E0000000F000000100000001100000012000000130000001400000015000000160000001700000018000000190000001A0000001B0000001C0000001D0000001E0000001F000000200000002100000022000000230000002400000025000000260000002700000028000000290000002A0000002B0000002C0000002D0000002E0000002F000000300000003100000032000000330000003400000035000000360000003700000038000000390000003A0000003B0000003C0000003D0000003E0000003F000000400000004100000042000000430000004400000045000000460000004700000048000000490000004A0000004B0000004C0000004D0000004E0000004F000000500000005100000052000000530000005400000055000000560000005700000058000000590000005A0000005B0000005C0000005D0000005E0000005F000000600000006100000062000000630000006400000065000000660000006700000068000000690000006A0000006B0000006C0000006D0000006E0000006F000000700000007100000072000000730000007400000075000000760000007700000078000000790000007A0000007B0000007C0000007D0000007E0000007F000020AC0000067E0000201A000001920000201E000020260000202000002021000002C600002030000006790000203900000152000006860000069800000688000006AF00002018000020190000201C0000201D000020220000201300002014000006A900002122000006910000203A000001530000200C0000200D000006BA000000A00000060C000000A2000000A3000000A4000000A5000000A6000000A7000000A8000000A9000006BE000000AB000000AC000000AD000000AE000000AF000000B0000000B1000000B2000000B3000000B4000000B5000000B6000000B7000000B8000000B90000061B000000BB000000BC000000BD000000BE0000061F000006C10000062100000622000006230000062400000625000006260000062700000628000006290000062A0000062B0000062C0000062D0000062E0000062F00000630000006310000063200000633000006340000063500000636000000D70000063700000638000006390000063A00000640000006410000064200000643000000E000000644000000E200000645000006460000064700000648000000E7000000E8000000E9000000EA000000EB000006490000064A000000EE000000EF0000064B0000064C0000064D0000064E000000F40000064F00000650000000F700000651000000F900000652000000FB000000FC0000200E0000200F000006D2"
idecpname$(24)="micsft_windows_cp1257"
idecp$(24)="000000000000000100000002000000030000000400000005000000060000000700000008000000090000000A0000000B0000000C0000000D0000000E0000000F000000100000001100000012000000130000001400000015000000160000001700000018000000190000001A0000001B0000001C0000001D0000001E0000001F000000200000002100000022000000230000002400000025000000260000002700000028000000290000002A0000002B0000002C0000002D0000002E0000002F000000300000003100000032000000330000003400000035000000360000003700000038000000390000003A0000003B0000003C0000003D0000003E0000003F000000400000004100000042000000430000004400000045000000460000004700000048000000490000004A0000004B0000004C0000004D0000004E0000004F000000500000005100000052000000530000005400000055000000560000005700000058000000590000005A0000005B0000005C0000005D0000005E0000005F000000600000006100000062000000630000006400000065000000660000006700000068000000690000006A0000006B0000006C0000006D0000006E0000006F000000700000007100000072000000730000007400000075000000760000007700000078000000790000007A0000007B0000007C0000007D0000007E0000007F000020AC000000000000201A000000000000201E0000202600002020000020210000000000002030000000000000203900000000000000A8000002C7000000B80000000000002018000020190000201C0000201D0000202200002013000020140000000000002122000000000000203A00000000000000AF000002DB00000000000000A000000000000000A2000000A3000000A400000000000000A6000000A7000000D8000000A900000156000000AB000000AC000000AD000000AE000000C6000000B0000000B1000000B2000000B3000000B4000000B5000000B6000000B7000000F8000000B900000157000000BB000000BC000000BD000000BE000000E6000001040000012E0000010000000106000000C4000000C500000118000001120000010C000000C9000001790000011600000122000001360000012A0000013B000001600000014300000145000000D30000014C000000D5000000D6000000D700000172000001410000015A0000016A000000DC0000017B0000017D000000DF000001050000012F0000010100000107000000E4000000E500000119000001130000010D000000E90000017A0000011700000123000001370000012B0000013C000001610000014400000146000000F30000014D000000F5000000F6000000F700000173000001420000015B0000016B000000FC0000017C0000017E000002D9"
idecpname$(25)="micsft_windows_cp1258"
idecp$(25)="000000000000000100000002000000030000000400000005000000060000000700000008000000090000000A0000000B0000000C0000000D0000000E0000000F000000100000001100000012000000130000001400000015000000160000001700000018000000190000001A0000001B0000001C0000001D0000001E0000001F000000200000002100000022000000230000002400000025000000260000002700000028000000290000002A0000002B0000002C0000002D0000002E0000002F000000300000003100000032000000330000003400000035000000360000003700000038000000390000003A0000003B0000003C0000003D0000003E0000003F000000400000004100000042000000430000004400000045000000460000004700000048000000490000004A0000004B0000004C0000004D0000004E0000004F000000500000005100000052000000530000005400000055000000560000005700000058000000590000005A0000005B0000005C0000005D0000005E0000005F000000600000006100000062000000630000006400000065000000660000006700000068000000690000006A0000006B0000006C0000006D0000006E0000006F000000700000007100000072000000730000007400000075000000760000007700000078000000790000007A0000007B0000007C0000007D0000007E0000007F000020AC000000000000201A000001920000201E000020260000202000002021000002C6000020300000000000002039000001520000000000000000000000000000000000002018000020190000201C0000201D000020220000201300002014000002DC00002122000000000000203A00000153000000000000000000000178000000A0000000A1000000A2000000A3000000A4000000A5000000A6000000A7000000A8000000A9000000AA000000AB000000AC000000AD000000AE000000AF000000B0000000B1000000B2000000B3000000B4000000B5000000B6000000B7000000B8000000B9000000BA000000BB000000BC000000BD000000BE000000BF000000C0000000C1000000C200000102000000C4000000C5000000C6000000C7000000C8000000C9000000CA000000CB00000300000000CD000000CE000000CF00000110000000D100000309000000D3000000D4000001A0000000D6000000D7000000D8000000D9000000DA000000DB000000DC000001AF00000303000000DF000000E0000000E1000000E200000103000000E4000000E5000000E6000000E7000000E8000000E9000000EA000000EB00000301000000ED000000EE000000EF00000111000000F100000323000000F3000000F4000001A1000000F6000000F7000000F8000000F9000000FA000000FB000000FC000001B0000020AB000000FF"
idecpname$(26)="micsft_windows_cp874"
idecp$(26)="000000000000000100000002000000030000000400000005000000060000000700000008000000090000000A0000000B0000000C0000000D0000000E0000000F000000100000001100000012000000130000001400000015000000160000001700000018000000190000001A0000001B0000001C0000001D0000001E0000001F000000200000002100000022000000230000002400000025000000260000002700000028000000290000002A0000002B0000002C0000002D0000002E0000002F000000300000003100000032000000330000003400000035000000360000003700000038000000390000003A0000003B0000003C0000003D0000003E0000003F000000400000004100000042000000430000004400000045000000460000004700000048000000490000004A0000004B0000004C0000004D0000004E0000004F000000500000005100000052000000530000005400000055000000560000005700000058000000590000005A0000005B0000005C0000005D0000005E0000005F000000600000006100000062000000630000006400000065000000660000006700000068000000690000006A0000006B0000006C0000006D0000006E0000006F000000700000007100000072000000730000007400000075000000760000007700000078000000790000007A0000007B0000007C0000007D0000007E0000007F000020AC0000000000000000000000000000000000002026000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002018000020190000201C0000201D0000202200002013000020140000000000000000000000000000000000000000000000000000000000000000000000A000000E0100000E0200000E0300000E0400000E0500000E0600000E0700000E0800000E0900000E0A00000E0B00000E0C00000E0D00000E0E00000E0F00000E1000000E1100000E1200000E1300000E1400000E1500000E1600000E1700000E1800000E1900000E1A00000E1B00000E1C00000E1D00000E1E00000E1F00000E2000000E2100000E2200000E2300000E2400000E2500000E2600000E2700000E2800000E2900000E2A00000E2B00000E2C00000E2D00000E2E00000E2F00000E3000000E3100000E3200000E3300000E3400000E3500000E3600000E3700000E3800000E3900000E3A0000000000000000000000000000000000000E3F00000E4000000E4100000E4200000E4300000E4400000E4500000E4600000E4700000E4800000E4900000E4A00000E4B00000E4C00000E4D00000E4E00000E4F00000E5000000E5100000E5200000E5300000E5400000E5500000E5600000E5700000E5800000E5900000E5A00000E5B00000000000000000000000000000000"


'######## update.bas: init ########
'data for managing multiple file downloading
const Maxdls = 1
DIM SHARED DLs AS LONG
TYPE Download_Type
State AS LONG
'-1=failed
'0=inactive
'1=connected and reading data
'2=finished!
Handle AS LONG
END TYPE
DIM SHARED DL(1 TO Maxdls) AS Download_Type
DIM SHARED DL_Data(1 TO Maxdls) AS STRING
DIM SHARED Download_String AS STRING
'compress/decompress shared variables
DIM SHARED huff_count(0 TO 255) AS LONG
DIM SHARED huff_weight(0 TO 1000) AS LONG
DIM SHARED huff_branch(0 TO 255) AS LONG
DIM SHARED huff_parent(0 TO 1000) AS LONG
DIM SHARED huff_bit(0 TO 1000) AS LONG
DIM SHARED huff_bit0link(0 TO 1000) AS LONG
DIM SHARED huff_bit1link(0 TO 1000) AS LONG
DIM SHARED huff_mask(32 * 8 * 256) AS _UNSIGNED _BYTE
DIM SHARED huff_mask_bytes(0 TO 7, 0 TO 255) AS LONG 'number of bytes in mask (at offset 0-7)
DIM SHARED huff_mask_bits(0 TO 255) AS LONG 'number of bits in mask
DIM SHARED huff_bitval(0 TO 7) AS LONG
huff_bitval(0) = 1: huff_bitval(1) = 2: huff_bitval(2) = 4: huff_bitval(3) = 8
huff_bitval(4) = 16: huff_bitval(5) = 32: huff_bitval(6) = 64: huff_bitval(7) = 128
DIM SHARED huff_branch0(1000) AS LONG
DIM SHARED huff_branch1(1000) AS LONG
'(end of compress/decompress shared variables)
REDIM SHARED chksums_name(1 TO 1) AS STRING
REDIM SHARED chksums_valstr(1 TO 1) AS STRING
DIM SHARED update_error
DIM SHARED UpdateHandle
goto skip_update_error_handler
update_error_handler:
update_error = 1
RESUME NEXT
skip_update_error_handler:
'update settings
DIM SHARED ideupdatecheck, ideupdatedaily, ideupdateauto, ideupdatelast
dim shared ideupdatetimerval as single
'get settings
OPEN ".\internal\temp\options.bin" FOR BINARY AS #150
IF LOF(150)>=1048 THEN
seek #150,1039
get #150,,v%: if v%<>0 then v%=1
ideupdatecheck=v%
get #150,,v%: if v%<>0 then v%=1
ideupdatedaily=v%
get #150,,v%: if v%<>0 then v%=1
ideupdateauto=v%
get #150,,ideupdatelast&
else
ideupdatecheck=1
ideupdatedaily=1
ideupdateauto=1
ideupdatelast=0
end if
close #150

IF os$ = "WIN" THEN

'begin update check
if ideupdatecheck then
a$=date$: dateval=val(mid$(a$,4,2))+val(mid$(a$,1,2))*32+val(mid$(a$,7,4))*416 'create unique date value
if ideupdatedaily=0 or dateval<>ideupdatelast then
 'note: regardless of success or failure, daily checks are attempted once, so the 'last' value is updated here
 ideupdatelast=dateval
 OPEN ".\internal\temp\options.bin" FOR BINARY AS #150
 IF LOF(150)>=1048 THEN
 seek #150,1045
 put #150,,ideupdatelast
 end if
 close #150
'connect
UpdateHandle = BeginDownload("www.qb64.net/update.txt")
ideupdatetimerval=TIMER
end if 'update check required
end if 'ideupdatecheck on

END IF 'win

'hash table data
TYPE HashListItem
Flags AS LONG
Reference AS LONG
NextItem AS LONG
PrevItem AS LONG
LastItem AS LONG 'note: this value is only valid on the first item in the list
'note: name is stored in a seperate array of strings
END TYPE
DIM SHARED HashFind_NextListItem AS LONG
DIM SHARED HashFind_Reverse AS LONG
DIM SHARED HashFind_SearchFlags AS LONG
DIM SHARED HashFind_Name AS STRING
DIM SHARED HashRemove_LastFound AS LONG
DIM SHARED HashListSize AS LONG
DIM SHARED HashListNext as LONG
DIM SHARED HashListFreeSize as LONG
DIM SHARED HashListFreeLast as LONG
'hash lookup tables
DIM SHARED hash1char(255) AS INTEGER
DIM SHARED hash2char(65535) AS INTEGER
FOR x = 1 TO 26
  hash1char(64 + x) = x
  hash1char(96 + x) = x
NEXT
hash1char(95) = 27 '_
hash1char(48) = 28 '0
hash1char(49) = 29 '1
hash1char(50) = 30 '2
hash1char(51) = 31 '3
hash1char(52) = 23 '4 'note: x, y, z and beginning alphabet letters avoided because of common usage (eg. a2, y3)
hash1char(53) = 22 '5
hash1char(54) = 20 '6
hash1char(55) = 19 '7
hash1char(56) = 18 '8
hash1char(57) = 17 '9
FOR c1 = 0 TO 255
  FOR c2 = 0 TO 255
    hash2char(c1 + c2 * 256) = hash1char(c1) + hash1char(c2) * 32
  NEXT
NEXT
'init
HashListSize = 65536
HashListNext = 1
HashListFreeSize = 1024
HashListFreeLast = 0
REDIM SHARED HashList(1 TO HashListSize) AS HashListItem
REDIM SHARED HashListName(1 TO HashListSize) AS STRING * 256
REDIM SHARED HashListFree(1 TO HashListFreeSize) AS LONG
REDIM SHARED HashTable(16777215) AS LONG '64MB lookup table with indexes to the hashlist
const HASHFLAG_LABEL=2

type Label_Type
State as _unsigned _byte '0=label referenced, 1=label created
cn as string * 256
Scope as LONG
Data_Offset as _INTEGER64 'offset within data
Data_Referenced as _unsigned _byte 'set to 1 if data is referenced (data_offset will be used to create the data offset variable)
Error_Line as LONG 'the line number to reference on errors
Scope_Restriction as LONG 'cannot exist inside this scope (post checked)
end type
dim shared nLabels,Labels_Ubound
Labels_Ubound=100
redim shared Labels(1 to Labels_Ubound) as Label_Type
dim shared Empty_Label as Label_Type


dim shared DataOffset

dim shared prepass


DIM SHARED autoarray


DIM SHARED sp2 AS STRING * 1
sp2 = CHR$(249)

DIM SHARED ontimerid


DIM SHARED revertmaymusthave(1 TO 10000)
DIM SHARED revertmaymusthaven




DIM SHARED linecontinuation

DIM SHARED dim2typepassback AS STRING 'passes back correct case sensitive version of type


DIM SHARED inclevel
DIM SHARED incname(100) AS STRING 'must be full path as given
DIM SHARED inclinenumber(100) AS LONG
DIM SHARED incerror AS STRING


DIM SHARED fix046 AS STRING
fix046$ = "__" + "ASCII" + "_" + "CHR" + "_" + "046" + "__" 'broken up to avoid detection for layout reversion

DIM SHARED layout AS STRING 'passed to IDE
DIM SHARED layoutok AS LONG 'tracks status of entire line

DIM SHARED layoutcomment AS STRING

DIM SHARED tlayout AS STRING 'temporary layout string set by supporting functions
DIM SHARED layoutdone AS LONG 'tracks status of single command


DIM SHARED fooindwel

DIM SHARED alphanumeric(255)
FOR i = 48 TO 57
    alphanumeric(i) = -1
NEXT
FOR i = 65 TO 90
    alphanumeric(i) = -1
NEXT
FOR i = 97 TO 122
    alphanumeric(i) = -1
NEXT
'_ is treated as an alphabet letter
alphanumeric(95) = -1

DIM SHARED lfsinglechar(255)
lfsinglechar(40) = 1 '(
lfsinglechar(41) = 1 ')
lfsinglechar(42) = 1 '*
lfsinglechar(43) = 1 '+
lfsinglechar(45) = 1 '-
lfsinglechar(47) = 1 '/
lfsinglechar(60) = 1 '<
lfsinglechar(61) = 1 '=
lfsinglechar(62) = 1 '>
lfsinglechar(92) = 1 '\
lfsinglechar(94) = 1 '^

lfsinglechar(44) = 1 ',
lfsinglechar(46) = 1 '.
lfsinglechar(58) = 1 ':
lfsinglechar(59) = 1 ';

lfsinglechar(35) = 1 '# (file no only)
lfsinglechar(36) = 1 '$ (metacommand only)
lfsinglechar(63) = 1 '? (print macro)
lfsinglechar(95) = 1 '_










DIM SHARED nextrunlineindex AS LONG

DIM SHARED lineinput3buffer AS STRING
DIM SHARED lineinput3index AS LONG

DIM SHARED debug AS LONG 'debug is off by default
'debug=1

DIM SHARED dimstatic AS LONG

DIM SHARED staticarraylist AS STRING
DIM SHARED staticarraylistn AS LONG
DIM SHARED commonarraylist AS STRING
DIM SHARED commonarraylistn AS LONG

'CONST support
DIM SHARED constmax AS LONG
constmax = 10000
DIM SHARED constlast AS LONG
constlast = -1
DIM SHARED constname(constmax) AS STRING
DIM SHARED constcname(constmax) AS STRING
DIM SHARED constnamesymbol(constmax) AS STRING 'optional name symbol
' `1 and `no-number must be handled correctly
DIM SHARED constlastshared AS LONG 'so any defined inside a sub/function after this index can be "forgotten" when sub/function exits
constlastshared = -1
DIM SHARED consttype(constmax) AS LONG 'variable type number
'consttype determines storage
DIM SHARED constinteger(constmax) AS _INTEGER64
DIM SHARED constuinteger(constmax) AS _UNSIGNED _INTEGER64
DIM SHARED constfloat(constmax) AS _FLOAT
DIM SHARED conststring(constmax) AS STRING

'UDT
'names
DIM SHARED lasttype AS LONG
DIM SHARED udtxname(1000) AS STRING * 256
DIM SHARED udtxcname(1000) AS STRING * 256
DIM SHARED udtxsize(1000) AS LONG
DIM SHARED udtxbytealign(1000) AS INTEGER 'first element MUST be on a byte alignment & size is a multiple of 8
DIM SHARED udtxnext(1000) AS LONG
'elements
DIM SHARED lasttypeelement AS LONG
DIM SHARED udtename(1000) AS STRING * 256
DIM SHARED udtecname(1000) AS STRING * 256
DIM SHARED udtebytealign(1000) AS INTEGER
DIM SHARED udtesize(1000) AS LONG
DIM SHARED udtetype(1000) AS LONG
DIM SHARED udtetypesize(1000) AS LONG
DIM SHARED udtearrayelements(1000) AS LONG
DIM SHARED udtearraybaseelement(1000) AS STRING * 1024
DIM SHARED udtearraytopelement(1000) AS STRING * 1024
DIM SHARED udtenext(1000) AS LONG

TYPE idstruct

n AS STRING * 256 'name
cn AS STRING * 256 'case sensitive version of n

arraytype AS LONG 'similar to t
arrayelements AS INTEGER
staticarray AS INTEGER 'set for arrays declared in the main module with static elements

mayhave AS STRING * 8 'mayhave and musthave are exclusive of each other
musthave AS STRING * 8
t AS LONG 'type

tsize AS LONG


subfunc AS INTEGER 'if function=1, sub=2 (max 60 arguements!)
callname AS STRING * 256
ccall AS INTEGER
args AS INTEGER
arg AS STRING * 400 'similar to t
argsize AS STRING * 400 'similar to tsize (used for fixed length strings)
specialformat AS STRING * 256
secondargmustbe AS STRING * 256
secondargcantbe AS STRING * 256
ret AS LONG 'the value it returns if it is a function (again like t)

insubfunc AS STRING * 256
share AS INTEGER
nele AS STRING * 100
nelereq AS STRING * 100
linkid AS LONG
linkarg AS INTEGER
staticscope AS INTEGER
'For variables which are arguments passed to a sub/function
sfid AS LONG 'id number of variable's parent sub/function
sfarg AS INTEGER 'argument/parameter # within call (1=first)

END TYPE

DIM SHARED id AS idstruct

DIM SHARED idn AS LONG
DIM SHARED ids_max AS LONG
ids_max = 1024
REDIM SHARED ids(1 TO ids_max) AS idstruct
REDIM SHARED cmemlist(1 TO ids_max + 1) AS INTEGER 'variables that must be in cmem
REDIM SHARED sfcmemargs(1 TO ids_max + 1) AS STRING * 100 's/f arg that must be in cmem
REDIM SHARED arrayelementslist(1 TO ids_max + 1) AS INTEGER 'arrayelementslist (like cmemlist) helps to resolve the number of elements in arrays with an unknown number of elements. Note: arrays with an unknown number of elements have .arrayelements=-1


'create blank id template for idclear to copy (stops strings being set to chr$(0))
DIM SHARED cleariddata AS idstruct
cleariddata.cn = ""
cleariddata.n = ""
cleariddata.mayhave = ""
cleariddata.musthave = ""
cleariddata.callname = ""
cleariddata.arg = ""
cleariddata.argsize = ""
cleariddata.specialformat = ""
cleariddata.secondargmustbe = ""
cleariddata.secondargcantbe = ""
cleariddata.insubfunc = ""
cleariddata.nele = ""
cleariddata.nelereq = ""

DIM SHARED ISSTRING AS LONG
DIM SHARED ISFLOAT AS LONG
DIM SHARED ISUNSIGNED AS LONG
DIM SHARED ISPOINTER AS LONG
DIM SHARED ISFIXEDLENGTH AS LONG
DIM SHARED ISINCONVENTIONALMEMORY AS LONG
DIM SHARED ISOFFSETINBITS AS LONG
DIM SHARED ISARRAY AS LONG
DIM SHARED ISREFERENCE AS LONG
DIM SHARED ISUDT AS LONG

DIM SHARED STRINGTYPE AS LONG
DIM SHARED BITTYPE AS LONG
DIM SHARED UBITTYPE AS LONG
DIM SHARED BYTETYPE AS LONG
DIM SHARED UBYTETYPE AS LONG
DIM SHARED INTEGERTYPE AS LONG
DIM SHARED UINTEGERTYPE AS LONG
DIM SHARED LONGTYPE AS LONG
DIM SHARED ULONGTYPE AS LONG
DIM SHARED INTEGER64TYPE AS LONG
DIM SHARED UINTEGER64TYPE AS LONG
DIM SHARED SINGLETYPE AS LONG
DIM SHARED DOUBLETYPE AS LONG
DIM SHARED FLOATTYPE AS LONG

DIM SHARED gosubid AS LONG
DIM SHARED redimoption AS INTEGER
DIM SHARED arraydesc AS INTEGER
DIM SHARED qberrorhappened AS INTEGER
DIM SHARED qberrorcode AS INTEGER
DIM SHARED qberrorline AS INTEGER
'COMMON SHARED defineaz() AS STRING
'COMMON SHARED defineextaz() AS STRING

DIM SHARED sourcefile AS STRING 'the full path and filename
DIM SHARED file AS STRING 'name of the file (without .bas or path)

'COMMON SHARED separgs() AS STRING
DIM SHARED sp AS STRING * 1
DIM SHARED constequation AS INTEGER
DIM SHARED dynamic AS INTEGER
DIM SHARED findidsecondarg AS STRING
DIM SHARED findanotherid AS INTEGER
DIM SHARED findidinternal AS LONG
DIM SHARED currentid AS LONG 'is the index of the last ID accessed
DIM SHARED linenumber AS LONG
DIM SHARED wholeline AS STRING
DIM SHARED linefragment AS STRING
'COMMON SHARED bitmask() AS _INTEGER64
'COMMON SHARED bitmaskinv() AS _INTEGER64

DIM SHARED arrayprocessinghappened AS INTEGER
DIM SHARED stringprocessinghappened AS INTEGER
DIM SHARED cleanupstringprocessingcall AS STRING
DIM SHARED recompile AS INTEGER 'forces recompilation
'COMMON SHARED cmemlist() AS INTEGER
DIM SHARED optionbase AS INTEGER

DIM SHARED addmetastatic AS INTEGER
DIM SHARED addmetadynamic AS INTEGER
DIM SHARED addmetainclude AS STRING

DIM SHARED closedmain AS INTEGER
DIM SHARED module AS STRING
DIM SHARED subfunc AS STRING
DIM SHARED subfuncn AS LONG
DIM SHARED defdatahandle AS INTEGER
DIM SHARED dimsfarray AS INTEGER
DIM SHARED dimshared AS INTEGER

'Allows passing of known elements to recompilation
DIM SHARED sflistn AS INTEGER
'COMMON SHARED sfidlist() AS LONG
'COMMON SHARED sfarglist() AS INTEGER
'COMMON SHARED sfelelist() AS INTEGER
DIM SHARED glinkid AS LONG
DIM SHARED glinkarg AS INTEGER
DIM SHARED typname2typsize AS LONG
DIM SHARED uniquenumbern AS LONG

'CLEAR , , 16384


DIM SHARED bitmask(1 TO 56) AS _INTEGER64
DIM SHARED bitmaskinv(1 TO 56) AS _INTEGER64
DIM SHARED separgs(100) AS STRING
DIM SHARED separgslayout(100) AS STRING


DIM SHARED defineextaz(1 TO 27) AS STRING
DIM SHARED defineaz(1 TO 27) AS STRING '27 is an underscore

ISSTRING = 1073741824
ISFLOAT = 536870912
ISUNSIGNED = 268435456
ISPOINTER = 134217728
ISFIXEDLENGTH = 67108864 'only set for strings with pointer flag
ISINCONVENTIONALMEMORY = 33554432
ISOFFSETINBITS = 16777216
ISARRAY = 8388608
ISREFERENCE = 4194304
ISUDT = 2097152

STRINGTYPE = ISSTRING + ISPOINTER
BITTYPE = 1& + ISPOINTER + ISOFFSETINBITS
UBITTYPE = 1& + ISPOINTER + ISUNSIGNED + ISOFFSETINBITS 'QB64 will also support BIT*n, eg. DIM bitarray[10] AS _UNSIGNED _BIT*10
BYTETYPE = 8& + ISPOINTER
UBYTETYPE = 8& + ISPOINTER + ISUNSIGNED
INTEGERTYPE = 16& + ISPOINTER
UINTEGERTYPE = 16& + ISPOINTER + ISUNSIGNED
LONGTYPE = 32& + ISPOINTER
ULONGTYPE = 32& + ISPOINTER + ISUNSIGNED
INTEGER64TYPE = 64& + ISPOINTER
UINTEGER64TYPE = 64& + ISPOINTER + ISUNSIGNED
SINGLETYPE = 32& + ISFLOAT + ISPOINTER
DOUBLETYPE = 64& + ISFLOAT + ISPOINTER
FLOATTYPE = 256& + ISFLOAT + ISPOINTER '8-32 bytes






DIM SHARED statementn AS LONG





DIM controllevel AS INTEGER '0=not in a control block
DIM controltype(1000) AS INTEGER
'1=IF (awaiting END IF)
'2=FOR (awaiting NEXT)
'3=DO (awaiting LOOP [UNTIL|WHILE param])
'4=DO WHILE/UNTIL (awaiting LOOP)
'5=WHILE (awaiting WEND)
'10=SELECT CASE qbs (awaiting END SELECT/CASE)
'11=SELECT CASE int64 (awaiting END SELECT/CASE)
'12=SELECT CASE uint64 (awaiting END SELECT/CASE)
'13=SELECT CASE LONG double (awaiting END SELECT/CASE/CASE ELSE)
'14=SELECT CASE float ...
'15=SELECT CASE double
'16=SELECT CASE int32
'17=SELECT CASE uint32
'18=CASE (awaiting END SELECT/CASE/CASE ELSE)
'19=CASE ELSE (awaiting END SELECT)
DIM controlid(1000) AS LONG
DIM controlvalue(1000) AS LONG
DIM controlstate(1000) AS INTEGER
DIM controlref(1000) AS LONG 'the line number the control was created on


DIM separgs2(100) AS STRING
DIM separgslayout2(100) AS STRING

sp = CHR$(250)



ON ERROR GOTO qberror

i2&& = 1
FOR i&& = 1 TO 56
    bitmask(i&&) = i2&&
    bitmaskinv(i&&) = NOT i2&&
    i2&& = i2&& + 2 ^ i&&
NEXT

DIM id2 AS idstruct

cleanupstringprocessingcall$ = "qbs_cleanup(qbs_tmp_base,"

DIM SHARED sfidlist(1000) AS LONG
DIM SHARED sfarglist(1000) AS INTEGER
DIM SHARED sfelelist(1000) AS INTEGER

DIM SHARED command2$

command2$ = COMMAND$
a$ = LTRIM$(RTRIM$(command2$))
a2$ = LCASE$(LEFT$(a$, 2))
IF a2$ = "-c" THEN command2$ = LTRIM$(RIGHT$(a$, LEN(a$) - 2)): GOTO noide
'assume command2$ contains the name of a file to load/compile

'compiler-side IDE data & definitions
DIM SHARED idecurrentlinelayout AS STRING
DIM SHARED idecurrentlinelayouti AS LONG
DIM SHARED idelayoutallow AS LONG


DIM SHARED idecommand AS STRING
DIM SHARED idereturn AS STRING
DIM SHARED ideerror AS LONG
DIM SHARED idecompiled AS LONG
DIM SHARED idemode
DIM SHARED ideerrorline AS LONG 'set by qb64error(...) to the line number it would have reported, this number
'is later passed to the ide in message #8
DIM SHARED idemessage AS STRING 'set by qb64error(...) to the error message to be reported, this
'is later passed to the ide in message #8

'the function ?=ide(?) should always be passed 0, it returns a message code number, any further information
'is passed back in idereturn

'message code numbers:
'0  no ide present  (auto defined array ide() return 0)

'1  launch ide & with passed filename (compiler->ide)

'2  begin new compilation with returned line of code (compiler<-ide)
'   [2][line of code]

'3  request next line (compiler->ide)
'   [3]

'4  next line of code returned (compiler<-ide)
'   [4][line of code]

'5  no more lines of code exist (compiler<-ide)
'   [5]

'6  code is OK/ready (compiler->ide)
'   [6]

'7  repass the code from the beginning (compiler->ide)
'   [7]

'8  an error has occurred with 'this' message on 'this' line(compiler->ide)
'   [8][error message][line as LONG]

'9  C++ compile (if necessary) and run with 'this' name (compiler<-ide)
'   [9][name(no path, no .bas)]

'10 The line requires more time to process
'       Pass-back 'line of code' using method [4] when ready
'   [10][line of code]

'11 ".EXE file created" message

'12     The name of the exe I'll create is '...' (compiler->ide)
'   [12][exe name without .exe]

'255    A qb error happened in the IDE (compiler->ide)
'   note: detected by the fact that ideerror was not set to 0
'   [255]

'IDE MODULE: shared data & definitions
DIM SHARED mousex AS INTEGER
DIM SHARED mousey AS INTEGER
DIM SHARED mousewheel AS INTEGER
DIM SHARED mousebutton1 AS INTEGER
DIM SHARED mousebutton2 AS INTEGER
DIM SHARED mousevisible AS INTEGER
DIM SHARED mousepassed AS INTEGER
'---------------------------------------------------
DIM SHARED idet AS STRING, idel, ideli, iden
DIM SHARED idelaunched, idecompiling
DIM SHARED idecompiledline 'stores the number of the last line sent to the compiler, used only to know which line to send next
DIM SHARED idecompiledline$ 'stores the last line sent to the compiler
DIM SHARED idesx, idesy, idecx, idecy
DIM SHARED ideselect, ideselectx1, ideselecty1, idemouseselect
DIM SHARED ideunsaved
DIM SHARED ideroot AS STRING
DIM SHARED idetxt(1000) AS STRING
DIM SHARED idetxtlast AS INTEGER
DIM SHARED idehl
DIM SHARED idealtcode(255) AS INTEGER
DIM SHARED ideprogname AS STRING
DIM SHARED idepath AS STRING
DIM SHARED idefindtext AS STRING
DIM SHARED idefindcasesens AS INTEGER
DIM SHARED idefindwholeword AS INTEGER
DIM SHARED idechangeto AS STRING
DIM SHARED idechangemade AS INTEGER
DIM SHARED ideautosave AS INTEGER
DIM SHARED ideinsert AS INTEGER
DIM SHARED idepathsep AS STRING * 1

redim shared idekeymap_n as LONG
redim shared idekeymap_scancodes(1 to 1) as string
redim shared idekeymap_output(1 to 1) as _unsigned _byte
reDIM SHARED KeyDown(127) AS LONG
redim shared idekeymap_ready(1 to 1) as _unsigned _byte

'--------------------------------------------------------------------------------
TYPE idedbptype
x AS LONG
y AS LONG
w AS LONG
h AS LONG
nam AS LONG
END TYPE
'--------------------------------------------------------------------------------
TYPE idedbotype
par AS idedbptype
x AS LONG
y AS LONG
w AS LONG
h AS LONG
typ AS LONG
nam AS LONG
txt AS LONG
def AS LONG
cx AS LONG
cy AS LONG
foc AS LONG
sel AS LONG 'selected item no.
stx AS LONG 'selected item in string form
v1 AS LONG
num AS LONG
END TYPE
'--------------------------------------------------------------------------------
DIM SHARED idefocusline 'simply stores the location of the line to highlight in red
DIM SHARED ideautorun
DIM SHARED menu$(1 TO 10, 0 TO 20)
DIM SHARED menusize(1 TO 10)
DIM SHARED menus AS INTEGER
DIM SHARED menubar$
DIM SHARED idealthighlight, ideentermenu
DIM SHARED ideautolayout, ideautoindent, ideautoindentsize
DIM SHARED idewx, idewy, idecustomfont, idecustomfontfile$, idecustomfontheight, idecustomfonthandle
DIM SHARED iderunmode
'IDE MODULE SECTION END: shared data & definitions

idemode = 1
sendc$ = "" 'no initial message
IF command2$ <> "" THEN sendc$ = CHR$(1) + command2$
sendcommand:
idecommand$ = sendc$
c = ide(0)
ideerror = 0
IF c = 0 THEN idemode = 0: GOTO noide
c$ = idereturn$

IF c = 2 THEN 'begin
    ideerrorline = 0 'addresses invalid prepass error line numbers being reported
    idepass = 1
    GOTO fullrecompile
    ideret1:
    wholeline$ = c$
    GOTO ideprepass
    ideret2:
    sendc$ = CHR$(3) 'request next line
    GOTO sendcommand
END IF

IF c = 4 THEN 'next line
    IF idepass = 1 THEN
        wholeline$ = c$
        GOTO ideprepass
        '(returns to ideret2: above)
    END IF
    'assume idepass>1
    a3$ = c$
    continuelinefrom = 0
    GOTO ide4
    ideret4:
    sendc$ = CHR$(3) 'request next line
    GOTO sendcommand
END IF

IF c = 5 THEN 'end of program reached
    IF idepass = 1 THEN
        'prepass complete
        idepass = 2
        GOTO ide3
        ideret3:
        sendc$ = CHR$(7) 'repass request
        GOTO sendcommand
    END IF
    'assume idepass=2
    'finalize program
    GOTO ide5
    ideret5: 'note: won't return here if a recompile was required!
    sendc$ = CHR$(6) 'ready
    idecompiled = 0
    GOTO sendcommand
END IF

IF c = 9 THEN 'run

    IF idecompiled = 0 THEN 'exe needs to be compiled
        file$ = c$

        f$ = file$
        i = 1
        nextexeindex:
        e = 0
        ON ERROR GOTO qberror_test
        OPEN file$ + extension$ FOR OUTPUT AS #1 'locate accessible file and truncate
        ON ERROR GOTO qberror
        IF e = 1 THEN
            i = i + 1
            file$ = f$ + "(" + str2$(i) + ")"
            GOTO nextexeindex
        ELSE
            CLOSE #1
        END IF

        'inform IDE of name change if necessary (IDE will respond with message 9 and corrected name)
        IF i <> 1 THEN
            sendc$ = CHR$(12) + file$
            GOTO sendcommand
        END IF


        ideerrorline = 0 'addresses C++ comp. error's line number
        GOTO ide6
        ideret6:
        idecompiled = 1
    END IF

    IF iderunmode = 2 THEN
        sendc$ = CHR$(11) '.EXE file created
        GOTO sendcommand
    END IF

    'hack! (a new message should be sent to the IDE stating C++ compilation was successful)
    COLOR 7, 1: LOCATE idewy - 3, 2: PRINT SPACE$(idewx - 2);: LOCATE idewy - 2, 2: PRINT SPACE$(idewx - 2);: LOCATE idewy - 1, 2: PRINT SPACE$(idewx - 2); 'clear status window

    LOCATE idewy - 3, 2: PRINT "Starting program...";
    PCOPY 3, 0

    'execute program

    IF iderunmode = 1 THEN
        IF os$ = "WIN" THEN SHELL _DONTWAIT idezfilename$(CHR$(34) + file$ + extension$ + CHR$(34))
        IF os$ = "LNX" THEN SHELL _DONTWAIT idezfilename$("./" + file$+ extension$)
    ELSE
        IF os$ = "WIN" THEN SHELL idezfilename$(CHR$(34) + file$ + extension$ + CHR$(34))
        IF os$ = "LNX" THEN SHELL idezfilename$("./" + file$+ extension$)
    END IF

    sendc$ = CHR$(6) 'ready
    GOTO sendcommand
END IF

PRINT "Invalid IDE message": END

ideerror:
sendc$ = CHR$(8) + idemessage$ + MKL$(ideerrorline)
GOTO sendcommand


noide:
PRINT "QB64 COMPILER V0.923"

IF command2$ = "" THEN
    LINE INPUT ; "COMPILE (.bas)>", f$
ELSE
    f$ = command2$
END IF

f$ = LTRIM$(RTRIM$(f$))
IF LEN(f$) > 4 THEN
    IF UCASE$(RIGHT$(f$, 4)) <> ".BAS" THEN f$ = f$ + ".bas"
ELSE
    f$ = f$ + ".bas"
END IF
sourcefile$ = f$
'derive name from sourcefile
f$ = LEFT$(f$, LEN(f$) - 4) 'remove .bas
FOR x = LEN(f$) TO 1 STEP -1
    a$ = MID$(f$, x, 1)
    IF a$ = "/" OR a$ = "\" THEN
        f$ = RIGHT$(f$, LEN(f$) - x)
        EXIT FOR
    END IF
NEXT
file$ = f$

'if cmemlist(currentid+1)<>0 before calling regid the variable
'MUST be defined in cmem!

fullrecompile:
for closeall=1 to 255:CLOSE closeall:next

OPEN tmpdir$ + "temp.bin" FOR OUTPUT LOCK READ WRITE AS #26 'relock

IF debug THEN OPEN tmpdir$ + "debug.txt" FOR OUTPUT AS #9


FOR i = 1 TO ids_max + 1
    arrayelementslist(i) = 0
    cmemlist(i) = 0
    sfcmemargs(i) = ""
NEXT


'erase cmemlist
'erase sfcmemargs

lastunresolved = -1 'first pass
sflistn = -1 'no entries

recompile:



HashClear 'clear the hash table

'clear/init variables
mylib$=""
declaringlibrary=0
nLabels=0
dynscope = 0
elsefollowup = 0
ontimerid = 0
commonarraylist = "": commonarraylistn = 0
staticarraylist = "": staticarraylistn = 0
fooindwel = 0
layout = ""
layoutok = 0
nochecks = 0
inclevel = 0
addmetainclude$ = ""
nextrunlineindex = 1
lasttype = 0
lasttypeelement = 0
definingtype = 0
constlast = -1
constlastshared = -1
defdatahandle = 18
closedmain = 0
addmetastatic = 0
addmetadynamic = 0
dynamic = 0
optionbase = 0
DataOffset = 0
statementn = 0
qberrorhappened = 0: qberrorcode = 0: qberrorline = 0
FOR i = 1 TO 27: defineaz(i) = "SINGLE": defineextaz(i) = "!": NEXT
controllevel = 0
findidsecondarg$ = "": findanotherid = 0: findidinternal = 0: currentid = 0
linenumber = 0
wholeline$ = ""
linefragment$ = ""
idn = 0
arrayprocessinghappened = 0
stringprocessinghappened = 0
subfuncn = 0
subfunc = ""


'begin compilation
for closeall=1 to 255:CLOSE closeall:next
OPEN tmpdir$ + "temp.bin" FOR OUTPUT LOCK READ WRITE AS #26 'relock

IF debug THEN OPEN tmpdir$ + "debug.txt" FOR APPEND AS #9

IF idemode = 0 THEN
    qberrorhappened = -1
    OPEN sourcefile$ FOR INPUT AS #1
    qberrorhappened1:
    IF qberrorhappened = 1 THEN
        PRINT
        PRINT "CANNOT LOCATE SOURCE FILE:" + sourcefile$
        END
    ELSE
        CLOSE #1
    END IF
    qberrorhappened = 0
END IF

reginternal


OPEN tmpdir$ + "global.txt" FOR OUTPUT AS #18

IF iderecompile THEN
    iderecompile = 0
    idepass = 1 'prepass must be done again
    sendc$ = CHR$(7) 'repass request
    GOTO sendcommand
END IF

IF idemode THEN GOTO ideret1

lineinput3load sourcefile$

DO
    wholeline$ = lineinput3$
    IF wholeline$ = CHR$(13) THEN EXIT DO
    ideprepass:

    prepass=1
    layout = ""
    layoutok = 0

    linenumber = linenumber + 1
    IF LEN(wholeline$) THEN

        wholeline$ = lineformat(wholeline$)

        cwholeline$ = wholeline$
        wholeline$ = eleucase$(wholeline$) '********REMOVE THIS LINE LATER********


        addmetadynamic = 0: addmetastatic = 0
        wholelinen = numelements(wholeline$)

        IF wholelinen THEN

            wholelinei = 1

            'skip line number?
            e$ = getelement$(wholeline$, 1)
            IF (ASC(e$) >= 48 AND ASC(e$) <= 59) OR ASC(e$) = 46 THEN wholelinei = 2: GOTO ppskpl

            'skip 'POSSIBLE' line label?
            IF wholelinen >= 2 THEN
                x2 = INSTR(wholeline$, sp + ":" + sp): x3 = x2 + 2
                IF x2 = 0 THEN
                    IF RIGHT$(wholeline$, 2) = sp + ":" THEN x2 = LEN(wholeline$) - 1: x3 = x2 + 1
                END IF

                IF x2 THEN
                    e$ = LEFT$(wholeline$, x2 - 1)
                    IF validlabel(e$) THEN
                        wholeline$ = RIGHT$(wholeline$, LEN(wholeline$) - x3)
                        cwholeline$ = RIGHT$(cwholeline$, LEN(wholeline$) - x3)
                        wholelinen = numelements(wholeline$)
                        GOTO ppskpl
                    END IF 'valid
                END IF 'includes ":"
            END IF 'wholelinen>=2

            ppskpl:
            IF wholelinei <= wholelinen THEN
                '----------------------------------------
                a$ = ""
                ca$ = ""
                ppblda:
                e$ = getelement$(wholeline$, wholelinei)
                ce$ = getelement$(cwholeline$, wholelinei)
                IF e$ = ":" OR e$ = "ELSE" OR e$ = "THEN" OR e$ = "" THEN
                    IF LEN(a$) THEN
                        IF debug THEN PRINT #9, "PP[" + a$ + "]"
                        n = numelements(a$)
                        firstelement$ = getelement(a$, 1)
                        secondelement$ = getelement(a$, 2)
                        thirdelement$ = getelement(a$, 3)
                        '========================================

'declare library
if declaringlibrary then

if firstelement$="END" then
if n<>2 or secondelement$<>"DECLARE" then a$ = "Expected END DECLARE": GOTO errmes
declaringlibrary=0
GOTO finishedlinepp
end if 'end declare

declaringlibrary=2

if firstelement$="SUB" or firstelement$="FUNCTION" then goto declaresubfunc

a$ = "Expected SUB/FUNCTION definition or END DECLARE (#2)": GOTO errmes
end if

                        'UDT TYPE definition
                        IF n >= 1 THEN
                            IF firstelement$ = "TYPE" THEN
                                IF n <> 2 THEN a$ = "Expected TYPE typename": GOTO errmes
                                lasttype = lasttype + 1
                                definingtype = lasttype
                                i = definingtype
                                udtxname(i) = secondelement$
                                udtxcname(i) = getelement(ca$, 2)
                                udtxnext(i) = 0
                                udtxsize(i) = 0
                                'print "TYPE "+rtrim$(udtxname(i))
                                GOTO finishedlinepp
                            END IF
                        END IF

                        IF definingtype THEN
                            i = definingtype

                            IF n >= 1 THEN
                                IF firstelement$ = "END" THEN
                                    IF n <> 2 OR secondelement$ <> "TYPE" THEN a$ = "Expected END TYPE": GOTO errmes
                                    IF udtxnext(i) = 0 THEN a$ = "No elements defined in TYPE": GOTO errmes
                                    definingtype = 0

                                    'create global buffer for SWAP space
                                    siz$ = str2$(udtxsize(i) \ 8)
                                    PRINT #18, "char *g_tmp_udt_" + RTRIM$(udtxname(i)) + "=(char*)malloc(" + siz$ + ");"

                                    'print "END TYPE";udtxsize(i);udtxbytealign(i)
                                    GOTO finishedlinepp
                                END IF
                            END IF

                            lasttypeelement = lasttypeelement + 1
                            i2 = lasttypeelement
                            udtenext(i2) = 0

                            IF n < 3 THEN a$ = "Expected variablename AS type or END TYPE": GOTO errmes
                            n$ = firstelement$
                            ii = 2

                            udtearrayelements(i2) = 0
                            IF secondelement$ = "(" THEN
                                '...
                            END IF

                            IF ii >= n OR getelement$(a$, ii) <> "AS" THEN a$ = "Expected variablename AS type or END TYPE": GOTO errmes
                            t$ = getelements$(a$, ii + 1, n)

                            typ = typname2typ(t$)
                            IF typ = 0 THEN a$ = "Undefined type": GOTO errmes
                            typsize = typname2typsize

                            udtename(i2) = n$
                            udtecname(i2) = getelement$(ca$, 1)
                            udtetype(i2) = typ
                            udtetypesize(i2) = typsize

                            'Calculate element's size
                            IF typ AND ISUDT THEN
                                u = typ AND 511
                                udtesize(i2) = udtxsize(u)
                                IF udtxbytealign(u) THEN udtxbytealign(i) = 1: udtebytealign(i2) = 1
                            ELSE
                                IF (typ AND ISSTRING) THEN
                                    IF (typ AND ISFIXEDLENGTH) = 0 THEN a$ = "Expected STRING *": GOTO errmes
                                    udtesize(i2) = typsize * 8
                                    udtxbytealign(i) = 1: udtebytealign(i2) = 1
                                ELSE
                                    udtesize(i2) = typ AND 511
                                    IF (typ AND ISOFFSETINBITS) = 0 THEN udtxbytealign(i) = 1: udtebytealign(i2) = 1
                                END IF
                            END IF

                            'Increase block size
                            IF udtebytealign(i2) THEN
                                IF udtxsize(i) MOD 8 THEN
                                    udtxsize(i) = udtxsize(i) + (8 - (udtxsize(i) MOD 8))
                                END IF
                            END IF
                            udtxsize(i) = udtxsize(i) + udtesize(i2)

                            'Link element to previous element
                            IF udtxnext(i) = 0 THEN
                                udtxnext(i) = i2
                            ELSE
                                udtenext(i2 - 1) = i2
                            END IF

                            'print "+"+rtrim$(udtename(i2));udtesize(i2);udtebytealign(i2);udtxsize(i)

                            GOTO finishedlinepp

                        END IF 'definingtype


                        'DEFINE
                        d = 0
                        IF firstelement$ = "DEFINT" THEN d = 1
                        IF firstelement$ = "DEFLNG" THEN d = 1
                        IF firstelement$ = "DEFSNG" THEN d = 1
                        IF firstelement$ = "DEFDBL" THEN d = 1
                        IF firstelement$ = "DEFSTR" THEN d = 1
                        IF firstelement$ = "_DEFINE" THEN d = 1
                        IF d THEN
                            predefining = 1: GOTO predefine
                            predefined: predefining = 0
                            GOTO finishedlinepp
                        END IF

'declare library
if firstelement$="DECLARE" and (secondelement$="LIBRARY" or secondelement$="DYNAMIC") then
declaringlibrary=1
GOTO finishedlinepp
end if

                        'SUB/FUNCTION
                        declaresubfunc:
                        firstelement$ = getelement$(a$, 1)
                        sf = 0
                        IF firstelement$ = "FUNCTION" THEN sf = 1
                        IF firstelement$ = "SUB" THEN sf = 2
                        IF sf THEN
                            IF n = 1 THEN a$ = "Expected name after SUB/FUNCTION": GOTO errmes

                            'convert periods to _046_
                            i2 = INSTR(a$, sp + "." + sp)
                            IF i2 THEN
                                DO
                                    a$ = LEFT$(a$, i2 - 1) + fix046$ + RIGHT$(a$, LEN(a$) - i2 - 2)
                                    ca$ = LEFT$(ca$, i2 - 1) + fix046$ + RIGHT$(ca$, LEN(ca$) - i2 - 2)
                                    i2 = INSTR(a$, sp + "." + sp)
                                LOOP UNTIL i2 = 0
                                n = numelements(a$)
                                firstelement$ = getelement(a$, 1): secondelement$ = getelement(a$, 2): thirdelement$ = getelement(a$, 3)
                            END IF

                            n$ = getelement$(ca$, 2)
                            symbol$ = removesymbol$(n$)
                            IF sf = 2 AND symbol$ <> "" THEN a$ = "Type symbols after a SUB name are invalid": GOTO errmes

                            'remove STATIC (which is ignored)
                            e$ = getelement$(a$, n): IF e$ = "STATIC" THEN a$ = LEFT$(a$, LEN(a$) - 7): ca$ = LEFT$(ca$, LEN(ca$) - 7): n = n - 1

'check for ALIAS
aliasname$=n$ 'use given name by default
if n>2 then
e$ = getelement$(a$, 3)
if e$="ALIAS" then
if declaringlibrary=0 then a$ = "ALIAS can only be used with DECLARE LIBRARY": GOTO errmes
if n=3 then a$ = "Expected ALIAS name-in-library": GOTO errmes
e$ = getelement$(ca$, 4)
 'strip string content (optional)
 if left$(e$,1)=chr$(34) then
 e$=right$(e$,len(e$)-1)
 x=instr(e$,chr$(34)): if x=0 then a$ = "Expected "+chr$(34): GOTO errmes
 e$=left$(e$,x-1)
 end if
'validate alias name
if isvalidvariable(e$)=0 or len(e$)=0 then a$ = "Expected ALIAS name-in-library": GOTO errmes
for x=1 to len(e$)
if alphanumeric(asc(e$,x))=0 then a$ = "Expected ALIAS name-in-library": GOTO errmes
next
aliasname$=e$
 'remove ALIAS section from line
 if n<=4 then a$=getelements(a$, 1, 2)
 if n>=5 then a$=getelements(a$, 1, 2)+sp+getelements(a$, 5, n)
 if n<=4 then ca$=getelements(ca$, 1, 2)
 if n>=5 then ca$=getelements(ca$, 1, 2)+sp+getelements(ca$, 5, n)
 n=n-2
end if
end if

                            params = 0
                            params$ = ""
                            paramsize$ = ""
                            nele$ = ""
                            nelereq$ = ""
                            IF n > 2 THEN
                                e$ = getelement$(a$, 3)
                                IF e$ <> "(" THEN a$ = "Expected (": GOTO errmes
                                e$ = getelement$(a$, n)
                                IF e$ <> ")" THEN a$ = "Expected )": GOTO errmes
                                IF n < 4 THEN a$ = "Expected ( ... )": GOTO errmes
                                IF n = 4 THEN GOTO nosfparams
                                b = 0
                                a2$ = ""
                                FOR i = 4 TO n - 1
                                    e$ = getelement$(a$, i)
                                    IF e$ = "(" THEN b = b + 1
                                    IF e$ = ")" THEN b = b - 1
                                    IF e$ = "," AND b = 0 THEN
                                        IF i = n - 1 THEN a$ = "Expected , ... )": GOTO errmes
                                        getlastparam:
                                        IF a2$ = "" THEN a$ = "Expected ... ,": GOTO errmes
                                        a2$ = LEFT$(a2$, LEN(a2$) - 1)
                                        'possible format: [BYVAL]a[%][(1)][AS][type]
                                        n2 = numelements(a2$)
                                        array = 0
                                        t2$ = ""

					i2=1
                                        e$ = getelement$(a2$, i2): i2=i2+1

					byvalue=0
                                        if e$="BYVAL" then
					if declaringlibrary=0 then a$ = "BYVAL can currently only be used with DECLARE LIBRARY": GOTO errmes
e$=getelement$(a2$, i2): i2=i2+1:byvalue=1
end if

                                        n2$ = e$
                                        symbol2$ = removesymbol$(n2$)
                                        m = 0
                                        FOR i2 = i2 TO n2
                                            e$ = getelement$(a2$, i2)
                                            IF e$ = "(" THEN
                                                IF m <> 0 THEN a$ = "Syntax error": GOTO errmes
                                                m = 1
                                                array = 1
                                                GOTO gotaa
                                            END IF
                                            IF e$ = ")" THEN
                                                IF m <> 1 THEN a$ = "Syntax error": GOTO errmes
                                                m = 2
                                                GOTO gotaa
                                            END IF
                                            IF e$ = "AS" THEN
                                                IF m <> 0 AND m <> 2 THEN a$ = "Syntax error": GOTO errmes
                                                m = 3
                                                GOTO gotaa
                                            END IF
                                            IF m = 1 THEN GOTO gotaa 'ignore contents of bracket
                                            IF m <> 3 THEN a$ = "Syntax error": GOTO errmes
                                            IF t2$ = "" THEN t2$ = e$ ELSE t2$ = t2$ + " " + e$
                                            gotaa:
                                        NEXT i2

                                        params = params + 1
                                        argnelereq = 0

                                        IF symbol2$ <> "" AND t2$ <> "" THEN a$ = "Syntax error": GOTO errmes
                                        IF t2$ = "" THEN t2$ = symbol2$
                                        IF t2$ = "" THEN
                                            IF LEFT$(n2$, 1) = "_" THEN v = 27 ELSE v = ASC(UCASE$(n2$)) - 64
                                            t2$ = defineaz(v)
                                        END IF

                                        paramsize = 0
                                        IF array = 1 THEN
                                            t = typname2typ(t2$)
                                            IF t = 0 THEN a$ = "Illegal SUB/FUNCTION parameter": GOTO errmes
                                            IF (t AND ISFIXEDLENGTH) THEN paramsize = typname2typsize
                                            t = t + ISARRAY
                                            'check for recompilation override
                                            FOR i10 = 0 TO sflistn
                                                IF sfidlist(i10) = idn + 1 THEN
                                                    IF sfarglist(i10) = params THEN
                                                        argnelereq = sfelelist(i10)
                                                    END IF
                                                END IF
                                            NEXT
                                        ELSE
                                            t = typname2typ(t2$)
                                            IF t = 0 THEN a$ = "Illegal SUB/FUNCTION parameter": GOTO errmes
                                            IF (t AND ISFIXEDLENGTH) THEN paramsize = typname2typsize

if byvalue then
if t AND ISPOINTER then t=t-ISPOINTER
end if

                                        END IF
                                        nelereq$ = nelereq$ + CHR$(argnelereq)

                                        'consider changing 0 in following line too!
                                        nele$ = nele$ + CHR$(0)

                                        paramsize$ = paramsize$ + MKL$(paramsize)
                                        params$ = params$ + MKL$(t)
                                        a2$ = ""
                                    ELSE
                                        a2$ = a2$ + e$ + sp
                                        IF i = n - 1 THEN GOTO getlastparam
                                    END IF
                                NEXT i
                            END IF 'n>2
                            nosfparams:

                            IF sf = 1 THEN
                                'function
                                clearid
                                id.n = n$
                                id.subfunc = 1

                                id.callname = "FUNC_" + UCASE$(n$)
if declaringlibrary then id.callname = aliasname$: id.ccall=1
                                id.args = params
                                id.arg = params$
                                id.argsize = paramsize$
                                id.nele = nele$
                                id.nelereq = nelereq$
                                IF symbol$ <> "" THEN
                                    id.ret = typname2typ(symbol$)
                                ELSE
                                    IF LEFT$(n$, 1) = "_" THEN v = 27 ELSE v = ASC(UCASE$(n$)) - 64
                                    symbol$ = defineaz(v)
                                    id.ret = typname2typ(symbol$)
                                END IF
                                IF id.ret = 0 THEN a$ = "Invalid FUNCTION return type": GOTO errmes

				ctype$ = typ2ctyp$(id.ret, "")
				if declaringlibrary then id.callname = "("+ctype$+")"+rtrim$(id.callname)

                                s$ = LEFT$(symbol$, 1)
                                IF s$ <> "~" AND s$ <> "`" AND s$ <> "%" AND s$ <> "&" AND s$ <> "!" AND s$ <> "#" AND s$ <> "$" THEN
                                    symbol$ = type2symbol$(symbol$)
                                END IF
                                id.mayhave = symbol$
                                IF id.ret AND ISPOINTER THEN
                                    IF (id.ret AND ISSTRING) = 0 THEN id.ret = id.ret - ISPOINTER
                                END IF
                                regid
                            ELSE
                                'sub
                                clearid
                                id.n = n$
                                id.subfunc = 2
                                id.callname = "SUB_" + UCASE$(n$)
if declaringlibrary then id.callname = aliasname$: id.ccall=1
                                id.args = params
                                id.arg = params$
                                id.argsize = paramsize$
                                id.nele = nele$
                                id.nelereq = nelereq$
                                regid
                            END IF


                        END IF

                        '========================================
                        finishedlinepp:
                    END IF
                    a$ = ""
                    ca$ = ""
                ELSE
                    IF a$ = "" THEN a$ = e$: ca$ = ce$ ELSE a$ = a$ + sp + e$: ca$ = ca$ + sp + ce$
                END IF
                IF wholelinei <= wholelinen THEN wholelinei = wholelinei + 1: GOTO ppblda
                '----------------------------------------
            END IF 'wholelinei<=wholelinen
        END IF 'wholelinen
    END IF 'len(wholeline$)

    'Include Manager #1
    IF LEN(addmetainclude$) THEN
        a$ = addmetainclude$: addmetainclude$ = "" 'read/clear message
        IF inclevel = 100 THEN qb64error "Too many indwelling INCLUDE files"
        '1. Verify file exists (location is either (a)relative to source file or (b)absolute)
        fh = 99 + inclevel + 1
        FOR try = 1 TO 2
            IF try = 1 THEN
                IF inclevel = 0 THEN
                    IF idemode THEN p$ = idepath$ + pathsep$ ELSE p$ = getfilepath$(sourcefile$)
                ELSE
                    p$ = getfilepath$(incname(inclevel))
                END IF
                f$ = p$ + a$
            END IF
            IF try = 2 THEN f$ = a$
            qberrorhappened = -3
            OPEN f$ FOR INPUT AS #fh
            qberrorhappened3:
            IF qberrorhappened = -3 THEN EXIT FOR
            qberrorhappened = 0
        NEXT
        IF qberrorhappened <> -3 THEN qberrorhappened = 0: qb64error "File " + a$ + " not found"
        inclevel = inclevel + 1: incname$(inclevel) = f$: inclinenumber(inclevel) = 0
    END IF 'fall through to next section...
    '--------------------
    IF inclevel THEN
        fh = 99 + inclevel
        '2. Feed next line
        IF EOF(fh) = 0 THEN
            LINE INPUT #fh, x$
            wholeline$ = x$
            inclinenumber(inclevel) = inclinenumber(inclevel) + 1
            'create extended error string 'incerror$'
            e$ = " in line " + str2(inclinenumber(inclevel)) + " of " + incname$(inclevel) + " included"
            IF inclevel > 1 THEN
                e$ = e$ + " (through "
                FOR x = 1 TO inclevel - 1 STEP 1
                    e$ = e$ + incname$(x)
                    IF x < inclevel - 1 THEN 'a sep is req
                        IF x = inclevel - 2 THEN
                            e$ = e$ + " then "
                        ELSE
                            e$ = e$ + ", "
                        END IF
                    END IF
                NEXT
                e$ = e$ + ")"
            END IF
            incerror$ = e$
            linenumber = linenumber - 1 'lower official linenumber to counter later increment
            IF idemode THEN sendc$ = CHR$(10) + wholeline$: GOTO sendcommand 'passback
            GOTO ideprepass
        END IF
        '3. Close & return control
        CLOSE #fh
        inclevel = inclevel - 1
        'fall through to next section...
    END IF
    '(end manager)



    IF idemode THEN GOTO ideret2
LOOP
if definingtype then definingtype=0 'ignore this error so that auto-formatting can be performed and catch it again later
if declaringlibrary then declaringlibrary=0 'ignore this error so that auto-formatting can be performed and catch it again later

'prepass finished

lineinput3index = 1 'reset input line

'ide specific
ide3:

addmetainclude$ = "" 'reset stray meta-includes



'reset altered variables
DataOffset = 0
inclevel = 0

FOR i = 1 TO 27: defineaz(i) = "SINGLE": defineextaz(i) = "!": NEXT

OPEN tmpdir$+"data.bin" FOR OUTPUT AS #16: CLOSE #16
OPEN tmpdir$+"data.bin" FOR BINARY AS #16


OPEN tmpdir$ + "main.txt" FOR OUTPUT AS #12
OPEN tmpdir$ + "maindata.txt" FOR OUTPUT AS #13

OPEN tmpdir$ + "regsf.txt" FOR OUTPUT AS #17
OPEN tmpdir$ + "mainfree.txt" FOR OUTPUT AS #19
OPEN tmpdir$ + "runline.txt" FOR OUTPUT AS #21

OPEN tmpdir$ + "mainerr.txt" FOR OUTPUT AS #14 'main error handler
'i. check the value of error_line
'ii. jump to the appropriate label
errorlabels = 0
PRINT #14, "if (error_occurred){ error_occurred=0;"

OPEN tmpdir$ + "chain.txt" FOR OUTPUT AS #22: CLOSE #22 'will be appended to as necessary
OPEN tmpdir$ + "inpchain.txt" FOR OUTPUT AS #23: CLOSE #23 'will be appended to as necessary
'*** #22 & #23 are reserved for usage by chain & inpchain ***

OPEN tmpdir$ + "ontimer.txt" FOR OUTPUT AS #24
OPEN tmpdir$ + "ontimerj.txt" FOR OUTPUT AS #25
'*****#26 used for locking qb64

gosubid = 1
'to be included whenever return without a label is called

'return [label] in QBASIC was not possible in a sub/function, but QB64 will support this
'special codes will represent special return conditions:
'0=return from main to calling sub/function/proc by return NULL;
'1... a global number representing a return point after a gosub
'note: RETURN [label] should fail if a "return NULL;" type return is required
OPEN tmpdir$ + "ret0.txt" FOR OUTPUT AS #15
PRINT #15, "if (next_return_point){"
PRINT #15, "next_return_point--;"
PRINT #15, "switch(return_point[next_return_point]){"
PRINT #15, "case 0:"
PRINT #15, "return NULL;"
PRINT #15, "break;"

continueline = 0
endifs = 0
lineelseused = 0
continuelinefrom = 0
linenumber = 0

PRINT #12, "S_0:;" 'note: REQUIRED by run statement

'ide specific
IF idemode THEN GOTO ideret3

DO
    ide4:
    includeline:
    prepass=0

    stringprocessinghappened = 0

    IF continuelinefrom THEN
        start = continuelinefrom
        continuelinefrom = 0
        GOTO contline
    END IF

    'begin a new line

    impliedendif = 0
    THENGOTO = 0
    continueline = 0
    endifs = 0
    lineelseused = 0
    newif = 0

    'apply metacommands from previous line
    IF addmetadynamic = 1 THEN addmetadynamic = 0: dynamic = 1
    IF addmetastatic = 1 THEN addmetastatic = 0: dynamic = 0

    'a3$ is passed in idemode and when using $include
    IF idemode = 0 AND inclevel = 0 THEN a3$ = lineinput3$
    IF a3$ = CHR$(13) THEN EXIT DO
    linenumber = linenumber + 1

    layout = ""
    layoutok = 1

    IF idemode = 0 THEN
        IF LEN(a3$) THEN
            dotlinecount = dotlinecount + 1: IF dotlinecount >= 100 THEN dotlinecount = 0: PRINT ".";
        END IF
    END IF

    a3$ = LTRIM$(RTRIM$(a3$))
    wholeline = a3$

    layoutoriginal$ = a3$
    layoutcomment$ = "" 'clear any previous layout comment
    lhscontrollevel = controllevel

    linefragment = "[INFORMATION UNAVAILABLE]"
    IF LEN(a3$) = 0 THEN GOTO finishednonexec
    IF debug THEN PRINT #9, "########" + a3$ + "########"

    layoutdone = 1 'validates layout of any following goto finishednonexec/finishedline

    'QB64 Metacommands
    IF ASC(a3$) = 36 THEN '$

        a3u$ = UCASE$(a3$)

        IF a3u$ = "$CHECKING:OFF" THEN
            layout$ = "$CHECKING:OFF"
            nochecks = 1
            GOTO finishednonexec
        END IF

        IF a3u$ = "$CHECKING:ON" THEN
            layout$ = "$CHECKING:ON"
            nochecks = 0
            GOTO finishednonexec
        END IF

    END IF 'QB64 Metacommands

    linedataoffset = DataOffset

    entireline$ = lineformat(a3$): IF LEN(entireline$) = 0 THEN GOTO finishednonexec
    u$ = UCASE$(entireline$)

    newif = 0

    'Convert "CASE ELSE" to "CASE C-EL" to avoid confusing compiler
    'note: CASE does not have to begin on a new line
    s = 1
    i = INSTR(s, u$, "CASE" + sp + "ELSE")
    DO WHILE i
        skip = 0
        IF i <> 1 THEN
            IF MID$(u$, i - 1, 1) <> sp THEN skip = 1
        END IF
        IF i <> LEN(u$) - 8 THEN
            IF MID$(u$, i + 9, 1) <> sp THEN skip = 1
        END IF
        IF skip = 0 THEN
            MID$(entireline$, i) = "CASE" + sp + "C-EL"
            u$ = UCASE$(entireline$)
        END IF
        s = i + 9
        i = INSTR(s, u$, "CASE" + sp + "ELSE")
    LOOP

    n = numelements(entireline$)

    'line number?
    a = ASC(entireline$)
    IF (a >= 48 AND a <= 57) OR a = 46 THEN 'numeric
        label$ = getelement(entireline$, 1)
        IF validlabel(label$) THEN

v=HashFind(label$,HASHFLAG_LABEL,ignore,r)
addlabchk100: 
if v then
s=labels(r).scope
if s=subfuncn or s=-1 then 'same scope?
if s=-1 then labels(r).scope=subfuncn 'acquire scope
if labels(r).state=1 then a$ = "Duplicate label": GOTO errmes
'aquire state 0 types
tlayout$=rtrim$(labels(r).cn)
goto addlabaq100
end if 'same scope
if v=2 then v=HashFindCont(ignore,r): goto addlabchk100
end if
'does not exist
nLabels=nLabels+1: if nLabels>Labels_Ubound then Labels_Ubound=Labels_Ubound*2: redim _preserve Labels(1 to Labels_Ubound) as Label_Type
Labels(nLabels)=Empty_label
hashadd label$,HASHFLAG_LABEL,nLabels
r=nLabels
Labels(r).cn=tlayout$
Labels(r).scope=subfuncn
addlabaq100:
Labels(r).state=1
Labels(r).Data_Offset=linedataoffset

            layout$ = tlayout$
            PRINT #12, "LABEL_" + label$ + ":;"
            
            IF INSTR(label$, "p") THEN MID$(label$, INSTR(label$, "p"), 1) = "."
            PRINT #12, "last_line=" + label$ + ";"
            IF n = 1 THEN GOTO finishednonexec
            entireline$ = getelements(entireline$, 2, n): u$ = UCASE$(entireline$): n = n - 1
            'note: fall through, numeric labels can be followed by alphanumeric label
        END IF 'validlabel
    END IF 'numeric
    'it wasn't a line number

    'label?
    'note: ignores possibility that this could be a single command SUB/FUNCTION (as in QBASIC?)
    IF n >= 2 THEN
        x2 = INSTR(entireline$, sp + ":")
        IF x2 THEN
            IF x2 = LEN(entireline$) - 1 THEN x3 = x2 + 1 ELSE x3 = x2 + 2
            a$ = LEFT$(entireline$, x2 - 1)
            IF validlabel(a$) THEN
                



v=HashFind(a$,HASHFLAG_LABEL,ignore,r)
addlabchk: 
if v then
s=labels(r).scope
if s=subfuncn or s=-1 then 'same scope?
if s=-1 then labels(r).scope=subfuncn 'acquire scope
if labels(r).state=1 then a$ = "Duplicate label": GOTO errmes
'aquire state 0 types
tlayout$=rtrim$(labels(r).cn)
goto addlabaq
end if 'same scope
if v=2 then v=HashFindCont(ignore,r): goto addlabchk
end if
'does not exist
nLabels=nLabels+1: if nLabels>Labels_Ubound then Labels_Ubound=Labels_Ubound*2: redim _preserve Labels(1 to Labels_Ubound) as Label_Type
Labels(nLabels)=Empty_label
hashadd a$,HASHFLAG_LABEL,nLabels
r=nLabels
Labels(r).cn=tlayout$
Labels(r).scope=subfuncn
addlabaq:
Labels(r).state=1
Labels(r).Data_Offset=linedataoffset


		IF LEN(layout$) THEN layout$ = layout$ + sp + tlayout$ + ":" ELSE layout$ = tlayout$ + ":"

                PRINT #12, "LABEL_" + a$ + ":;"

                entireline$ = RIGHT$(entireline$, LEN(entireline$) - x3): u$ = UCASE$(entireline$)
                n = numelements(entireline$): IF n = 0 THEN GOTO finishednonexec
            END IF 'valid
        END IF 'includes sp+":"
    END IF 'n>=2

    'remove leading ":"
    DO WHILE ASC(u$) = 58 '":"
        IF LEN(layout$) THEN layout$ = layout$ + sp2 + ":" ELSE layout$ = ":"
        IF LEN(u$) = 1 THEN GOTO finishednonexec
        entireline$ = getelements(entireline$, 2, n): u$ = UCASE$(entireline$): n = n - 1
    LOOP

    'ELSE at the beginning of a line
    IF ASC(u$) = 69 THEN '"E"

        e1$ = getelement(u$, 1)

        IF e1$ = "ELSE" THEN
            a$ = "ELSE"
            IF n > 1 THEN continuelinefrom = 2
            GOTO gotcommand
        END IF

        IF e1$ = "ELSEIF" THEN
            IF n < 3 THEN a$ = "Expected ... THEN": GOTO errmes
            IF getelement(u$, n) = "THEN" THEN a$ = entireline$: GOTO gotcommand
            FOR i = 3 TO n - 1
                IF getelement(u$, i) = "THEN" THEN
                    a$ = getelements(entireline$, 1, i)
                    continuelinefrom = i + 1
                    GOTO gotcommand
                END IF
            NEXT
            a$ = "Expected THEN": GOTO errmes
        END IF

    END IF '"E"

    start = 1

    GOTO skipcontinit

    contline:

    n = numelements(entireline$)
    u$ = UCASE$(entireline$)

    skipcontinit:

    'jargon:
    'lineelseused - counts how many line ELSEs can POSSIBLY follow
    'endifs - how many C++ endifs "}" need to be added at the end of the line
    'lineelseused - counts the number of indwelling ELSE statements on a line
    'impliedendif - stops autoformat from adding "END IF"

    a$ = ""

    FOR i = start TO n
        e$ = getelement(u$, i)


        IF e$ = ":" THEN
            IF i = start THEN
                layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp2 + ":" ELSE layout$ = ":"
                IF i <> n THEN continuelinefrom = i + 1
                GOTO finishednonexec
            END IF
            IF i <> n THEN continuelinefrom = i
            GOTO gotcommand
        END IF


        'begin scanning an 'IF' statement
        IF e$ = "IF" AND a$ = "" THEN newif = 1


        IF e$ = "THEN" OR (e$ = "GOTO" AND newif = 1) THEN
            newif = 0
            IF lineelseused > 0 THEN lineelseused = lineelseused - 1
            IF e$ = "GOTO" THEN
                IF i = n THEN a$ = "Expected IF expression GOTO label": GOTO errmes
                i = i - 1
            END IF
            a$ = a$ + sp + e$ '+"THEN"/"GOTO"
            IF i <> n THEN continuelinefrom = i + 1: endifs = endifs + 1
            GOTO gotcommand
        END IF


        IF e$ = "ELSE" THEN

            IF start = i THEN
                IF lineelseused >= 1 THEN
                    'note: more than one else used (in a row) on this line, so close first if with an 'END IF' first
                    'note: parses 'END IF' then (after continuelinefrom) parses 'ELSE'
                    'consider the following: (square brackets make reading easier)
                    'eg. if a=1 then [if b=2 then c=2 else d=2] else e=3
                    impliedendif = 1: a$ = "END" + sp + "IF"
                    endifs = endifs - 1
                    continuelinefrom = i
                    lineelseused = lineelseused - 1
                    GOTO gotcommand
                END IF
                'follow up previously encountered 'ELSE' by applying 'ELSE'
                a$ = "ELSE": continuelinefrom = i + 1
                lineelseused = lineelseused + 1
                GOTO gotcommand
            END IF 'start=i

            'apply everything up to (but not including) 'ELSE'
            continuelinefrom = i
            GOTO gotcommand
        END IF '"ELSE"


        e$ = getelement(entireline$, i): IF a$ = "" THEN a$ = e$ ELSE a$ = a$ + sp + e$
    NEXT


    'we're reached the end of the line
    IF endifs > 0 THEN
        endifs = endifs - 1
        impliedendif = 1: entireline$ = entireline$ + sp + ":" + sp + "END" + sp + "IF": n = n + 3
        i = i + 1 'skip the ":" (i is now equal to n+2)
        continuelinefrom = i
        GOTO gotcommand
    END IF


    gotcommand:

    dynscope = 0

    ca$ = a$
    a$ = eleucase$(ca$) '***REVISE THIS SECTION LATER***


    layoutdone = 0

    linefragment = a$
    IF debug THEN PRINT #9, a$
    n = numelements(a$)
    IF n = 0 THEN GOTO finishednonexec

    'convert non-UDT dimensioned periods to _046_
    IF INSTR(ca$, sp + "." + sp) THEN
        a3$ = getelement(ca$, 1)
        except = 0
        aa$ = a3$ + sp 'rebuilt a$ (always has a trailing spacer)
        FOR x = 2 TO n
            a2$ = getelement(ca$, x)
            IF except = 1 THEN except = 2: GOTO udtperiod 'skip element name
            IF a2$ = "." AND x <> n THEN
                IF except = 2 THEN except = 1: GOTO udtperiod 'sub-element of UDT

                IF a3$ = ")" THEN
                    'assume it was something like typevar(???).x and treat as a UDT
                    except = 1
                    GOTO udtperiod
                END IF

                'find an ID of that type
                try = findid(UCASE$(a3$))
                DO WHILE try
                    IF ((id.t AND ISUDT) <> 0) OR ((id.arraytype AND ISUDT) <> 0) THEN
                        except = 1
                        GOTO udtperiod
                    END IF
                    IF try = 2 THEN findanotherid = 1: try = findid(UCASE$(a3$)) ELSE try = 0
                LOOP
                'not a udt; fuse lhs & rhs with _046_
                aa$ = LEFT$(aa$, LEN(aa$) - 1) + fix046$
                GOTO periodfused
            END IF '"."
            except = 0
            udtperiod:
            aa$ = aa$ + a2$ + sp
            periodfused:
            a3$ = a2$
        NEXT
        a$ = LEFT$(aa$, LEN(aa$) - 1)
        ca$ = a$
        a$ = eleucase$(ca$)
        n = numelements(a$)
    END IF

    arrayprocessinghappened = 0

    firstelement$ = getelement(a$, 1)
    secondelement$ = getelement(a$, 2)
    thirdelement$ = getelement(a$, 3)

    'non-executable section

if n=1 then
if firstelement$="'" then layoutdone = 1: GOTO finishednonexec 'nop
end if

    IF n <= 2 THEN
        IF firstelement$ = "DATA" THEN
            l$ = firstelement$
            if n=2 then

e$=space$((len(secondelement$)-1)\2)
for x=1 to len(e$)
v1=asc(secondelement$,x*2)
v2=asc(secondelement$,x*2+1)
if v1<65 then v1=v1-48 else v1=v1-55
if v2<65 then v2=v2-48 else v2=v2-55
asc(e$,x)=v1+v2*16
next
l$=l$+sp+e$
end if 'n=2

        layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$

            GOTO finishednonexec
        END IF
    END IF



'declare library
if declaringlibrary then

if firstelement$="END" then
if n<>2 or secondelement$<>"DECLARE" then a$ = "Expected END DECLARE": GOTO errmes
declaringlibrary=0
l$="END"+sp+"DECLARE"
layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
GOTO finishednonexec
end if 'end declare

declaringlibrary=2

if firstelement$="SUB" or firstelement$="FUNCTION" then 
GOTO declaresubfunc2
end if

a$ = "Expected SUB/FUNCTION definition or END DECLARE": GOTO errmes
end if 'declaringlibrary



    'check TYPE declarations (created on prepass)
    IF firstelement$ = "TYPE" THEN
        IF n <> 2 THEN qb64error "Expected TYPE type-name"
        l$ = "TYPE" + sp + getelement(ca$, 2)
        layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
        definingtype = 1
        definingtypeerror = linenumber
        GOTO finishednonexec
    END IF

    IF definingtype THEN
    
        IF firstelement$ = "END" THEN
            IF n <> 2 OR secondelement$ <> "TYPE" THEN qb64error "Expected END TYPE"
            definingtype = 0
            l$ = "END" + sp + "TYPE"
            layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
            GOTO finishednonexec
        END IF
                
        IF n < 3 OR secondelement$ <> "AS" THEN qb64error "Expected element-name AS type-name"
        definingtype = 2
        l$ = getelement(ca$, 1) + sp + "AS"
        t$ = getelements$(a$, 3, n)
        typ = typname2typ(t$)
        IF typ = 0 THEN a$ = "Undefined type": GOTO errmes
        IF typ AND ISUDT THEN
            t$ = RTRIM$(udtxcname(typ AND 511))
        END IF
        l$ = l$ + sp + t$
        layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
        GOTO finishednonexec

    END IF 'defining type

    'skip DECLARE SUB/FUNCTION
    IF n >= 1 THEN
        IF firstelement$ = "DECLARE" THEN

if secondelement$="LIBRARY" or secondelement$="DYNAMIC" then

declaringlibrary=1
dynamiclibrary=0

x=3
l$="DECLARE"+sp+"LIBRARY"

if secondelement$="DYNAMIC" then
e$=getelement$(a$,3): if e$<>"LIBRARY" then a$="Expected DYNAMIC LIBRARY "+chr$(34)+"..."+chr$(34): GOTO errmes
dynamiclibrary=1
x=4
l$="DECLARE"+sp+"DYNAMIC"+sp+"LIBRARY"
if n=3 then a$ = "Expected DECLARE DYNAMIC LIBRARY "+chr$(34)+"..."+chr$(34): GOTO errmes
end if

sfdeclare=0

if n>=x then

sfdeclare=1

addlibrary:

libname$=""
headername$=""

'assume library name in double quotes follows
'assume library is in main qb64 folder
x$=getelement$(ca$,x)
if asc(x$)<>34 then a$ = "Expected LIBRARY "+chr$(34)+"..."+chr$(34): GOTO errmes
x$=right$(x$,len(x$)-1)
z=instr(x$,chr$(34))
if z=0 then a$ = "Expected LIBRARY "+chr$(34)+"..."+chr$(34): GOTO errmes
x$=left$(x$,z-1)

if dynamiclibrary<>0 and len(x$)=0 then a$ = "Expected DECLARE DYNAMIC LIBRARY "+chr$(34)+"..."+chr$(34): GOTO errmes

'***handle \\ and other C++ string exceptions here***
purex$=x$
while instr(x$,"\\")
z=instr(x$,"\\")
x$=left$(x$,z-1)+right$(x$,len(x$)-z)
wend

if len(x$) then

if dynamiclibrary=0 then

'check for .lib
if len(libname$)=0 then
f=FREEFILE
open x$+".lib" for binary as #f
if lof(f) then
close #f
libname$=x$+".lib"
else
close #f
kill x$+".lib"
end if
end if

'check for .a
if len(libname$)=0 then
f=FREEFILE
open x$+".a" for binary as #f
if lof(f) then
close #f
libname$=x$+".a"
else
close #f
kill x$+".a"
end if
end if

'check for .o
if len(libname$)=0 then
f=FREEFILE
open x$+".o" for binary as #f
if lof(f) then
close #f
libname$=x$+".o"
else
close #f
kill x$+".o"
end if
end if

else

'check for .dll
if len(libname$)=0 then
f=FREEFILE
open x$+".dll" for binary as #f
if lof(f) then
close #f
libname$=x$+".dll"
else
close #f
kill x$+".dll"
end if
end if

'check for .dll
if len(libname$)=0 then
f=FREEFILE
open ENVIRON$("SYSTEMROOT")+"\System32\"+x$+".dll" for binary as #f
if lof(f) then
close #f
libname$=x$+".dll"
else
close #f
kill x$+".dll"
end if
end if

end if

'check for .h
if len(headername$)=0 then
f=FREEFILE
open x$+".h" for binary as #f
if lof(f) then
close #f
headername$=purex$+".h"
sfdeclare=0
else
close #f
kill x$+".h"
end if
end if

'library found?
if len(libname$)=0 and len(headername$)=0 then a$ = "LIBRARY not found": GOTO errmes

'***actual method should cull redundant header and library entries***

if dynamiclibrary=0 then

'static
if len(libname$) then
mylib$=mylib$+" ..\..\"+libname$+" "
end if

else

'dynamic
if len(headername$)=0 then 'no header
IF subfuncn then
f=FREEFILE
OPEN tmpdir$ + "maindata.txt" FOR APPEND AS #f
else
f=13
end if

'make name a C-appropriate variable name
'by converting everything except numbers and
'letters to underscores
x2$=x$
for x2=1 to len(x2$)
if asc(x2$,x2)<48 then asc(x2$,x2)=95
if asc(x2$,x2)>57 and asc(x2$,x2)<65 then asc(x2$,x2)=95
if asc(x2$,x2)>90 and asc(x2$,x2)<97 then asc(x2$,x2)=95
if asc(x2$,x2)>122 then asc(x2$,x2)=95
next
DLLname$=x2$

if sfdeclare then

print #17, "HINSTANCE DLL_"+x2$+";"

print #f, "HINSTANCE DLL_"+x2$+"=LoadLibrary("+chr$(34)+libname$+chr$(34)+");"

end if

IF subfuncn then close #f

end if 'no header

end if 'dynamiclibrary

if len(headername$) then
print #17,"#include "+chr$(34)+"..\\..\\"+headername$+chr$(34)
end if

end if

l$=l$+sp+chr$(34)+x$+chr$(34)

if n>x then
if dynamiclibrary then a$ = "Cannot specify multiple DYNAMIC LIBRARY names in a single DECLARE statement": GOTO errmes
x=x+1: x2$=getelement$(a$,x): if x2$<>"," then a$ = "Expected ,": GOTO errmes
l$=l$+sp2+","
x=x+1: if x>n then a$ ="Expected , ...": GOTO errmes
goto addlibrary
end if

end if 'n>=x

layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
GOTO finishednonexec
end if

        GOTO finishednonexec 'note: no layout required
        END IF
    END IF

    'begin SUB/FUNCTION
    IF n >= 1 THEN
        declaresubfunc2:
        sf = 0
        IF firstelement$ = "FUNCTION" THEN sf = 1
        IF firstelement$ = "SUB" THEN sf = 2
        IF sf THEN

            if len(subfunc) then a$ = "Expected END SUB/FUNCTION before "+firstelement$: GOTO errmes

            IF n = 1 THEN a$ = "Expected name after SUB/FUNCTION": GOTO errmes
            e$ = getelement$(ca$, 2)
            symbol$ = removesymbol$(e$) '$,%,etc.
            IF sf = 2 AND symbol$ <> "" THEN a$ = "Type symbols after a SUB name are invalid": GOTO errmes
            try = findid(e$)
            DO WHILE try
                IF id.subfunc = sf THEN GOTO createsf
                IF try = 2 THEN findanotherid = 1: try = findid(e$) ELSE try = 0
            LOOP
            a$ = "Unregistered SUB/FUNCTION encountered": GOTO errmes
            createsf:
            l$ = firstelement$ + sp + e$ + symbol$
            id2 = id
            targetid = currentid

'check for ALIAS
if n>2 then
ee$ = getelement$(a$, 3)
if ee$="ALIAS" then
if declaringlibrary=0 then a$ = "ALIAS can only be used with DECLARE LIBRARY": GOTO errmes
if n=3 then a$ = "Expected ALIAS name-in-library": GOTO errmes
ee$ = getelement$(ca$, 4)
 'strip string content (optional)
 if left$(ee$,1)=chr$(34) then
 ee$=right$(ee$,len(ee$)-1)
 x=instr(ee$,chr$(34)): if x=0 then a$ = "Expected "+chr$(34): GOTO errmes
 ee$=left$(ee$,x-1)
 end if
l$=l$+sp+"ALIAS"+sp+ee$
 'remove ALIAS section from line
 if n<=4 then a$=getelements(a$, 1, 2)
 if n>=5 then a$=getelements(a$, 1, 2)+sp+getelements(a$, 5, n)
 if n<=4 then ca$=getelements(ca$, 1, 2)
 if n>=5 then ca$=getelements(ca$, 1, 2)+sp+getelements(ca$, 5, n)
 n=n-2
end if
end if

if declaringlibrary then goto declibjmp1


            IF closedmain = 0 THEN closemain

'check for open controls (copy #2)
if controllevel then
x=controltype(controllevel)
if x=1 then a$="IF without ENDIF"
if x=2 then a$="FOR without NEXT"
if x=3 or x=4 then a$="DO without LOOP"
if x=5 then a$="WHILE without WEND"
if (x>=10 and x<=17) or x=18 or x=19 then a$="SELECT CASE without END SELECT"
linenumber=controlref(controllevel)
GOTO errmes
end if

            subfuncn = subfuncn + 1
            CLOSE #13: OPEN tmpdir$ + "data" + str2$(subfuncn) + ".txt" FOR OUTPUT AS #13
            CLOSE #19: OPEN tmpdir$ + "free" + str2$(subfuncn) + ".txt" FOR OUTPUT AS #19
            CLOSE #15: OPEN tmpdir$ + "ret" + str2$(subfuncn) + ".txt" FOR OUTPUT AS #15
            PRINT #15, "if (next_return_point){"
            PRINT #15, "next_return_point--;"
            PRINT #15, "switch(return_point[next_return_point]){"
            PRINT #15, "case 0:"
            PRINT #15, "error(3);" 'return without gosub!
            PRINT #15, "break;"
            defdatahandle = 13


            subfunc = RTRIM$(id.callname) 'SUB_..."
            subfuncret$ = ""

declibjmp1:

if declaringlibrary then
if sfdeclare=0 then
close #17
OPEN tmpdir$ + "regsf_ignore.txt" FOR OUTPUT AS #17
end if
end if




            IF sf = 1 THEN
                rettyp = id.ret
                t$ = typ2ctyp$(id.ret, "")
                IF t$ = "qbs" THEN t$ = "qbs*"

if declaringlibrary then
if rettyp AND ISSTRING then
a$ = "LIBRARY FUNCTIONs cannot return a STRING": GOTO errmes
end if
end if

if dynamiclibrary then
		print #17, "typedef "+t$+" (CALLBACK* DLLCALL_"+ removecast$(RTRIM$(id.callname))+")(";
else
                PRINT #17, t$ + " " + removecast$(RTRIM$(id.callname)) + "(";
end if
if declaringlibrary then goto declibjmp2
                PRINT #12, t$ + " " + removecast$(RTRIM$(id.callname)) + "(";

                'create variable to return result
                'if type wasn't specified, define it
                IF symbol$ = "" THEN
                    a = ASC(UCASE$(e$)): IF a = 95 THEN a = 91
                    a = a - 64 'so A=1, Z=27 and _=28
                    symbol$ = defineextaz(a)
                END IF
                ignore = dim2(e$, symbol$, 0, "")
                'the following line stops the return variable from being free'd before being returned
                CLOSE #19: OPEN tmpdir$ + "free" + str2$(subfuncn) + ".txt" FOR OUTPUT AS #19
                'create return
                IF (rettyp AND ISSTRING) THEN
                    r$ = refer$(str2$(currentid), id.t, 1)
                    subfuncret$ = subfuncret$ + "qbs_maketmp(" + r$ + ");"
                    subfuncret$ = subfuncret$ + "return " + r$ + ";"
                ELSE
                    r$ = refer$(str2$(currentid), id.t, 0)
                    subfuncret$ = "return " + r$ + ";"
                END IF
            ELSE

if dynamiclibrary then
		print #17, "typedef void (CALLBACK* DLLCALL_"+ removecast$(RTRIM$(id.callname))+")(";
else
                PRINT #17, "void " + removecast$(RTRIM$(id.callname)) + "(";
end if
if declaringlibrary then goto declibjmp2
                PRINT #12, "void " + removecast$(RTRIM$(id.callname)) + "(";

            END IF
declibjmp2:

            addstatic2layout = 0
            staticsf = 0
            e$ = getelement$(a$, n)
            IF e$ = "STATIC" THEN
if declaringlibrary then a$ = "STATIC cannot be used in a library declaration": GOTO errmes
                addstatic2layout = 1
                staticsf = 2
                a$ = LEFT$(a$, LEN(a$) - 7): n = n - 1 'remove STATIC
            END IF

            'check items to pass
            params = 0
            IF n > 2 THEN
                e$ = getelement$(a$, 3)
                IF e$ <> "(" THEN a$ = "Expected (": GOTO errmes
                e$ = getelement$(a$, n)
                IF e$ <> ")" THEN a$ = "Expected )": GOTO errmes
                l$ = l$ + sp + "("
                IF n = 4 THEN GOTO nosfparams2
                IF n < 4 THEN a$ = "Expected ( ... )": GOTO errmes
                b = 0
                a2$ = ""
                FOR i = 4 TO n - 1
                    e$ = getelement$(ca$, i)
                    IF e$ = "(" THEN b = b + 1
                    IF e$ = ")" THEN b = b - 1
                    IF e$ = "," AND b = 0 THEN
                        IF i = n - 1 THEN a$ = "Expected , ... )": GOTO errmes
                        getlastparam2:
                        IF a2$ = "" THEN a$ = "Expected ... ,": GOTO errmes
                        a2$ = LEFT$(a2$, LEN(a2$) - 1)
                        'possible format: [BYVAL]a[%][(1)][AS][type]
                        params = params + 1
                        glinkid = targetid
                        glinkarg = params



                        IF params > 1 THEN
                            PRINT #17, ",";

if declaringlibrary=0 then
                            PRINT #12, ",";
end if

                        END IF
                        n2 = numelements(a2$)
                        array = 0
                        t2$ = ""
                        e$ = getelement$(a2$, 1)

byvalue=0
if ucase$(e$)="BYVAL" then
if declaringlibrary=0 then a$ = "BYVAL can currently only be used with DECLARE LIBRARY": GOTO errmes
byvalue=1: a2$=right$(a2$,len(a2$)-6)
IF RIGHT$(l$, 1) = "(" THEN l$ = l$ + sp2 + "BYVAL" ELSE l$ = l$ + sp + "BYVAL"
n2 = numelements(a2$): e$ = getelement$(a2$, 1)
end if


                        IF RIGHT$(l$, 1) = "(" THEN l$ = l$ + sp2 + e$ ELSE l$ = l$ + sp + e$

                        n2$ = e$
                        dimmethod = 0


                        symbol2$ = removesymbol$(n2$)
                        IF symbol2$ <> "" THEN dimmethod = 1
                        m = 0
                        FOR i2 = 2 TO n2
                            e$ = getelement$(a2$, i2)
                            IF e$ = "(" THEN
                                IF m <> 0 THEN a$ = "Syntax error": GOTO errmes
                                m = 1
                                array = 1
                                l$ = l$ + sp2 + "("
                                GOTO gotaa2
                            END IF
                            IF e$ = ")" THEN
                                IF m <> 1 THEN a$ = "Syntax error": GOTO errmes
                                m = 2
                                l$ = l$ + sp2 + ")"
                                GOTO gotaa2
                            END IF
                            IF UCASE$(e$) = "AS" THEN
                                IF m <> 0 AND m <> 2 THEN a$ = "Syntax error": GOTO errmes
                                m = 3
                                l$ = l$ + sp + "AS"
                                GOTO gotaa2
                            END IF
                            IF m = 1 THEN l$ = l$ + sp + e$: GOTO gotaa2 'ignore contents of option bracket telling how many dimensions (add to layout as is)
                            IF m <> 3 THEN a$ = "Syntax error": GOTO errmes
                            IF t2$ = "" THEN t2$ = e$ ELSE t2$ = t2$ + " " + e$
                            gotaa2:
                        NEXT i2
                        IF symbol2$ <> "" AND t2$ <> "" THEN a$ = "Syntax error": GOTO errmes


                        IF LEN(t2$) THEN 'add type-name after AS
                            t2$ = UCASE$(t2$)
                            t3$ = t2$
                            typ = typname2typ(t3$)
                            IF typ = 0 THEN a$ = "Undefined type": GOTO errmes
                            IF typ AND ISUDT THEN
                                t3$ = RTRIM$(udtxcname(typ AND 511))
                            ELSE
                                FOR t3i = 1 TO LEN(t3i)
                                    IF ASC(t3$, t3i) = 32 THEN ASC(t3$, t3i) = ASC(sp)
                                NEXT
                            END IF
                            l$ = l$ + sp + t3$
                        END IF

                        IF t2$ = "" THEN t2$ = symbol2$
                        IF t2$ = "" THEN
                            IF LEFT$(n2$, 1) = "_" THEN v = 27 ELSE v = ASC(UCASE$(n2$)) - 64
                            t2$ = defineaz(v)
                            dimmethod = 1
                        END IF




                        IF array = 1 THEN
if declaringlibrary then a$ = "Arrays cannot be passed to a library": GOTO errmes
                            dimsfarray = 1
                            'note: id2.nele is currently 0
                            nelereq = ASC(MID$(id2.nelereq, params, 1))
                            IF nelereq THEN
                                nele = nelereq
                                MID$(id2.nele, params, 1) = CHR$(nele)

                                ids(targetid) = id2

                                ignore = dim2(n2$, t2$, dimmethod, str2$(nele))
                            ELSE
                                nele = 1
                                MID$(id2.nele, params, 1) = CHR$(nele)

                                ids(targetid) = id2

                                ignore = dim2(n2$, t2$, dimmethod, "?")
                            END IF

                            dimsfarray = 0
                            r$ = refer$(str2$(currentid), id.t, 1)
                            PRINT #17, "ptrszint*" + r$;
                            PRINT #12, "ptrszint*" + r$;
                        ELSE

if declaringlibrary then
t$ = typ2ctyp$(0, t2$)
if t$="qbs" then
t$="char*"
if byvalue=1 then a$="STRINGs cannot be passed using BYVAL": goto errmes
byvalue=1 'use t$ as is
end if
if byvalue then PRINT #17, t$; else PRINT #17, t$ + "*";
goto declibjmp3
end if

                            dimsfarray = 1
                            ignore = dim2(n2$, t2$, dimmethod, "")
                            dimsfarray = 0
                            t$ = ""
                            typ = id.t 'the typ of the ID created by dim2
                            t$ = typ2ctyp$(typ, "")
                            IF t$ = "" THEN x = 101: GOTO errnum
                            'searchpoint
                            'get the name of the variable
                            r$ = refer$(str2$(currentid), id.t, 1)
                            PRINT #17, t$ + "*" + r$;
                            PRINT #12, t$ + "*" + r$;
                            IF t$ = "qbs" THEN
                                u$ = str2$(uniquenumber)
                                PRINT #13, "qbs*oldstr" + u$ + "=NULL;"
                                PRINT #13, "if(" + r$ + "->tmp||" + r$ + "->fixed||" + r$ + "->readonly){"
                                PRINT #13, "oldstr" + u$ + "=" + r$ + ";"

				PRINT #13, "if (oldstr" + u$+"->cmem_descriptor){"
                                PRINT #13, r$ + "=qbs_new_cmem(oldstr" + u$ + "->len,0);"
                                PRINT #13, "}else{"
                                PRINT #13, r$ + "=qbs_new(oldstr" + u$ + "->len,0);"
                                PRINT #13, "}"

                                PRINT #13, "memcpy(" + r$ + "->chr,oldstr" + u$ + "->chr,oldstr" + u$ + "->len);"
                                PRINT #13, "}"

                                PRINT #19, "if(oldstr" + u$ + "){"
                                PRINT #19, "if(oldstr" + u$ + "->fixed)qbs_set(oldstr" + u$ + "," + r$ + ");"
                                PRINT #19, "qbs_free(" + r$ + ");"
                                PRINT #19, "}"
                            END IF
                        END IF
declibjmp3:
                        IF i <> n - 1 THEN l$ = l$ + sp2 + ","

                        a2$ = ""
                    ELSE
                        a2$ = a2$ + e$ + sp
                        IF i = n - 1 THEN GOTO getlastparam2
                    END IF
                NEXT i
                nosfparams2:
                l$ = l$ + sp2 + ")"
            END IF 'n>2

            IF addstatic2layout THEN l$ = l$ + sp + "STATIC"
            layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$

            PRINT #17, ");"

if declaringlibrary then goto declibjmp4

            PRINT #12, "){"
            PRINT #12, "qbs *tqbs;"
            PRINT #12, "ptrszint tmp_long;"
            PRINT #12, "int32 tmp_fileno;"
            PRINT #12, "uint32 qbs_tmp_base=qbs_tmp_list_nexti;"
            PRINT #12, "uint8 *tmp_mem_static_pointer=mem_static_pointer;"
            PRINT #12, "uint32 tmp_cmem_sp=cmem_sp;"
            PRINT #12, "#include " + CHR$(34) + "data" + str2$(subfuncn) + ".txt" + CHR$(34)
            PRINT #12, "if (new_error) goto exit_subfunc;"

            'statementn = statementn + 1
            'if nochecks=0 then PRINT #12, "S_" + str2$(statementn) + ":;"

            dimstatic = staticsf

declibjmp4:

if declaringlibrary then

if dynamiclibrary then
if sfdeclare then

print #17, "DLLCALL_"+ removecast$(RTRIM$(id2.callname))+" "+removecast$(RTRIM$(id2.callname))+";"

IF subfuncn then
f=FREEFILE
OPEN tmpdir$ + "maindata.txt" FOR APPEND AS #f
else
f=13
end if

print #f, removecast$(RTRIM$(id2.callname))+"=(DLLCALL_"+removecast$(RTRIM$(id2.callname))+")GetProcAddress(DLL_"+DLLname$+","+chr$(34)+removecast$(RTRIM$(id2.callname))+chr$(34)+");"

IF subfuncn then close #f

end if 'sfdeclare
end if 'dynamic

if sfdeclare=0 then
close #17
OPEN tmpdir$ + "regsf.txt" FOR APPEND AS #17
end if

end if 'declaring library

            GOTO finishednonexec
        END IF
    END IF

    'END SUB/FUNCTION
    IF n = 2 THEN
        IF firstelement$ = "END" THEN
            sf = 0
            IF secondelement$ = "FUNCTION" THEN sf = 1
            IF secondelement$ = "SUB" THEN sf = 2
            IF sf THEN

if len(subfunc)=0 then a$="END "+secondelement$+" without "+secondelement$: goto errmes

'check for open controls (copy #3)
if controllevel then
x=controltype(controllevel)
if x=1 then a$="IF without ENDIF"
if x=2 then a$="FOR without NEXT"
if x=3 or x=4 then a$="DO without LOOP"
if x=5 then a$="WHILE without WEND"
if (x>=10 and x<=17) or x=18 or x=19 then a$="SELECT CASE without END SELECT"
linenumber=controlref(controllevel)
GOTO errmes
end if

                l$ = firstelement$ + sp + secondelement$
                layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$

                staticarraylist = "": staticarraylistn = 0 'remove previously listed arrays
                dimstatic = 0
                PRINT #12, "exit_subfunc:;"
                PRINT #12, "#include " + CHR$(34) + "free" + str2$(subfuncn) + ".txt" + CHR$(34)
                PRINT #12, "if ((tmp_mem_static_pointer>=mem_static)&&(tmp_mem_static_pointer<=mem_static_limit)) mem_static_pointer=tmp_mem_static_pointer; else mem_static_pointer=mem_static;"
                PRINT #12, "cmem_sp=tmp_cmem_sp;"
                IF subfuncret$ <> "" THEN PRINT #12, subfuncret$

                PRINT #12, "}" 'skeleton sub
                'ret???.txt
                PRINT #15, "}" 'end case
                PRINT #15, "}"
                PRINT #15, "error(3);" 'no valid return possible
                subfunc = ""
      
                'unshare temp. shared variables
                FOR i = 1 TO idn
                    IF ids(i).share AND 2 THEN ids(i).share = ids(i).share - 2
                NEXT

                FOR i = 1 TO revertmaymusthaven
                    x = revertmaymusthave(i)
                    SWAP ids(x).musthave, ids(x).mayhave
                NEXT
                revertmaymusthaven = 0

                'undeclare constants in sub/function's scope
                constlast = constlastshared
                GOTO finishednonexec

end if
        END IF
    END IF



    IF n >= 1 AND firstelement$ = "CONST" THEN
        l$="CONST"
        'DEF... do not change type, the expression is stored in a suitable type
        'based on its value if type isn't forced/specified
        IF n < 3 THEN a$ = "Expected CONST name = value/expression": GOTO errmes
        i = 2

        constdefpending:
        pending = 0

        n$ = getelement$(ca$, i): i = i + 1
        l$=l$+sp+n$+sp+"="
        typeoverride = 0
        s$ = removesymbol$(n$)
        IF s$ <> "" THEN
            typeoverride = typname2typ(s$)
            IF typeoverride AND ISFIXEDLENGTH THEN a$ = "Invalid constant type": GOTO errmes
            IF typeoverride = 0 THEN a$ = "Invalid constant type": GOTO errmes
        END IF

        IF getelement$(a$, i) <> "=" THEN a$ = "Expected =": GOTO errmes
        i = i + 1

        'get expression
        e$ = ""
        b = 0
        FOR i2 = i TO n
            e2$ = getelement$(ca$, i2)
            IF e2$ = "(" THEN b = b + 1
            IF e2$ = ")" THEN b = b - 1
            IF e2$ = "," AND b = 0 THEN
                pending = 1
                i = i2 + 1
                IF i > n - 2 THEN a$ = "Expected CONST ... , name = value/expression": GOTO errmes
                EXIT FOR
            END IF
            IF LEN(e$) = 0 THEN e$ = e2$ ELSE e$ = e$ + sp + e2$
        NEXT

        e$ = fixoperationorder(e$)
        l$=l$+sp + tlayout$
        e$ = evaluateconst(e$, t)

        IF t AND ISSTRING THEN 'string type

            IF typeoverride THEN
                IF (typeoverride AND ISSTRING) = 0 THEN a$ = "Type mismatch": GOTO errmes
            END IF

        ELSE 'not a string type

            IF typeoverride THEN
                IF typeoverride AND ISSTRING THEN a$ = "Type mismatch": GOTO errmes
            END IF

            IF t AND ISFLOAT THEN
                constval## = _CV(_FLOAT, e$)
                constval&& = constval##
                constval~&& = constval&&
            ELSE
                IF (t AND ISUNSIGNED) AND (t AND 511) = 64 THEN
                    constval~&& = _CV(_UNSIGNED _INTEGER64, e$)
                    constval&& = constval~&&
                    constval## = constval&&
                ELSE
                    constval&& = _CV(_INTEGER64, e$)
                    constval## = constval&&
                    constval~&& = constval&&
                END IF
            END IF

            'override type?
            IF typeoverride THEN
                'range check required here (noted in todo)
                t = typeoverride
            END IF

        END IF 'not a string type

        constlast = constlast + 1
        i2 = constlast
        IF subfunc = "" THEN constlastshared = i2
        constname(i2) = ucase$(n$)
        constcname(i2)=n$
        constnamesymbol(i2) = typevalue2symbol$(t)
        consttype(i2) = t
        IF t AND ISSTRING THEN
            conststring(i2) = e$
        ELSE
            IF t AND ISFLOAT THEN
                constfloat(i2) = constval##
            ELSE
                IF t AND ISUNSIGNED THEN
                    constuinteger(i2) = constval~&&
                ELSE
                    constinteger(i2) = constval&&
                END IF
            END IF
        END IF

        IF pending THEN l$=l$+sp2+",": GOTO constdefpending

        layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$

        GOTO finishednonexec
    END IF

    predefine:
    IF n >= 2 THEN
        asreq = 0
        IF firstelement$ = "DEFINT" THEN a$ = a$ + sp + "AS" + sp + "INTEGER": n = n + 2: GOTO definetype
        IF firstelement$ = "DEFLNG" THEN a$ = a$ + sp + "AS" + sp + "LONG": n = n + 2: GOTO definetype
        IF firstelement$ = "DEFSNG" THEN a$ = a$ + sp + "AS" + sp + "SINGLE": n = n + 2: GOTO definetype
        IF firstelement$ = "DEFDBL" THEN a$ = a$ + sp + "AS" + sp + "DOUBLE": n = n + 2: GOTO definetype
        IF firstelement$ = "DEFSTR" THEN a$ = a$ + sp + "AS" + sp + "STRING": n = n + 2: GOTO definetype
        IF firstelement$ = "_DEFINE" THEN
            asreq = 1
            definetype:
            l$ = firstelement$
            'get type from rhs
            typ$ = ""
            typ2$ = ""
            t$ = ""
            FOR i = n TO 2 STEP -1
                t$ = getelement$(a$, i)
                IF t$ = "AS" THEN EXIT FOR
                typ$ = t$ + " " + typ$
                typ2$ = t$ + sp + typ2$
            NEXT
            typ$ = RTRIM$(typ$)
            IF t$ <> "AS" THEN x = 23: GOTO errnum
            IF i = n OR i = 2 THEN x = 24: GOTO errnum


            n = i - 1
            'the data is from element 2 to element n
            i = 2 - 1
            definenext:
            'expects an alphabet letter or underscore
            i = i + 1: e$ = getelement$(a$, i): e = ASC(UCASE$(e$))
            IF LEN(e$) > 1 THEN x = 25: GOTO errnum
            IF e <> 95 AND (e > 90 OR e < 65) THEN x = 26: GOTO errnum
            IF e = 95 THEN e = 27 ELSE e = e - 64
            defineaz(e) = typ$
            defineextaz(e) = type2symbol(typ$)
            firste = e
            l$ = l$ + sp + e$

            IF i = n THEN
                IF predefining = 1 THEN GOTO predefined
                IF asreq THEN l$ = l$ + sp + "AS" + sp + typ2$
                layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
                GOTO finishednonexec
            END IF

            'expects "-" or ","
            i = i + 1: e$ = getelement$(a$, i)
            IF e$ <> "-" AND e$ <> "," THEN x = 27: GOTO errnum
            IF e$ = "-" THEN
                l$ = l$ + sp2 + "-"
                IF i = n THEN x = 28: GOTO errnum
                'expects an alphabet letter or underscore
                i = i + 1: e$ = getelement$(a$, i): e = ASC(UCASE$(e$))
                IF LEN(e$) > 1 THEN x = 29: GOTO errnum
                IF e <> 95 AND (e > 90 OR e < 65) THEN x = 30: GOTO errnum
                IF e = 95 THEN e = 27 ELSE e = e - 64
                IF firste > e THEN SWAP e, firste
                FOR e2 = firste TO e
                    defineaz(e2) = typ$
                    defineextaz(e2) = type2symbol(typ$)
                NEXT
                l$ = l$ + sp2 + e$
                IF i = n THEN
                    IF predefining = 1 THEN GOTO predefined
                    IF asreq THEN l$ = l$ + sp + "AS" + sp + typ2$
                    layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
                    GOTO finishednonexec
                END IF
                'expects ","
                i = i + 1: e$ = getelement$(a$, i)
                IF e$ <> "," THEN x = 31: GOTO errnum
            END IF
            l$ = l$ + sp2 + ","
            GOTO definenext
        END IF '_DEFINE
    END IF '2
    IF predefining = 1 THEN GOTO predefined

    IF closedmain <> 0 AND subfunc = "" THEN a$ = "Statement cannot be placed between SUB/FUNCTIONs": GOTO errmes

    'executable section:

    statementn = statementn + 1


    IF n >= 1 THEN
        IF firstelement$ = "NEXT" THEN

            l$ = "NEXT"
            IF n = 1 THEN GOTO simplenext
            v$ = ""
            FOR i = 2 TO n
                a2$ = getelement(ca$, i)

                IF a2$ = "," THEN

                    lastnextele:
                    e$ = fixoperationorder(v$)
                    IF LEN(l$) = 4 THEN l$ = l$ + sp + tlayout$ ELSE l$ = l$ + sp2 + "," + sp + tlayout$
                    e$ = evaluate(e$, typ)
                    IF (typ AND ISREFERENCE) THEN
                        getid VAL(e$)
                        IF (id.t AND ISPOINTER) THEN
                            IF (id.t AND ISSTRING) = 0 THEN
                                IF (id.t AND ISOFFSETINBITS) = 0 THEN
                                    IF (id.t AND ISARRAY) = 0 THEN
                                        GOTO fornextfoundvar2
                                    END IF
                                END IF
                            END IF
                        END IF
                    END IF
                    a$ = "Unsupported variable after NEXT": GOTO errmes
                    fornextfoundvar2:
                    simplenext:
                    IF controltype(controllevel) <> 2 THEN a$ = "NEXT without FOR": GOTO errmes
                    IF n <> 1 AND controlvalue(controllevel) <> currentid THEN a$ = "Incorrect variable after NEXT": GOTO errmes
                    PRINT #12, "}"
                    PRINT #12, "fornext_exit_" + str2$(controlid(controllevel)) + ":;"
                    controllevel = controllevel - 1
                    IF n = 1 THEN EXIT FOR
                    v$ = ""

                ELSE

                    IF LEN(v$) THEN v$ = v$ + sp + a2$ ELSE v$ = a2$
                    IF i = n THEN GOTO lastnextele

                END IF

            NEXT

            layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
            GOTO finishednonexec '***no error causing code, event checking done by FOR***
        END IF
    END IF



    IF n >= 1 THEN
        IF firstelement$ = "WHILE" THEN
            IF nochecks = 0 THEN PRINT #12, "S_" + str2$(statementn) + ":;": dynscope = 1

            controllevel = controllevel + 1
            controlref(controllevel)=linenumber
            controltype(controllevel) = 5
            controlid(controllevel) = uniquenumber
            IF n >= 2 THEN
                e$ = fixoperationorder(getelements$(ca$, 2, n))
                l$ = "WHILE" + sp + tlayout$
                layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
                e$ = evaluate(e$, typ)
                IF (typ AND ISREFERENCE) THEN e$ = refer$(e$, typ, 0)
                IF stringprocessinghappened THEN e$ = cleanupstringprocessingcall$ + e$ + ")"
                IF (typ AND ISSTRING) THEN x = 12: GOTO errnum
                PRINT #12, "while((" + e$ + ")||new_error){"
            ELSE
                x = 13: GOTO errnum
            END IF

            GOTO finishedline
        END IF
    END IF

    IF n = 1 THEN
        IF firstelement$ = "WEND" THEN


            IF controltype(controllevel) <> 5 THEN a$ = "WEND without WHILE": GOTO errmes
            PRINT #12, "}"
            PRINT #12, "ww_exit_" + str2$(controlid(controllevel)) + ":;"
            controllevel = controllevel - 1
            l$ = "WEND"
            layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
            GOTO finishednonexec '***no error causing code, event checking done by WHILE***
        END IF
    END IF





    IF n >= 1 THEN
        IF firstelement$ = "DO" THEN
            IF nochecks = 0 THEN PRINT #12, "S_" + str2$(statementn) + ":;": dynscope = 1
            controllevel = controllevel + 1
            controlref(controllevel)=linenumber
            l$ = "DO"
            IF n >= 2 THEN
                whileuntil = 0
                IF secondelement$ = "WHILE" THEN whileuntil = 1: l$ = l$ + sp + "WHILE"
                IF secondelement$ = "UNTIL" THEN whileuntil = 2: l$ = l$ + sp + "UNTIL"
                IF whileuntil = 0 THEN x = 15: GOTO errnum
                e$ = fixoperationorder(getelements$(ca$, 3, n))
                l$ = l$ + sp + tlayout$
                e$ = evaluate(e$, typ)
                IF (typ AND ISREFERENCE) THEN e$ = refer$(e$, typ, 0)
                IF stringprocessinghappened THEN e$ = cleanupstringprocessingcall$ + e$ + ")"
                IF (typ AND ISSTRING) THEN x = 16: GOTO errnum
                IF whileuntil = 1 THEN PRINT #12, "while((" + e$ + ")||new_error){" ELSE PRINT #12, "while((!(" + e$ + "))||new_error){"
                controltype(controllevel) = 4
            ELSE
                controltype(controllevel) = 3
                PRINT #12, "do{"
            END IF
            controlid(controllevel) = uniquenumber
            layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
            GOTO finishedline
        END IF
    END IF

    IF n >= 1 THEN
        IF firstelement$ = "LOOP" THEN
            l$ = "LOOP"
            IF controltype(controllevel) <> 3 AND controltype(controllevel) <> 4 THEN x = 17: GOTO errnum
            IF n >= 2 THEN
                IF nochecks = 0 THEN PRINT #12, "S_" + str2$(statementn) + ":;": dynscope = 1
                IF controltype(controllevel) = 4 THEN x = 18: GOTO errnum
                whileuntil = 0
                IF secondelement$ = "WHILE" THEN whileuntil = 1: l$ = l$ + sp + "WHILE"
                IF secondelement$ = "UNTIL" THEN whileuntil = 2: l$ = l$ + sp + "UNTIL"
                IF whileuntil = 0 THEN x = 19: GOTO errnum
                e$ = fixoperationorder(getelements$(ca$, 3, n))
                l$ = l$ + sp + tlayout$
                e$ = evaluate(e$, typ)
                IF (typ AND ISREFERENCE) THEN e$ = refer$(e$, typ, 0)
                IF stringprocessinghappened THEN e$ = cleanupstringprocessingcall$ + e$ + ")"
                IF (typ AND ISSTRING) THEN x = 20: GOTO errnum
                IF whileuntil = 1 THEN PRINT #12, "}while((" + e$ + ")&&(!new_error));" ELSE PRINT #12, "}while((!(" + e$ + "))&&(!new_error));"
            ELSE
                IF controltype(controllevel) = 4 THEN
                    PRINT #12, "}"
                ELSE
                    PRINT #12, "}while(1);" 'infinite loop!
                END IF
            END IF
            PRINT #12, "dl_exit_" + str2$(controlid(controllevel)) + ":;"
            controllevel = controllevel - 1
            layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
            IF n = 1 THEN GOTO finishednonexec '***no error causing code, event checking done by DO***
            GOTO finishedline
        END IF
    END IF









    IF n >= 6 THEN
        IF firstelement$ = "FOR" THEN
            IF nochecks = 0 THEN PRINT #12, "S_" + str2$(statementn) + ":;": dynscope = 1

            l$ = "FOR"
            controllevel = controllevel + 1
            controlref(controllevel)=linenumber
            controltype(controllevel) = 2
            controlid(controllevel) = uniquenumber
            v$ = ""
            startvalue$ = ""
            p3$ = "1": stepused = 0
            p2$ = ""
            FOR i = 2 TO n
                IF getelement$(a$, i) = "=" THEN
                    v$ = getelements$(ca$, 2, i - 1)
                    equpos = i
                END IF
                IF getelement$(a$, i) = "TO" THEN
                    startvalue$ = getelements$(ca$, equpos + 1, i - 1)
                    topos = i
                END IF
                IF getelement$(a$, i) = "STEP" THEN
                    stepused = 1
                    p2$ = getelements$(ca$, topos + 1, i - 1)
                    p3$ = getelements$(ca$, i + 1, n)
                END IF
            NEXT
            IF p2$ = "" THEN p2$ = getelements$(ca$, topos + 1, n)

            e$ = fixoperationorder(v$)
            l$ = l$ + sp + tlayout$
            e$ = evaluate(e$, typ)
            IF (typ AND ISREFERENCE) THEN
                getid VAL(e$)
                IF (id.t AND ISPOINTER) THEN
                    IF (id.t AND ISSTRING) = 0 THEN
                        IF (id.t AND ISOFFSETINBITS) = 0 THEN
                            IF (id.t AND ISARRAY) = 0 THEN
                                GOTO fornextfoundvar
                            END IF
                        END IF
                    END IF
                END IF
            END IF
            x = 21: GOTO errnum
            fornextfoundvar:
            controlvalue(controllevel) = currentid
            v$ = e$

            'find C++ datatype to match variable
            'markup to cater for greater range/accuracy
            ctype$ = ""
            ctyp = typ - ISPOINTER
            bits = typ AND 511
            IF (typ AND ISFLOAT) THEN
                IF bits = 32 THEN ctype$ = "double": ctyp = 64& + ISFLOAT
                IF bits = 64 THEN ctype$ = "long double": ctyp = 256& + ISFLOAT
                IF bits = 256 THEN ctype$ = "long double": ctyp = 256& + ISFLOAT
            ELSE
                IF bits = 8 THEN ctype$ = "int16": ctyp = 16&
                IF bits = 16 THEN ctype$ = "int32": ctyp = 32&
                IF bits = 32 THEN ctype$ = "int64": ctyp = 64&
                IF bits = 64 THEN ctype$ = "int64": ctyp = 64&
            END IF
            IF ctype$ = "" THEN x = 22: GOTO errnum
            u$ = str2(uniquenumber)

            IF subfunc = "" THEN
                PRINT #13, "static " + ctype$ + " fornext_value" + u$ + ";"
                PRINT #13, "static " + ctype$ + " fornext_finalvalue" + u$ + ";"
                PRINT #13, "static " + ctype$ + " fornext_step" + u$ + ";"
                PRINT #13, "static uint8 fornext_step_negative" + u$ + ";"
            ELSE
                PRINT #13, ctype$ + " fornext_value" + u$ + ";"
                PRINT #13, ctype$ + " fornext_finalvalue" + u$ + ";"
                PRINT #13, ctype$ + " fornext_step" + u$ + ";"
                PRINT #13, "uint8 fornext_step_negative" + u$ + ";"
            END IF

            'calculate start
            e$=fixoperationorder$(startvalue$)
            l$ = l$ + sp + "=" + sp + tlayout$
            e$=evaluatetotyp$(e$,ctyp)
            PRINT #12, "fornext_value" + u$ + "="+e$+";"

            'final
            e$ = fixoperationorder$(p2$)
            l$ = l$ + sp + "TO" + sp + tlayout$
            e$ = evaluatetotyp(e$, ctyp)
            PRINT #12, "fornext_finalvalue" + u$ + "=" + e$ + ";"

	    'step
            e$ = fixoperationorder$(p3$)
            IF stepused = 1 THEN l$ = l$ + sp + "STEP" + sp + tlayout$
            e$ = evaluatetotyp(e$, ctyp)
            PRINT #12, "fornext_step" + u$ + "=" + e$ + ";"
            PRINT #12, "if (fornext_step" + u$ + "<0) fornext_step_negative" + u$ + "=1; else fornext_step_negative" + u$ + "=0;"

            PRINT #12, "if (new_error) goto fornext_error" + u$ + ";"
            PRINT #12, "goto fornext_entrylabel" + u$ + ";"
            PRINT #12, "while(1){"
            typbak = typ
            PRINT #12, "fornext_value" + u$ + "=fornext_step" + u$ + "+(" + refer$(v$, typ, 0) + ");"
            typ = typbak
            PRINT #12, "fornext_entrylabel" + u$ + ":"
            setrefer v$, typ, "fornext_value" + u$, 1
            PRINT #12, "if (fornext_step_negative" + u$ + "){"
            PRINT #12, "if (fornext_value" + u$ + "<fornext_finalvalue" + u$ + ") break;"
            PRINT #12, "}else{"
            PRINT #12, "if (fornext_value" + u$ + ">fornext_finalvalue" + u$ + ") break;"
            PRINT #12, "}"
            PRINT #12, "fornext_error" + u$ + ":"

            layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$

            GOTO finishedline
        END IF
    END IF


    IF n = 1 THEN
        IF firstelement$ = "ELSE" THEN
            FOR i = controllevel TO 1 STEP -1
                t = controltype(i)
                IF t = 1 THEN
                    IF controlstate(controllevel) = 2 THEN a$ = "IF-THEN already contains an ELSE statement": GOTO errmes
                    PRINT #12, "}else{"
                    controlstate(controllevel) = 2
                    IF lineelseused = 0 THEN lhscontrollevel = lhscontrollevel - 1
                    l$ = "ELSE"
                    layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
                    GOTO finishednonexec '***no error causing code, event checking done by IF***
                END IF
            NEXT
            a$ = "ELSE without IF": GOTO errmes
        END IF
    END IF

    IF n >= 3 THEN
        IF firstelement$ = "ELSEIF" THEN
            IF nochecks = 0 THEN PRINT #12, "S_" + str2$(statementn) + ":;": dynscope = 1

            FOR i = controllevel TO 1 STEP -1
                t = controltype(i)
                IF t = 1 THEN
                    IF controlstate(controllevel) = 2 THEN a$ = "ELSEIF invalid after ELSE": GOTO errmes
                    controlstate(controllevel) = 1
                    controlvalue(controllevel) = controlvalue(controllevel) + 1
                    e$ = getelement$(a$, n)
                    IF e$ <> "THEN" THEN a$ = "Expected ELSEIF expression THEN": GOTO errmes
                    PRINT #12, "}else{"
                    e$ = fixoperationorder$(getelements$(ca$, 2, n - 1))
                    l$ = "ELSEIF" + sp + tlayout$ + sp + "THEN"
                    layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
                    e$ = evaluate(e$, typ)
                    IF (typ AND ISREFERENCE) THEN e$ = refer$(e$, typ, 0)
                    IF stringprocessinghappened THEN
                        PRINT #12, "if (" + cleanupstringprocessingcall$ + e$ + ")){"
                    ELSE
                        PRINT #12, "if (" + e$ + "){"
                    END IF
                    lhscontrollevel = lhscontrollevel - 1
                    GOTO finishedline
                END IF
            NEXT
            a$ = "ELSEIF without IF": GOTO errmes
        END IF
    END IF

    IF n >= 3 THEN
        IF firstelement$ = "IF" THEN
            IF nochecks = 0 THEN PRINT #12, "S_" + str2$(statementn) + ":;": dynscope = 1

            e$ = getelement(a$, n)
            iftype = 0
            IF e$ = "THEN" THEN iftype = 1
            IF e$ = "GOTO" THEN iftype = 2
            IF iftype = 0 THEN a$ = "Expected IF expression THEN/GOTO": GOTO errmes

            controllevel = controllevel + 1
            controlref(controllevel)=linenumber
            controltype(controllevel) = 1
            controlvalue(controllevel) = 0 'number of extra closing } required at END IF
            controlstate(controllevel) = 0

            e$ = fixoperationorder$(getelements(ca$, 2, n - 1))
            l$ = "IF" + sp + tlayout$
            e$ = evaluate(e$, typ)
            IF (typ AND ISREFERENCE) THEN e$ = refer$(e$, typ, 0)

            IF stringprocessinghappened THEN
                PRINT #12, "if ((" + cleanupstringprocessingcall$ + e$ + "))||new_error){"
            ELSE
                PRINT #12, "if ((" + e$ + ")||new_error){"
            END IF

            IF iftype = 1 THEN l$ = l$ + sp + "THEN" 'note: 'GOTO' will be added when iftype=2
            layoutdone = 1: IF LEN(layout$) = 0 THEN layout$ = l$ ELSE layout$ = layout$ + sp + l$

            IF iftype = 2 THEN 'IF ... GOTO
                GOTO finishedline
            END IF

            THENGOTO = 1 'possible: IF a=1 THEN 10
            GOTO finishedline2
        END IF
    END IF


    'END IF
    IF n = 2 THEN
        IF getelement(a$, 1) = "END" AND getelement(a$, 2) = "IF" THEN


            IF controltype(controllevel) <> 1 THEN a$ = "END IF without IF": GOTO errmes
            layoutdone = 1
            IF impliedendif = 0 THEN
                l$ = "END" + sp + "IF"
                IF LEN(layout$) = 0 THEN layout$ = l$ ELSE layout$ = layout$ + sp + l$
            END IF
            PRINT #12, "}"
            FOR i = 1 TO controlvalue(controllevel)
                PRINT #12, "}"
            NEXT
            controllevel = controllevel - 1
            GOTO finishednonexec '***no error causing code, event checking done by IF***
        END IF
    END IF



    'SELECT CASE
    IF n >= 1 THEN
        IF firstelement$ = "SELECT" THEN
            IF nochecks = 0 THEN PRINT #12, "S_" + str2$(statementn) + ":;": dynscope = 1

            IF n = 1 OR secondelement$ <> "CASE" THEN a$ = "Expected CASE": GOTO errmes
            IF n = 2 THEN a$ = "Expected SELECT CASE expression": GOTO errmes
            e$ = fixoperationorder(getelements$(ca$, 3, n))
            l$ = "SELECT" + sp + "CASE" + sp + tlayout$
            layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
            e$ = evaluate(e$, typ)
            u = uniquenumber

            controllevel = controllevel + 1
            controlvalue(controllevel) = 0 'id

            t$ = ""
            IF (typ AND ISSTRING) THEN
t = 0
if (typ AND ISUDT)=0 AND (typ AND ISARRAY)=0 AND (typ AND ISREFERENCE)<>0 THEN
		controlvalue(controllevel)=VAL(e$)
ELSE
		IF (typ AND ISREFERENCE) THEN e$ = refer(e$, typ, 0)
                PRINT #13, "static qbs *sc_" + str2$(u) + "=qbs_new(0,0);"
                PRINT #12, "qbs_set(sc_" + str2$(u) + "," + e$ + ");"
END IF

            ELSE

                IF (typ AND ISFLOAT) THEN

if (typ and 511)>64 then t=3: t$="long double"
if (typ and 511)=32 then t=4: t$="float"
if (typ and 511)=64 then t=5: t$="double"
 if (typ AND ISUDT)=0 AND (typ AND ISARRAY)=0 AND (typ AND ISREFERENCE)<>0 THEN
  controlvalue(controllevel)=VAL(e$)
 else
  IF (typ AND ISREFERENCE) THEN e$ = refer(e$, typ, 0)
  PRINT #13, "static " + t$ + " sc_" + str2$(u) + ";"
  PRINT #12, "sc_" + str2$(u) + "=" + e$ + ";"
 end if

                ELSE

'non-float
t = 1: t$ = "int64"
if (typ AND ISUNSIGNED) then
 if (typ AND 511)<=32 then t=7:t$="uint32"
 if (typ AND 511)>32 then t=2:t$="uint64"
else
 if (typ AND 511)<=32 then t=6:t$="int32"
 if (typ AND 511)>32 then t=1:t$="int64"
end if
 if (typ AND ISUDT)=0 AND (typ AND ISARRAY)=0 AND (typ AND ISREFERENCE)<>0 THEN
  controlvalue(controllevel)=VAL(e$)
 else
  IF (typ AND ISREFERENCE) THEN e$ = refer(e$, typ, 0)
  PRINT #13, "static " + t$ + " sc_" + str2$(u) + ";"
  PRINT #12, "sc_" + str2$(u) + "=" + e$ + ";"
 end if

		end if
end if
            
            controlref(controllevel)=linenumber
            controltype(controllevel) = 10 + t
            controlid(controllevel) = u

            GOTO finishedline
        END IF
    END IF


    'END SELECT
    IF n = 2 THEN
        IF firstelement$ = "END" AND secondelement$ = "SELECT" THEN


            'complete current case if necessary
            '18=CASE (awaiting END SELECT/CASE/CASE ELSE)
            '19=CASE ELSE (awaiting END SELECT)
            IF controltype(controllevel) = 18 THEN
                controllevel = controllevel - 1
                PRINT #12, "goto sc_" + str2$(controlid(controllevel)) + "_end;"
                PRINT #12, "}"
            END IF
            IF controltype(controllevel) = 19 THEN
                controllevel = controllevel - 1
            END IF
            PRINT #12, "sc_" + str2$(controlid(controllevel)) + "_end:;"
            IF controltype(controllevel) < 10 OR controltype(controllevel) > 17 THEN a$ = "END SELECT without SELECT CASE": GOTO errmes
            controllevel = controllevel - 1
            l$ = "END" + sp + "SELECT"
            layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
            GOTO finishednonexec '***no error causing code, event checking done by SELECT CASE***
        END IF
    END IF

    'CASE
    IF n >= 1 THEN
        IF firstelement$ = "CASE" THEN

            l$ = "CASE"
            'complete current case if necessary
            '18=CASE (awaiting END SELECT/CASE/CASE ELSE)
            '19=CASE ELSE (awaiting END SELECT)
            IF controltype(controllevel) = 19 THEN a$ = "Expected END SELECT": GOTO errmes
            IF controltype(controllevel) = 18 THEN
                lhscontrollevel = lhscontrollevel - 1
                controllevel = controllevel - 1
                PRINT #12, "goto sc_" + str2$(controlid(controllevel)) + "_end;"
                PRINT #12, "}"
                'following line fixes problem related to RESUME after error
                'statementn = statementn + 1
                'if nochecks=0 then PRINT #12, "S_" + str2$(statementn) + ":;"
            END IF

            IF controltype(controllevel) < 10 OR controltype(controllevel) > 17 THEN a$ = "CASE without SELECT CASE": GOTO errmes
            IF n = 1 THEN a$ = "Expected CASE expression": GOTO errmes



'upgrade:
'#1: variables can be referred to directly by storing an id in 'controlref'
'    (but not if part of an array etc.)
'DIM controlvalue(1000) AS LONG 
'#2: more types will be available
'    +SINGLE
'    +DOUBLE
'    -LONG DOUBLE
'    +INT32
'    +UINT32
'14=SELECT CASE float ...
'15=SELECT CASE double
'16=SELECT CASE int32
'17=SELECT CASE uint32

'10=SELECT CASE qbs (awaiting END SELECT/CASE)
'11=SELECT CASE int64 (awaiting END SELECT/CASE)
'12=SELECT CASE uint64 (awaiting END SELECT/CASE)
'13=SELECT CASE LONG double (awaiting END SELECT/CASE/CASE ELSE)
'14=SELECT CASE float ...
'15=SELECT CASE double
'16=SELECT CASE int32
'17=SELECT CASE uint32

'    bits = targettyp AND 511
'                                IF bits <= 16 THEN e$ = "qbr_float_to_long(" + e$ + ")"
'                                IF bits > 16 AND bits < 32 THEN e$ = "qbr_double_to_long(" + e$ + ")"
'                                IF bits >= 32 THEN e$ = "qbr(" + e$ + ")"


t=controltype(controllevel)-10
'get required type cast, and float options
flt=0
if t=0 then tc$=""
if t=1 then tc$=""
if t=2 then tc$=""
if t=3 then tc$="": flt=1
if t=4 then tc$="(float)": flt=1
if t=5 then tc$="(double)": flt=1
if t=6 then tc$=""
if t=7 then tc$=""

n$ = "sc_" + str2$(controlid(controllevel))
cv=controlvalue(controllevel)
if cv then
n$=refer$(str2$(cv),0,0)
end if

            'CASE ELSE
            IF n = 2 THEN
                IF getelement$(a$, 2) = "C-EL" THEN
                    controllevel = controllevel + 1: controltype(controllevel) = 19
                    controlref(controllevel)=controlref(controllevel-1)
                    l$ = l$ + sp + "ELSE"
                    layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
                    GOTO finishednonexec '***no error causing code, event checking done by SELECT CASE***
                END IF
            END IF

            IF nochecks = 0 THEN PRINT #12, "S_" + str2$(statementn) + ":;": dynscope = 1


            PRINT #12, "if ((";
            nexp = 0
            b = 0
            e$ = ""
            FOR i = 2 TO n
                e2$ = getelement$(ca$, i)
                IF e2$ = "(" THEN b = b + 1
                IF e2$ = ")" THEN b = b - 1
                IF i = n THEN e$ = e$ + sp + e2$
                IF i = n OR (e2$ = "," AND b = 0) THEN
                    IF nexp <> 0 THEN l$ = l$ + sp2 + ",": PRINT #12, "||";
                    IF e$ = "" THEN a$ = "Expected expression": GOTO errmes
                    e$ = RIGHT$(e$, LEN(e$) - 1)



                    'TYPE 1? ... TO ...
                    n2 = numelements(e$)
                    b2 = 0
                    el$ = "": er$ = ""
                    usedto = 0
                    FOR i2 = 1 TO n2
                        e3$ = getelement$(e$, i2)
                        IF e3$ = "(" THEN b2 = b2 + 1
                        IF e3$ = ")" THEN b2 = b2 - 1
                        IF b2 = 0 AND UCASE$(e3$) = "TO" THEN
                            usedto = 1
                        ELSE
                            IF usedto = 0 THEN el$ = el$ + sp + e3$ ELSE er$ = er$ + sp + e3$
                        END IF
                    NEXT
                    IF usedto = 1 THEN
                        IF el$ = "" OR er$ = "" THEN a$ = "Expected expression TO expression": GOTO errmes
                        el$ = RIGHT$(el$, LEN(el$) - 1): er$ = RIGHT$(er$, LEN(er$) - 1)
                        'evaluate each side
                        FOR i2 = 1 TO 2
                            IF i2 = 1 THEN e$ = el$ ELSE e$ = er$
                            e$ = fixoperationorder(e$)
                            IF i2 = 1 THEN l$ = l$ + sp + tlayout$ ELSE l$ = l$ + sp + "TO" + sp + tlayout$
                            e$ = evaluate(e$, typ)
                            IF (typ AND ISREFERENCE) THEN e$ = refer(e$, typ, 0)
                            IF t = 0 THEN
                                IF (typ AND ISSTRING) = 0 THEN a$ = "Expected string expression": GOTO errmes
                                IF i2 = 1 THEN PRINT #12, "(qbs_greaterorequal(" + n$ + "," + e$ + ")&&qbs_lessorequal(" + n$ + ",";
                                IF i2 = 2 THEN PRINT #12, e$ + "))";
                            ELSE
                                IF (typ AND ISSTRING) THEN a$ = "Expected numeric expression": GOTO errmes
                                'round to integer?
                                IF (typ AND ISFLOAT) THEN
                                    IF t = 1 THEN e$ = "qbr(" + e$ + ")"
                                    IF t = 2 THEN e$ = "qbr_longdouble_to_uint64(" + e$ + ")"
                                    IF t = 6 or t = 7 THEN e$ = "qbr_double_to_long(" + e$ + ")"
                                END IF
				'cast result?
				if len(tc$) then e$=tc$+"("+e$+")"
                                IF i2 = 1 THEN PRINT #12, "((" + n$ + ">=(" + e$ + "))&&(" + n$ + "<=(";
                                IF i2 = 2 THEN PRINT #12, e$ + ")))";
                            END IF
                        NEXT
                        GOTO addedexp
                    END IF

'10=SELECT CASE qbs (awaiting END SELECT/CASE)
'11=SELECT CASE int64 (awaiting END SELECT/CASE)
'12=SELECT CASE uint64 (awaiting END SELECT/CASE)
'13=SELECT CASE LONG double (awaiting END SELECT/CASE/CASE ELSE)
'14=SELECT CASE float ...
'15=SELECT CASE double
'16=SELECT CASE int32
'17=SELECT CASE uint32

'    bits = targettyp AND 511
'                                IF bits <= 16 THEN e$ = "qbr_float_to_long(" + e$ + ")"
'                                IF bits > 16 AND bits < 32 THEN e$ = "qbr_double_to_long(" + e$ + ")"
'                                IF bits >= 32 THEN e$ = "qbr(" + e$ + ")"






                    o$ = "==" 'used by type 3

                    'TYPE 2?
                    x$ = getelement$(e$, 1)
                    IF isoperator(x$) THEN 'non-standard usage correction
                        IF x$ = "=" OR x$ = "<>" OR x$ = ">" OR x$ = "<" OR x$ = ">=" OR x$ = "<=" THEN
                            e$ = "IS" + sp + e$
                            x$ = "IS"
                        END IF
                    END IF
                    IF UCASE$(x$) = "IS" THEN
                        n2 = numelements(e$)
                        IF n2 < 3 THEN a$ = "Expected IS =,<>,>,<,>=,<= expression": GOTO errmes
                        o$ = getelement$(e$, 2)
			o2$=o$
                        o = 0
                        IF o$ = "=" THEN o$ = "==": o = 1
                        IF o$ = "<>" THEN o$ = "!=": o = 1
                        IF o$ = ">" THEN o = 1
                        IF o$ = "<" THEN o = 1
                        IF o$ = ">=" THEN o = 1
                        IF o$ = "<=" THEN o = 1
                        IF o <> 1 THEN a$ = "Expected IS =,<>,>,<,>=,<= expression": GOTO errmes
                        l$ = l$ + sp + "IS" + sp + o2$
                        e$ = getelements$(e$, 3, n2)
                        'fall through to type 3 using modified e$ & o$
                    END IF

                    'TYPE 3? simple expression
                    e$ = fixoperationorder(e$)
                    l$ = l$ + sp + tlayout$
                    e$ = evaluate(e$, typ)
                    IF (typ AND ISREFERENCE) THEN e$ = refer(e$, typ, 0)
                    IF t = 0 THEN
                        'string comparison
                        IF (typ AND ISSTRING) = 0 THEN a$ = "Expected string expression": GOTO errmes
                        IF o$ = "==" THEN o$ = "qbs_equal"
                        IF o$ = "!=" THEN o$ = "qbs_notequal"
                        IF o$ = ">" THEN o$ = "qbs_greaterthan"
                        IF o$ = "<" THEN o$ = "qbs_lessthan"
                        IF o$ = ">=" THEN o$ = "qbs_greaterorequal"
                        IF o$ = "<=" THEN o$ = "qbs_lessorequal"
                        PRINT #12, o$ + "(" + n$ + "," + e$ + ")";
                    ELSE
                        'numeric
                        IF (typ AND ISSTRING) THEN a$ = "Expected numeric expression": GOTO errmes
                                'round to integer?
                                IF (typ AND ISFLOAT) THEN
                                    IF t = 1 THEN e$ = "qbr(" + e$ + ")"
                                    IF t = 2 THEN e$ = "qbr_longdouble_to_uint64(" + e$ + ")"
                                    IF t = 6 or t = 7 THEN e$ = "qbr_double_to_long(" + e$ + ")"
                                END IF
				'cast result?
				if len(tc$) then e$=tc$+"("+e$+")"
                        PRINT #12, "(" + n$ + o$ + "(" + e$ + "))";
                    END IF

                    addedexp:
                    e$ = ""
                    nexp = nexp + 1
                ELSE
                    e$ = e$ + sp + e2$
                END IF
            NEXT
            PRINT #12, ")||new_error){"

            layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
            controllevel = controllevel + 1
            controlref(controllevel)=controlref(controllevel-1)
            controltype(controllevel) = 18
            GOTO finishedline
        END IF
    END IF












    'static scope commands:

    IF nochecks = 0 THEN
        PRINT #12, "do{"
        'PRINT #12, "S_" + str2$(statementn) + ":;"
    END IF






    'dynamic scope commands:
if firstelement$="FIELD" then

'get filenumber
b=0: e$=""
for i=2 to n
e2$=getelement(ca$, i)
if e2$="(" then b=b+1
if e2$=")" then b=b-1
if e2$="," and b=0 then
i=i+1: goto fieldgotfn
end if
if len(e$) then e$=e$+sp+e2$ else e$=e2$
next
goto fielderror
fieldgotfn:
if e$="#" or len(e$)=0 then goto fielderror
if left$(e$,2)="#"+sp then e$=right$(e$,len(e$)-2):l$="FIELD"+sp+"#"+sp2 else l$="FIELD"+sp
e$=fixoperationorder(e$)
l$=l$+tlayout$+sp2+","+sp
e$=evaluatetotyp(e$,32&)
print #12,"field_new("+e$+");"

fieldnext:

'get fieldwidth
if i>n then goto fielderror
b=0: e$=""
for i=i to n
e2$=getelement(ca$, i)
if e2$="(" then b=b+1
if e2$=")" then b=b-1
if ucase$(e2$)="AS" and b=0 then
i=i+1: goto fieldgotfw
end if
if len(e$) then e$=e$+sp+e2$ else e$=e2$
next
goto fielderror
fieldgotfw:
if len(e$)=0 then goto fielderror
e$=fixoperationorder(e$)
l$=l$+tlayout$+sp+"AS"+sp
sizee$=evaluatetotyp(e$,32&)

'get variable name
if i>n then goto fielderror
b=0: e$=""
for i=i to n
e2$=getelement(ca$, i)
if e2$="(" then b=b+1
if e2$=")" then b=b-1
if (i=n or e2$=",") and b=0 then
if e2$="," then i=i-1
if i=n then
if len(e$) then e$=e$+sp+e2$ else e$=e2$
end if
goto fieldgotfname
end if
if len(e$) then e$=e$+sp+e2$ else e$=e2$
next
goto fielderror
fieldgotfname:
if len(e$)=0 then goto fielderror
'evaluate it to check it is a STRING
e$=fixoperationorder(e$)
l$=l$+tlayout$
e$=evaluate(e$,typ)
if (typ AND ISSTRING)=0 then goto fielderror
if typ AND ISFIXEDLENGTH then a$="Fixed length strings cannot be used in a FIELD statement": GOTO errmes
IF (typ AND ISREFERENCE)=0 THEN goto fielderror
e$ = refer(e$, typ, 0)
print #12,"field_add("+e$+","+sizee$+");"

if i<n then
i=i+1
e$=getelement(a$,i)
if e$<>"," then a$="Expected ,":goto errmes
l$=l$+sp2+","+sp
i=i+1
goto fieldnext
end if

layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
goto finishedline

fielderror: a$ = "Expected FIELD #filenumber, characters AS variable$, ...": GOTO errmes
end if





    '1=IF (awaiting END IF)
    '2=FOR (awaiting NEXT)
    '3=DO (awaiting LOOP [UNTIL|WHILE param])
    '4=DO WHILE/UNTIL (awaiting LOOP)
    '5=WHILE (awaiting WEND)

    IF n = 2 THEN
        IF firstelement$ = "EXIT" THEN

            l$ = firstelement$ + sp + secondelement$

            IF secondelement$ = "DO" THEN
                'scan backwards until previous control level reached
                FOR i = controllevel TO 1 STEP -1
                    t = controltype(i)
                    IF t = 3 OR t = 4 THEN
                        PRINT #12, "goto dl_exit_" + str2$(controlid(i)) + ";"
                        layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
                        GOTO finishedline
                    END IF
                NEXT
                a$ = "EXIT DO without DO": GOTO errmes
            END IF

            IF secondelement$ = "FOR" THEN
                'scan backwards until previous control level reached
                FOR i = controllevel TO 1 STEP -1
                    t = controltype(i)
                    IF t = 2 THEN
                        PRINT #12, "goto fornext_exit_" + str2$(controlid(i)) + ";"
                        layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
                        GOTO finishedline
                    END IF
                NEXT
                a$ = "EXIT FOR without FOR": GOTO errmes
            END IF

            IF secondelement$ = "WHILE" THEN
                'scan backwards until previous control level reached
                FOR i = controllevel TO 1 STEP -1
                    t = controltype(i)
                    IF t = 5 THEN
                        PRINT #12, "goto ww_exit_" + str2$(controlid(i)) + ";"
                        layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
                        GOTO finishedline
                    END IF
                NEXT
                a$ = "EXIT WHILE without WHILE": GOTO errmes
            END IF

        END IF
    END IF


    IF n >= 2 THEN
        IF firstelement$ = "ON" AND secondelement$ = "TIMER" THEN
            i = 3
            IF i > n THEN a$ = "Expected (": GOTO errmes
            a2$ = getelement$(ca$, i): i = i + 1
            IF a2$ <> "(" THEN a$ = "Expected (": GOTO errmes
            l$ = "ON" + sp + "TIMER" + sp2 + "("
            IF i > n THEN a$ = "Expected ...": GOTO errmes
            b = 0
            x = 0
            e2$ = ""
            e3$ = ""
            FOR i = i TO n
                e$ = getelement$(ca$, i)
                a = ASC(e$)
                IF a = 40 THEN b = b + 1
                IF a = 41 THEN b = b - 1
                IF b = -1 THEN GOTO ontimgotarg
                IF a = 44 AND b = 0 THEN
                    x = x + 1
                    IF x > 1 THEN a$ = "Expected )": GOTO errmes
                    IF e2$ = "" THEN a$ = "Expected ... ,": GOTO errmes
                    e3$ = e2$
                    e2$ = ""
                ELSE
                    IF LEN(e2$) THEN e2$ = e2$ + sp + e$ ELSE e2$ = e$
                END IF
            NEXT
            a$ = "Expected )": GOTO errmes
            ontimgotarg:
            IF e2$ = "" THEN a$ = "Expected ... )": GOTO errmes
            PRINT #12, "ontimer_setup(";
            'i
            IF LEN(e3$) THEN
                e$ = fixoperationorder$(e3$)
                l$ = l$ + sp2 + tlayout$ + "," + sp
                e$ = evaluatetotyp(e$, 32&)
                PRINT #12, e$ + ",";
            ELSE
                PRINT #12, "0,";
                l$ = l$ + sp2
            END IF
            'sec
            e$ = fixoperationorder$(e2$)
            l$ = l$ + tlayout$ + sp2 + ")" + sp
            e$ = evaluatetotyp(e$, DOUBLETYPE - ISPOINTER)
            PRINT #12, e$ + ",";
            i = i + 1
            IF i > n THEN a$ = "Expected GOSUB/CALL": GOTO errmes
            a2$ = getelement$(a$, i): i = i + 1
            ontimerid = ontimerid + 1
            PRINT #12, str2$(ontimerid) + ",";

            IF a2$ = "GOSUB" THEN
                IF i > n THEN a$ = "Expected linenumber/label": GOTO errmes
                a2$ = getelement$(ca$, i): i = i + 1

                PRINT #12, "0);"

                IF validlabel(a2$) = 0 THEN nerror (65)

v=HashFind(a2$,HASHFLAG_LABEL,ignore,r)
x=1
labchk60: 
if v then
s=labels(r).scope
if s=0 or s=-1 then 'main scope?
if s=-1 then labels(r).scope=0 'acquire scope
x=0 'already defined
tlayout$=rtrim$(labels(r).cn)
Labels(r).Scope_Restriction=subfuncn
Labels(r).Error_Line=linenumber
else
if v=2 then v=HashFindCont(ignore,r): goto labchk60
end if
end if
if x then
'does not exist
nLabels=nLabels+1: if nLabels>Labels_Ubound then Labels_Ubound=Labels_Ubound*2: redim _preserve Labels(1 to Labels_Ubound) as Label_Type
Labels(nLabels)=Empty_label
hashadd a2$,HASHFLAG_LABEL,nLabels
r=nLabels
Labels(r).state=0
Labels(r).cn=tlayout$
Labels(r).scope=0
Labels(r).Error_Line=linenumber
Labels(r).Scope_Restriction=subfuncn
end if 'x
                l$ = l$ + "GOSUB" + sp + tlayout$

                PRINT #25, "if(timer_event_id==" + str2$(ontimerid) + ")goto LABEL_" + a2$ + ";"

                PRINT #24, "case " + str2$(ontimerid) + ":"
                PRINT #24, "timer_event_occurred++;"
                PRINT #24, "timer_event_id=" + str2$(ontimerid) + ";"
                PRINT #24, "timer_event_occurred++;"
                PRINT #24, "QBMAIN(NULL);"
                PRINT #24, "event_return--;"
                PRINT #24, "break;"



                'call validlabel (to validate the label) [see goto]
                'increment ontimerid
                'use ontimerid to generate the jumper routine
                'etc.


                IF LEN(layout$) = 0 THEN layout$ = l$ ELSE layout$ = layout$ + sp + l$
                layoutdone = 1
                GOTO finishedline
            ELSE

                'establish whether sub a2$ exists using try
                x = 0
                try = findid(a2$)
                DO WHILE try
                    IF id.subfunc = 2 THEN x = 1: EXIT DO
                    IF try = 2 THEN findanotherid = 1: try = findid(a2$) ELSE try = 0
                LOOP
                IF x = 0 THEN a$ = "Expected GOSUB/sub": GOTO errmes

                l$ = l$ + a2$ '*

                PRINT #24, "case " + str2$(ontimerid) + ":"
                PRINT #24, RTRIM$(id.callname) + "(";

                IF id.args > 1 THEN a$ = "SUB requires more than one argument": GOTO errmes

                IF i > n THEN

                    IF id.args = 1 THEN a$ = "Expected argument after SUB": GOTO errmes
                    PRINT #12, "0);"
                    PRINT #24, ");"

                ELSE

                    IF id.args = 0 THEN a$ = "SUB has no arguments": GOTO errmes

                    t = CVL(id.arg)
                    b = t AND 511
                    IF b = 0 OR (t AND ISARRAY) <> 0 OR (t AND ISFLOAT) <> 0 OR (t AND ISSTRING) <> 0 OR (t AND ISOFFSETINBITS) <> 0 THEN a$ = "Only SUB arguments of integer-type allowed": GOTO errmes
                    IF b = 8 THEN ct$ = "int8"
                    IF b = 16 THEN ct$ = "int16"
                    IF b = 32 THEN ct$ = "int32"
                    IF b = 64 THEN ct$ = "int64"
                    IF t AND ISUNSIGNED THEN ct$ = "u" + ct$
                    PRINT #24, "(" + ct$ + "*)&i64);"

                    e$ = getelements$(ca$, i, n)
                    e$ = fixoperationorder$(e$)
                    l$ = l$ + sp + tlayout$
                    e$ = evaluatetotyp(e$, INTEGER64TYPE - ISPOINTER)
                    PRINT #12, e$ + ");"

                END IF

                PRINT #24, "break;"
                IF LEN(layout$) = 0 THEN layout$ = l$ ELSE layout$ = layout$ + sp + l$
                layoutdone = 1
                GOTO finishedline
            END IF

        END IF
    END IF


    'SHARED (SUB)
    IF n >= 1 THEN
        IF firstelement$ = "SHARED" THEN
            IF n = 1 THEN a$ = "Expected SHARED ...": GOTO errmes
            i = 2
            IF subfuncn = 0 THEN a$ = "SHARED must be used within a SUB/FUNCTION": GOTO errmes



            l$ = "SHARED"
            subfuncshr:

            'get variable name
            n$ = getelement$(ca$, i): i = i + 1

            IF n$ = "" THEN a$ = "Expected SHARED variable-name": GOTO errmes

            s$ = removesymbol(n$)
            l2$ = s$ 'either symbol or nothing

            'array?
            a = 0
            IF getelement$(a$, i) = "(" THEN
                IF getelement$(a$, i + 1) <> ")" THEN a$ = "Expected ()": GOTO errmes
                i = i + 2
                a = 1
                l2$ = l2$ + sp2 + "(" + sp2 + ")"
            END IF

            method = 1

            'specific type?
            t$ = ""
            ts$ = ""
            t3$ = ""
            IF getelement$(a$, i) = "AS" THEN
                l2$ = l2$ + sp + "AS"
                getshrtyp:
                i = i + 1
                t2$ = getelement$(a$, i)
                IF t2$ <> "," AND t2$ <> "" THEN
                    IF t$ = "" THEN t$ = t2$ ELSE t$ = t$ + " " + t2$
                    IF t3$ = "" THEN t3$ = t2$ ELSE t3$ = t3$ + sp + t2$
                    GOTO getshrtyp
                END IF
                IF t$ = "" THEN a$ = "Expected AS type": GOTO errmes

                t = typname2typ(t$)
                IF t AND ISINCONVENTIONALMEMORY THEN t = t - ISINCONVENTIONALMEMORY
                IF t AND ISPOINTER THEN t = t - ISPOINTER
                IF t AND ISREFERENCE THEN t = t - ISREFERENCE
                tsize = typname2typsize
                method = 0
                IF (t AND ISUDT) = 0 THEN ts$ = type2symbol$(t$) ELSE t3$ = RTRIM$(udtxcname(t AND 511))
                l2$ = l2$ + sp + t3$

            END IF 'as

            IF LEN(s$) <> 0 AND LEN(t$) <> 0 THEN a$ = "Expected symbol or AS type after variable name": GOTO errmes

            'no symbol of type specified, apply default
            IF s$ = "" AND t$ = "" THEN
                IF LEFT$(n$, 1) = "_" THEN v = 27 ELSE v = ASC(UCASE$(n$)) - 64
                s$ = defineextaz(v)
            END IF

            'switch to main module
            oldsubfunc$ = subfunc$
            subfunc$ = ""
            defdatahandle = 18
            CLOSE #13: OPEN tmpdir$ + "maindata.txt" FOR APPEND AS #13
            CLOSE #19: OPEN tmpdir$ + "mainfree.txt" FOR APPEND AS #19

            'use 'try' to locate the variable (if it already exists)
            n2$ = n$ + s$ + ts$ 'note: either ts$ or s$ will exist unless it is a UDT
            try = findid(n2$)
            DO WHILE try
                IF a THEN
                    'an array

                    IF id.arraytype THEN
                        IF LEN(t$) = 0 THEN GOTO shrfound
                        t2 = id.arraytype: t2size = id.tsize
                        IF t2 AND ISINCONVENTIONALMEMORY THEN t2 = t2 - ISINCONVENTIONALMEMORY
                        IF t2 AND ISPOINTER THEN t2 = t2 - ISPOINTER
                        IF t2 AND ISREFERENCE THEN t2 = t2 - ISREFERENCE
                        IF t = t2 AND tsize = t2size THEN GOTO shrfound
                    END IF

                ELSE
                    'not an array

                    IF id.t THEN
                        IF LEN(t$) = 0 THEN GOTO shrfound
                        t2 = id.t: t2size = id.tsize
                        IF t2 AND ISINCONVENTIONALMEMORY THEN t2 = t2 - ISINCONVENTIONALMEMORY
                        IF t2 AND ISPOINTER THEN t2 = t2 - ISPOINTER
                        IF t2 AND ISREFERENCE THEN t2 = t2 - ISREFERENCE

                        IF debug THEN PRINT #9, "SHARED:comparing:"; t; t2, tsize; t2size

                        IF t = t2 AND tsize = t2size THEN GOTO shrfound
                    END IF

                END IF

                IF try = 2 THEN findanotherid = 1: try = findid(n2$) ELSE try = 0
            LOOP
            'unknown variable
            IF a THEN a$ = "Array not defined": GOTO errmes
            'create variable
            IF LEN(s$) THEN typ$ = s$ ELSE typ$ = t$
            retval = dim2(n$, typ$, method, "")
            'note: variable created!

            shrfound:
            l$ = l$ + sp + RTRIM$(id.cn) + l2$

            ids(currentid).share = ids(currentid).share OR 2 'set as temporarily shared

            'method must apply to the current sub/function regardless of how the variable was defined in 'main'
            lmay = LEN(RTRIM$(id.mayhave)): lmust = LEN(RTRIM$(id.musthave))
            IF lmay <> 0 OR lmust <> 0 THEN
                IF (method = 1 AND lmust = 0) OR (method = 0 AND lmay = 0) THEN
                    revertmaymusthaven = revertmaymusthaven + 1
                    revertmaymusthave(revertmaymusthaven) = currentid
                    SWAP ids(currentid).musthave, ids(currentid).mayhave
                END IF
            END IF

            'switch back to sub/func
            subfunc$ = oldsubfunc$
            defdatahandle = 13
            CLOSE #13: OPEN tmpdir$ + "data" + str2$(subfuncn) + ".txt" FOR APPEND AS #13
            CLOSE #19: OPEN tmpdir$ + "free" + str2$(subfuncn) + ".txt" FOR APPEND AS #19

            IF getelement$(a$, i) = "," THEN i = i + 1: l$ = l$ + sp2 + ",": GOTO subfuncshr
            IF getelement$(a$, i) <> "" THEN a$ = "Expected ,": GOTO errmes

            layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
            GOTO finishedline
        END IF
    END IF

    'EXIT SUB/FUNCTION
    IF n = 2 THEN
        IF firstelement$ = "EXIT" THEN
            sf = 0
            IF secondelement$ = "FUNCTION" THEN sf = 1
            IF secondelement$ = "SUB" THEN sf = 2
            IF sf THEN

                if len(subfunc)=0 then a$="EXIT "+secondelement$+" must be used within a SUB/FUNCTION": goto errmes

                PRINT #12, "goto exit_subfunc;"
                l$ = firstelement$ + sp + secondelement$
                layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
                GOTO finishedline
            END IF
        END IF
    END IF




    'SWAP
    IF firstelement$ = "SWAP" THEN
        IF n < 4 THEN a$ = "Expected SWAP ... , ...": GOTO errmes
        b = 0
        ele = 1
        e1$ = ""
        e2$ = ""
        FOR i = 2 TO n
            e$ = getelement$(a$, i)
            IF e$ = "(" THEN b = b + 1
            IF e$ = ")" THEN b = b - 1
            IF e$ = "," AND b = 0 THEN
                IF ele = 2 THEN a$ = "Expected SWAP ... , ...": GOTO errmes
                ele = 2
            ELSE
                IF ele = 1 THEN e1$ = e1$ + sp + e$ ELSE e2$ = e2$ + sp + e$
            END IF
        NEXT
        IF e2$ = "" THEN a$ = "Expected SWAP ... , ...": GOTO errmes
        e1$ = RIGHT$(e1$, LEN(e1$) - 1): e2$ = RIGHT$(e2$, LEN(e2$) - 1)

        e1$ = fixoperationorder(e1$)
        e1l$ = tlayout$
        e2$ = fixoperationorder(e2$)
        e2l$ = tlayout$
        e1$ = evaluate(e1$, e1typ): e2$ = evaluate(e2$, e2typ)
        IF (e1typ AND ISREFERENCE) = 0 OR (e2typ AND ISREFERENCE) = 0 THEN a$ = "Expected variable": GOTO errmes

        layoutdone = 1
        l$ = "SWAP" + sp + e1l$ + sp2 + "," + sp + e2l$
        IF LEN(layout$) = 0 THEN layout$ = l$ ELSE layout$ = layout$ + sp + l$

        'swap strings?
        IF (e1typ AND ISSTRING) THEN
            IF (e2typ AND ISSTRING) = 0 THEN a$ = "Type mismatch": GOTO errmes
            e1$ = refer(e1$, e1typ, 0): e2$ = refer(e2$, e2typ, 0)
            PRINT #12, "swap_string(" + e1$ + "," + e2$ + ");"
            GOTO finishedline
        END IF

        'swap UDT?
        'note: entire UDTs, unlike thier elements cannot be swapped like standard variables
        '      as UDT sizes may vary, and to avoid a malloc operation, QB64 should allocate a buffer
        '      in global.txt for the purpose of swapping each UDT type

        IF e1typ AND ISUDT THEN
            a$ = e1$
            'retrieve ID
            i = INSTR(a$, "³")
            IF i THEN
                idnumber = VAL(LEFT$(a$, i - 1)): a$ = RIGHT$(a$, LEN(a$) - i)
                getid idnumber
                u = VAL(a$)
                i = INSTR(a$, "³"): a$ = RIGHT$(a$, LEN(a$) - i): e = VAL(a$)
                i = INSTR(a$, "³"): o$ = RIGHT$(a$, LEN(a$) - i)
                n$ = "UDT_" + RTRIM$(id.n): IF id.t = 0 THEN n$ = "ARRAY_" + n$ + "[0]"
                IF e = 0 THEN 'not an element of UDT u
                    lhsscope$ = scope$
                    e$ = e2$: t2 = e2typ
                    IF (t2 AND ISUDT) = 0 THEN a$ = "Expected SWAP with similar user defined type": GOTO errmes
                    idnumber2 = VAL(e$)
                    getid idnumber2
                    n2$ = "UDT_" + RTRIM$(id.n): IF id.t = 0 THEN n2$ = "ARRAY_" + n2$ + "[0]"
                    i = INSTR(e$, "³"): e$ = RIGHT$(e$, LEN(e$) - i): u2 = VAL(e$)
                    i = INSTR(e$, "³"): e$ = RIGHT$(e$, LEN(e$) - i): e2 = VAL(e$)
                    i = INSTR(e$, "³"): o2$ = RIGHT$(e$, LEN(e$) - i)
                    'WARNING: u2 may need minor modifications based on e to see if they are the same
                    IF u <> u2 OR e2 <> 0 THEN a$ = "Expected SWAP with similar user defined type": GOTO errmes
                    dst$ = "(((char*)" + lhsscope$ + n$ + ")+(" + o$ + "))"
                    src$ = "(((char*)" + scope$ + n2$ + ")+(" + o2$ + "))"
                    b = udtxsize(u) \ 8
                    siz$ = str2$(b)
                    IF b = 1 THEN PRINT #12, "swap_8(" + src$ + "," + dst$ + ");"
                    IF b = 2 THEN PRINT #12, "swap_16(" + src$ + "," + dst$ + ");"
                    IF b = 4 THEN PRINT #12, "swap_32(" + src$ + "," + dst$ + ");"
                    IF b = 8 THEN PRINT #12, "swap_64(" + src$ + "," + dst$ + ");"
                    IF b <> 1 AND b <> 2 AND b <> 4 AND b <> 8 THEN PRINT #12, "swap_block(" + src$ + "," + dst$ + "," + siz$ + ");"
                    GOTO finishedline
                END IF 'e=0
            END IF 'i
        END IF 'isudt

        'cull irrelavent flags to make comparison possible
        e1typc = e1typ
        IF e1typc AND ISPOINTER THEN e1typc = e1typc - ISPOINTER
        IF e1typc AND ISINCONVENTIONALMEMORY THEN e1typc = e1typc - ISINCONVENTIONALMEMORY
        IF e1typc AND ISARRAY THEN e1typc = e1typc - ISARRAY
        IF e1typc AND ISUNSIGNED THEN e1typc = e1typc - ISUNSIGNED
        IF e1typc AND ISUDT THEN e1typc = e1typc - ISUDT
        e2typc = e2typ
        IF e2typc AND ISPOINTER THEN e2typc = e2typc - ISPOINTER
        IF e2typc AND ISINCONVENTIONALMEMORY THEN e2typc = e2typc - ISINCONVENTIONALMEMORY
        IF e2typc AND ISARRAY THEN e2typc = e2typc - ISARRAY
        IF e2typc AND ISUNSIGNED THEN e2typc = e2typc - ISUNSIGNED
        IF e2typc AND ISUDT THEN e2typc = e2typc - ISUDT
        IF e1typc <> e2typc THEN a$ = "Type mismatch": GOTO errmes
        t = e1typ
        IF t AND ISOFFSETINBITS THEN a$ = "Cannot SWAP bit-length variables": GOTO errmes
        b = t AND 511
        t$ = str2$(b): IF b > 64 THEN t$ = "longdouble"
        PRINT #12, "swap_" + t$ + "(&" + refer(e1$, e1typ, 0) + ",&" + refer(e2$, e2typ, 0) + ");"
        GOTO finishedline
    END IF



    'LSET/RSET
    IF n >= 1 THEN
        IF firstelement$ = "LSET" OR firstelement$ = "RSET" THEN
            l$ = firstelement$
            dest$ = ""
            source$ = ""
            part = 1
            i = 2
            a3$ = ""
            b = 0
            DO
                IF i > n THEN
                    IF part <> 2 OR a3$ = "" THEN x = 1: GOTO errnum
                    source$ = a3$
                    EXIT DO
                END IF
                a2$ = getelement$(ca$, i)
                IF a2$ = "(" THEN b = b + 1
                IF a2$ = ")" THEN b = b - 1
                IF a2$ = "=" AND b = 0 THEN
                    IF part = 1 THEN dest$ = a3$: part = 2: a3$ = "": GOTO lrsetgotpart
                END IF
                IF LEN(a3$) THEN a3$ = a3$ + sp + a2$ ELSE a3$ = a2$
                lrsetgotpart:
                i = i + 1
            LOOP
            IF dest$ = "" THEN x = 2: GOTO errnum
            'check if it is a valid source string
            f$ = fixoperationorder$(dest$)
            l$ = l$ + sp + tlayout$ + sp + "="
            e$ = evaluate(f$, sourcetyp)
            IF (sourcetyp AND ISREFERENCE) = 0 OR (sourcetyp AND ISSTRING) = 0 THEN x = 3: GOTO errnum
            dest$ = evaluatetotyp(f$, ISSTRING)
            source$ = fixoperationorder$(source$)
            l$ = l$ + sp + tlayout$
            layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
            source$ = evaluatetotyp(source$, ISSTRING)
            IF firstelement$ = "LSET" THEN
                PRINT #12, "sub_lset(" + dest$ + "," + source$ + ");"
            ELSE
                PRINT #12, "sub_rset(" + dest$ + "," + source$ + ");"
            END IF
            GOTO finishedline
        END IF
    END IF

    'ASC statement (fully inline)
    IF n >= 1 THEN
        IF firstelement$ = "ASC" THEN
            IF getelement$(a$, 2) <> "(" THEN a$ = "Expected ( after ASC": GOTO errmes

            'calculate 3 parts
            useposition = 0
            part = 1
            i = 3
            a3$ = ""
            stringvariable$ = ""
            position$ = ""
            b = 0
            DO

                IF i > n THEN 'got part 3
                    IF part <> 3 OR LEN(a3$) = 0 THEN a$ = "Expected ASC ( ... , ... ) = ...": GOTO errmes
                    expression$ = a3$
                    EXIT DO
                END IF

                a2$ = getelement$(ca$, i)
                IF a2$ = "(" THEN b = b + 1
                IF a2$ = ")" THEN b = b - 1

                IF b = -1 THEN

                    IF part = 1 THEN 'eg. ASC(a$)=65
                        IF getelement$(a$, i + 1) <> "=" THEN a$ = "Expected =": GOTO errmes
                        stringvariable$ = a3$
                        position$ = "1"
                        part = 3: a3$ = "": i = i + 1: GOTO ascgotpart
                    END IF

                    IF part = 2 THEN 'eg. ASC(a$,i)=65
                        IF getelement$(a$, i + 1) <> "=" THEN a$ = "Expected =": GOTO errmes
                        useposition = 1
                        position$ = a3$
                        part = 3: a3$ = "": i = i + 1: GOTO ascgotpart
                    END IF

                    'fall through, already in part 3

                END IF

                IF a2$ = "," AND b = 0 THEN
                    IF part = 1 THEN stringvariable$ = a3$: part = 2: a3$ = "": GOTO ascgotpart
                END IF

                IF LEN(a3$) THEN a3$ = a3$ + sp + a2$ ELSE a3$ = a2$
                ascgotpart:
                i = i + 1
            LOOP
            IF LEN(stringvariable$) = 0 OR LEN(position$) = 0 THEN a$ = "Expected ASC ( ... , ... ) = ...": GOTO errmes

            'validate stringvariable$
            stringvariable$ = fixoperationorder$(stringvariable$)
            l$ = "ASC" + sp2 + "(" + sp2 + tlayout$

            e$ = evaluate(stringvariable$, sourcetyp)
            IF (sourcetyp AND ISREFERENCE) = 0 OR (sourcetyp AND ISSTRING) = 0 THEN a$ = "Expected ASC ( string-variable , ...": GOTO errmes
            stringvariable$ = evaluatetotyp(stringvariable$, ISSTRING)



            IF position$ = "1" THEN
                IF useposition THEN l$ = l$ + sp2 + "," + sp + "1" + sp2 + ")" + sp + "=" ELSE l$ = l$ + sp2 + ")" + sp + "="

                PRINT #12, "tqbs=" + stringvariable$ + "; if (!new_error){"
                e$ = fixoperationorder$(expression$)
                l$ = l$ + sp + tlayout$
                e$ = evaluatetotyp(e$, 32&)
                PRINT #12, "tmp_long=" + e$ + "; if (!new_error){"
                PRINT #12, "if (tqbs->len){tqbs->chr[0]=tmp_long;}else{error(5);}"
                PRINT #12, "}}"

            ELSE

                PRINT #12, "tqbs=" + stringvariable$ + "; if (!new_error){"
                e$ = fixoperationorder$(position$)
                l$ = l$ + sp2 + "," + sp + tlayout$ + sp2 + ")" + sp + "="
                e$ = evaluatetotyp(e$, 32&)
                PRINT #12, "tmp_fileno=" + e$ + "; if (!new_error){"
                e$ = fixoperationorder$(expression$)
                l$ = l$ + sp + tlayout$
                e$ = evaluatetotyp(e$, 32&)
                PRINT #12, "tmp_long=" + e$ + "; if (!new_error){"
                PRINT #12, "if ((tmp_fileno>0)&&(tmp_fileno<=tqbs->len)){tqbs->chr[tmp_fileno-1]=tmp_long;}else{error(5);}"
                PRINT #12, "}}}"

            END IF
            layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
            GOTO finishedline
        END IF
    END IF




    'MID$ statement
    IF n >= 1 THEN
        IF firstelement$ = "MID$" THEN
            IF getelement$(a$, 2) <> "(" THEN x = 4: GOTO errnum
            'calculate 4 parts
            length$ = ""
            part = 1
            i = 3
            a3$ = ""
            stringvariable$ = ""
            start$ = ""
            b = 0
            DO
                IF i > n THEN
                    IF part <> 4 OR a3$ = "" THEN x = 5: GOTO errnum
                    stringexpression$ = a3$
                    EXIT DO
                END IF
                a2$ = getelement$(ca$, i)
                IF a2$ = "(" THEN b = b + 1
                IF a2$ = ")" THEN b = b - 1
                IF b = -1 THEN
                    IF part = 2 THEN
                        IF getelement$(a$, i + 1) <> "=" THEN x = 6: GOTO errnum
                        start$ = a3$: part = 4: a3$ = "": i = i + 1: GOTO midgotpart
                    END IF
                    IF part = 3 THEN
                        IF getelement$(a$, i + 1) <> "=" THEN x = 7: GOTO errnum
                        IF a3$ = "" THEN x = 8: GOTO errnum
                        length$ = a3$: part = 4: a3$ = "": i = i + 1: GOTO midgotpart
                    END IF
                END IF
                IF a2$ = "," AND b = 0 THEN
                    IF part = 1 THEN stringvariable$ = a3$: part = 2: a3$ = "": GOTO midgotpart
                    IF part = 2 THEN start$ = a3$: part = 3: a3$ = "": GOTO midgotpart
                END IF
                IF LEN(a3$) THEN a3$ = a3$ + sp + a2$ ELSE a3$ = a2$
                midgotpart:
                i = i + 1
            LOOP
            IF stringvariable$ = "" THEN x = 9: GOTO errnum
            IF start$ = "" THEN x = 10: GOTO errnum
            'check if it is a valid source string
            stringvariable$ = fixoperationorder$(stringvariable$)
            l$ = "MID$" + sp2 + "(" + sp2 + tlayout$
            e$ = evaluate(stringvariable$, sourcetyp)
            IF (sourcetyp AND ISREFERENCE) = 0 OR (sourcetyp AND ISSTRING) = 0 THEN x = 11: GOTO errnum
            stringvariable$ = evaluatetotyp(stringvariable$, ISSTRING)

            start$ = evaluatetotyp(fixoperationorder$(start$), 32&)
            l$ = l$ + sp2 + "," + sp + tlayout$

            stringexpression$ = fixoperationorder$(stringexpression$)
            l2$ = tlayout$
            stringexpression$ = evaluatetotyp(stringexpression$, ISSTRING)

            IF LEN(length$) THEN
                length$ = fixoperationorder$(length$)
                l$ = l$ + sp2 + "," + sp + tlayout$
                length$ = evaluatetotyp(length$, 32&)
                PRINT #12, "sub_mid(" + stringvariable$ + "," + start$ + "," + length$ + "," + stringexpression$ + ",1);"
            ELSE
                PRINT #12, "sub_mid(" + stringvariable$ + "," + start$ + ",0," + stringexpression$ + ",0);"
            END IF

            l$ = l$ + sp2 + ")" + sp + "=" + sp + l2$
            layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
            GOTO finishedline
        END IF
    END IF


    IF n >= 2 THEN
        IF firstelement$ = "ERASE" THEN
            i = 2
            l$ = "ERASE"
            erasenextarray:
            var$ = getelement$(ca$, i)
            x$ = var$: ls$ = removesymbol(x$)
            reattempterase:
            try = findid(var$)
            DO WHILE try
                IF id.arraytype THEN
                    l$ = l$ + sp + RTRIM$(id.cn) + ls$
                    'erase the array
                    clearerase:
                    n$ = RTRIM$(id.callname)
                    bytesperelement$ = str2((id.arraytype AND 511) \ 8)
                    IF id.arraytype AND ISSTRING THEN bytesperelement$ = str2(id.tsize)
                    IF id.arraytype AND ISOFFSETINBITS THEN bytesperelement$ = str2((id.arraytype AND 511)) + "/8+1"
                    IF id.arraytype AND ISUDT THEN
                        bytesperelement$ = str2(udtxsize(id.arraytype AND 511) \ 8)
                    END IF
                    PRINT #12, "if (" + n$ + "[2]&1){" 'array is defined
                    PRINT #12, "if (" + n$ + "[2]&2){" 'array is static
                    IF (id.arraytype AND ISSTRING) <> 0 AND (id.arraytype AND ISFIXEDLENGTH) = 0 THEN
                        PRINT #12, "tmp_long=";
                        FOR i2 = 1 TO ABS(id.arrayelements)
                            IF i2 <> 1 THEN PRINT #12, "*";
                            PRINT #12, n$ + "[" + str2(i2 * 4 - 4 + 5) + "]";
                        NEXT
                        PRINT #12, ";"
                        PRINT #12, "while(tmp_long--){"
                        PRINT #12, "((qbs*)(((uint64*)(" + n$ + "[0]))[tmp_long]))->len=0;"
                        PRINT #12, "}"
                    ELSE
                        'numeric
                        'clear array
                        PRINT #12, "memset((void*)(" + n$ + "[0]),0,";
                        FOR i2 = 1 TO ABS(id.arrayelements)
                            IF i2 <> 1 THEN PRINT #12, "*";
                            PRINT #12, n$ + "[" + str2(i2 * 4 - 4 + 5) + "]";
                        NEXT
                        PRINT #12, "*" + bytesperelement$ + ");"
                    END IF
                    PRINT #12, "}else{" 'array is dynamic
                    '1. free memory & any allocated strings
                    IF (id.arraytype AND ISSTRING) <> 0 AND (id.arraytype AND ISFIXEDLENGTH) = 0 THEN
                        'free strings
                        PRINT #12, "tmp_long=";
                        FOR i2 = 1 TO ABS(id.arrayelements)
                            IF i2 <> 1 THEN PRINT #12, "*";
                            PRINT #12, n$ + "[" + str2(i2 * 4 - 4 + 5) + "]";
                        NEXT
                        PRINT #12, ";"
                        PRINT #12, "while(tmp_long--){"
                        PRINT #12, "qbs_free((qbs*)(((uint64*)(" + n$ + "[0]))[tmp_long]));"
                        PRINT #12, "}"
                        'free memory
                        PRINT #12, "free((void*)(" + n$ + "[0]));"
                    ELSE
                        'free memory
                        PRINT #12, "if (" + n$ + "[2]&4){" 'cmem array
                        PRINT #12, "cmem_dynamic_free((uint8*)(" + n$ + "[0]));"
                        PRINT #12, "}else{" 'non-cmem array
                        PRINT #12, "free((void*)(" + n$ + "[0]));"
                        PRINT #12, "}"
                    END IF
                    '2. set array (and its elements) as undefined
                    PRINT #12, n$ + "[2]^=1;" 'remove defined flag, keeping other flags (such as cmem)
                    'set dimensions as undefined
                    FOR i2 = 1 TO ABS(id.arrayelements)
                        b = i2 * 4
                        PRINT #12, n$ + "[" + str2(b) + "]=2147483647;" 'base
                        PRINT #12, n$ + "[" + str2(b + 1) + "]=0;" 'num. index
                        PRINT #12, n$ + "[" + str2(b + 2) + "]=0;" 'multiplier
                    NEXT
                    IF (id.arraytype AND ISSTRING) <> 0 AND (id.arraytype AND ISFIXEDLENGTH) = 0 THEN
                        PRINT #12, n$ + "[0]=(ptrszint)&nothingstring;"
                    ELSE
                        PRINT #12, n$ + "[0]=(ptrszint)nothingvalue;"
                    END IF
                    PRINT #12, "}" 'static/dynamic
                    PRINT #12, "}" 'array is defined
                    IF clearerasereturn = 1 THEN clearerasereturn = 0: GOTO clearerasereturned
                    GOTO erasedarray
                END IF
                IF try = 2 THEN findanotherid = 1: try = findid(var$) ELSE try = 0
            LOOP

            'add extension (if possible) as retry
            IF isvalidvariable(var$) THEN
                dtyp$ = removesymbol(var$)
                IF dtyp$ = "" THEN
                    IF LEFT$(var$, 1) = "_" THEN v = 27 ELSE v = ASC(UCASE$(var$)) - 64
                    're-attempt array erase
                    var$ = var$ + defineextaz(v)
                    GOTO reattempterase
                END IF
            END IF

            x = 32: GOTO errnum

            erasedarray:
            IF i < n THEN
                i = i + 1: n$ = getelement$(a$, i): IF n$ <> "," THEN x = 33: GOTO errnum
                l$ = l$ + sp2 + ","
                i = i + 1: IF i > n THEN x = 34: GOTO errnum
                GOTO erasenextarray
            END IF

            layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
            GOTO finishedline
        END IF
    END IF


    'DIM/REDIM/STATIC
    IF n >= 2 THEN
        dimoption = 0: redimoption = 0: commonoption = 0
        IF firstelement$ = "DIM" THEN dimoption = 1
        IF firstelement$ = "REDIM" THEN
            dimoption = 2: redimoption = 1
            IF secondelement$ = "_PRESERVE" THEN
                redimoption = 2
                IF n = 2 THEN a$ = "Expected REDIM _PRESERVE ...": GOTO errmes
            END IF
        END IF
        IF firstelement$ = "STATIC" THEN dimoption = 3
        IF firstelement$ = "COMMON" THEN dimoption = 1: commonoption = 1
        IF dimoption THEN
            l$ = firstelement$

            IF dimoption = 3 AND subfuncn = 0 THEN a$ = "STATIC must be used within a SUB/FUNCTION": GOTO errmes
            IF commonoption = 1 AND subfuncn <> 0 THEN a$ = "COMMON cannot be used within a SUB/FUNCTION": GOTO errmes

            i = 2
            IF redimoption = 2 THEN i = 3: l$ = l$ + sp + "_PRESERVE"

            IF dimoption <> 3 THEN 'shared cannot be static
                a2$ = getelement(a$, i)
                IF a2$ = "SHARED" THEN
                    IF subfuncn <> 0 THEN a$ = "DIM/REDIM SHARED invalid within a SUB/FUNCTION": GOTO errmes
                    dimshared = 1
                    i = i + 1
                    l$ = l$ + sp + a2$
                END IF
            END IF

            IF dimoption = 3 THEN dimstatic = 1

            dimnext:

            listarray = 0


            'old chain code
            'chaincommonarray=0

            varname$ = getelement(ca$, i): i = i + 1
            IF varname$ = "" THEN a$ = "Expected variable-name": GOTO errmes

            'get the next element
            IF i >= n + 1 THEN e$ = "" ELSE e$ = getelement(a$, i): i = i + 1

            'check if next element is a ( to create an array
            elements$ = ""

            IF e$ = "(" THEN
                b = 1
                FOR i = i TO n
                    e$ = getelement(ca$, i)
                    IF e$ = "(" THEN b = b + 1
                    IF e$ = ")" THEN b = b - 1
                    IF b = 0 THEN EXIT FOR
                    IF LEN(elements$) THEN elements$ = elements$ + sp + e$ ELSE elements$ = e$
                NEXT
                IF b <> 0 THEN a$ = "Expected )": GOTO errmes
                i = i + 1 'set i to point to the next element

                IF commonoption THEN elements$ = "?"


                IF debug THEN PRINT #9, "DIM2:array:elements$:[" + elements$ + "]"

                'arrayname() means list array to it will automatically be static when it is formally dimensioned later
                'note: listed arrays are always created in dynamic memory, but their contents are not erased
                '      this differs from static arrays from SUB...STATIC and the unique QB64 method -> STATIC arrayname(100)
                IF dimoption = 3 THEN 'STATIC
                    IF LEN(elements$) = 0 THEN
                        listarray = 1
                    END IF
                END IF

                'last element was ")"
                'get next element
                IF i >= n + 1 THEN e$ = "" ELSE e$ = getelement(a$, i): i = i + 1
            END IF 'e$="("
            d$ = e$

            dimmethod = 0

            appendname$ = "" 'the symbol to append to name returned by dim2
            appendtype$ = "" 'eg. sp+AS+spINTEGER
            dim2typepassback$ = ""

            'does varname have an appended symbol?
            s$ = removesymbol$(varname$)
            IF s$ <> "" THEN
                typ$ = s$
                dimmethod = 1
                appendname$ = typ$
                GOTO dimgottyp
            END IF

            IF d$ = "AS" THEN

                appendtype$ = sp + "AS"
                typ$ = ""
                FOR i = i TO n
                    d$ = getelement(a$, i)
                    IF d$ = "," THEN i = i + 1: EXIT FOR
                    typ$ = typ$ + d$ + " "
                    appendtype$ = appendtype$ + sp + d$
                    d$ = ""
                NEXT
                appendtype$ = UCASE$(appendtype$) 'capitalise default types (udt override this later if necessary)
                typ$ = RTRIM$(typ$)
                GOTO dimgottyp
            END IF

            'auto-define type based on name
            IF LEFT$(varname$, 1) = "_" THEN v = 27 ELSE v = ASC(UCASE$(varname$)) - 64
            typ$ = defineaz(v)
            dimmethod = 1
            GOTO dimgottyp
            dimgottyp:
            IF d$ <> "" AND d$ <> "," THEN x = 35: GOTO errnum



            IF listarray THEN 'eg. STATIC a()
                'note: static list arrays cannot be created until they are formally (RE)DIM'd later
                IF LEN(staticarraylist) THEN staticarraylist = staticarraylist + sp
                staticarraylist = staticarraylist + varname$ + sp + symbol2fulltypename$(typ$) + sp + str2(dimmethod)
                staticarraylistn = staticarraylistn + 1
                l$ = l$ + sp + varname$ + appendname$ + sp2 + "(" + sp2 + ")" + appendtype$
                'note: none of the following code is run, dim2 call is also skipped

            ELSE

                olddimstatic = dimstatic

                'check if varname is on the static list
                IF LEN(elements$) THEN 'it's an array
                    IF subfuncn THEN 'it's in a sub/function
                        xi = 1
                        FOR x = 1 TO staticarraylistn
                            varname2$ = getelement$(staticarraylist, xi): xi = xi + 1
                            typ2$ = getelement$(staticarraylist, xi): xi = xi + 1
                            dimmethod2 = VAL(getelement$(staticarraylist, xi)): xi = xi + 1
                            'check if they are similar
                            IF UCASE$(varname$) = UCASE$(varname2$) THEN
                                IF symbol2fulltypename$(typ$) = typ2$ THEN
                                    IF dimmethod = dimmethod2 THEN
                                        'match found!
                                        varname$ = varname2$
                                        dimstatic = 3
                                        IF dimoption = 3 THEN a$ = "Array already listed as STATIC": GOTO errmes
                                    END IF
                                END IF 'typ
                            END IF 'varname
                        NEXT
                    END IF
                END IF

                'COMMON exception
                'note: COMMON alone does not imply SHARED
                '      if either(or both) COMMON & later DIM have SHARED, variable becomes shared
                IF commonoption THEN
                    IF LEN(elements$) THEN
                        'add array to list
                        IF LEN(commonarraylist) THEN commonarraylist = commonarraylist + sp
                        'note: dimmethod distinguishes between a%(...) vs a(...) AS INTEGER
                        commonarraylist = commonarraylist + varname$ + sp + symbol2fulltypename$(typ$) + sp + str2(dimmethod) + sp + str2(dimshared)
                        commonarraylistn = commonarraylistn + 1
                        IF debug THEN PRINT #9, "common listed:" + varname$ + sp + symbol2fulltypename$(typ$) + sp + str2(dimmethod) + sp + str2(dimshared)
                        '   tlayout$=varname$+sp+"("+sp2+")"

                        'note: elements$="?"

                        'note: the following code only adds include directives, everything else is defered

                        x = idn + 1 'the id number of the array

                        OPEN tmpdir$ + "chain.txt" FOR APPEND AS #22
                        'include directive
                        PRINT #22, "#include " + CHR$(34) + "chain" + str2$(x) + ".txt" + CHR$(34)
                        CLOSE #22
                        'create/clear include file
                        OPEN tmpdir$ + "chain" + str2$(x) + ".txt" FOR OUTPUT AS #22: CLOSE #22

                        OPEN tmpdir$ + "inpchain.txt" FOR APPEND AS #22
                        'include directive
                        PRINT #22, "#include " + CHR$(34) + "inpchain" + str2$(x) + ".txt" + CHR$(34)
                        CLOSE #22
                        'create/clear include file
                        OPEN tmpdir$ + "inpchain" + str2$(x) + ".txt" FOR OUTPUT AS #22: CLOSE #22

                        GOTO dimcommonarray



                        'old chain code
                        ''add #include to chain.txt & inpchain.txt:
                        '
                        'OPEN tmpdir$ + "chain.txt" FOR APPEND AS #22
                        '
                        ''add array place-holder
                        'print #22,"int32val=2;" 'array place-holder
                        'print #22,"sub_put(FF,NULL,byte_element((uint64)&int32val,4),0);"
                        '
                        'PRINT #22, "#include " + CHR$(34) + "chain" + str2$(commonarraylistn) + ".txt" + CHR$(34)
                        '
                        'CLOSE #22
                        'open tmpdir$ + "chain" + str2$(commonarraylistn) + ".txt" for output as #22:close #22
                        '
                        'OPEN tmpdir$ + "inpchain.txt" FOR APPEND AS #23
                        'PRINT #23, "#include " + CHR$(34) + "inpchain" + str2$(commonarraylistn) + ".txt" + CHR$(34)
                        'CLOSE #23
                        'open tmpdir$ + "inpchain" + str2$(commonarraylistn) + ".txt" for output as #23:close #23



                        'create an array with one element
                        'redirect output of creator to dump file





                        'goto commonarraylisted
                    END IF
                END IF

                'is varname on common list?
                '******
                IF LEN(elements$) THEN 'it's an array
                    IF subfuncn = 0 THEN 'not in a sub/function

                        IF debug THEN PRINT #9, "common checking:" + varname$

                        xi = 1
                        FOR x = 1 TO commonarraylistn
                            varname2$ = getelement$(commonarraylist, xi): xi = xi + 1
                            typ2$ = getelement$(commonarraylist, xi): xi = xi + 1
                            dimmethod2 = VAL(getelement$(commonarraylist, xi)): xi = xi + 1
                            dimshared2 = VAL(getelement$(commonarraylist, xi)): xi = xi + 1
                            IF debug THEN PRINT #9, "common checking against:" + varname2$ + sp + typ2$ + sp + str2(dimmethod2) + sp + str2(dimshared2)
                            'check if they are similar
                            IF varname$ = varname2$ THEN
                                IF symbol2fulltypename$(typ$) = typ2$ THEN
                                    IF dimmethod = dimmethod2 THEN

                                        'match found!
                                        'enforce shared status (if necessary)
                                        IF dimshared2 THEN dimshared = dimshared + 2 'temp force SHARED

                                        'old chain code
                                        'chaincommonarray=x

                                    END IF 'method
                                END IF 'typ
                            END IF 'varname
                        NEXT
                    END IF
                END IF

                dimcommonarray:

                retval = dim2(varname$, typ$, dimmethod, elements$)
                IF dimshared >= 2 THEN dimshared = dimshared - 2

                'non-array COMMON variable
                IF commonoption <> 0 AND LEN(elements$) = 0 THEN

                    'CHAIN.TXT (save)

                    'switch output from main.txt to chain.txt
                    CLOSE #12
                    OPEN tmpdir$ + "chain.txt" FOR APPEND AS #12
                    l2$ = tlayout$

                    PRINT #12, "int32val=1;" 'simple variable
                    PRINT #12, "sub_put(FF,NULL,byte_element((uint64)&int32val,4),0);"

                    t = id.t
                    bits = t AND 511
                    IF t AND ISUDT THEN bits = udtxsize(t AND 511)
                    IF t AND ISSTRING THEN
                        IF t AND ISFIXEDLENGTH THEN
                            bits = id.tsize * 8
                        ELSE
                            PRINT #12, "int64val=__STRING_" + RTRIM$(id.n) + "->len*8;"
                            bits = 0
                        END IF
                    END IF

                    IF bits THEN
                        PRINT #12, "int64val=" + str2$(bits) + ";" 'size in bits
                    END IF
                    PRINT #12, "sub_put(FF,NULL,byte_element((uint64)&int64val,8),0);"

                    'put the variable
                    e$ = RTRIM$(id.n)

                    IF (t AND ISUDT) = 0 THEN
                        IF t AND ISFIXEDLENGTH THEN
                            e$ = e$ + "$" + str2$(id.tsize)
                        ELSE
                            e$ = e$ + typevalue2symbol$(t)
                        END IF
                    END IF
                    e$ = evaluatetotyp(fixoperationorder$(e$), -4)

                    PRINT #12, "sub_put(FF,NULL," + e$ + ",0);"

                    tlayout$ = l2$
                    'revert output to main.txt
                    CLOSE #12
                    OPEN tmpdir$ + "main.txt" FOR APPEND AS #12


                    'INPCHAIN.TXT (load)

                    'switch output from main.txt to chain.txt
                    CLOSE #12
                    OPEN tmpdir$ + "inpchain.txt" FOR APPEND AS #12
                    l2$ = tlayout$


                    PRINT #12, "if (int32val==1){"
                    'get the size in bits
                    PRINT #12, "sub_get(FF,NULL,byte_element((uint64)&int64val,8),0);"
                    '***assume correct size***

                    e$ = RTRIM$(id.n)
                    t = id.t
                    IF (t AND ISUDT) = 0 THEN
                        IF t AND ISFIXEDLENGTH THEN
                            e$ = e$ + "$" + str2$(id.tsize)
                        ELSE
                            e$ = e$ + typevalue2symbol$(t)
                        END IF
                    END IF

                    IF t AND ISSTRING THEN
                        IF (t AND ISFIXEDLENGTH) = 0 THEN
                            PRINT #12, "tqbs=qbs_new(int64val>>3,1);"
                            PRINT #12, "qbs_set(__STRING_" + RTRIM$(id.n) + ",tqbs);"
                            'now that the string is the correct size, the following GET command will work correctly...
                        END IF
                    END IF

                    e$ = evaluatetotyp(fixoperationorder$(e$), -4)
                    PRINT #12, "sub_get(FF,NULL," + e$ + ",0);"

                    PRINT #12, "sub_get(FF,NULL,byte_element((uint64)&int32val,4),0);" 'get next command
                    PRINT #12, "}"

                    tlayout$ = l2$
                    'revert output to main.txt
                    CLOSE #12
                    OPEN tmpdir$ + "main.txt" FOR APPEND AS #12






                END IF

                commonarraylisted:

                n2 = numelements(tlayout$)
                l$ = l$ + sp + getelement$(tlayout$, 1) + appendname$
                IF n2 > 1 THEN
                    l$ = l$ + sp2 + getelements$(tlayout$, 2, n2)
                END IF

                IF LEN(appendtype$) THEN
                    IF LEN(dim2typepassback$) THEN appendtype$ = sp + "AS" + sp + dim2typepassback$
                    l$ = l$ + appendtype$
                END IF

                'modify first element name to include symbol

                dimstatic = olddimstatic

            END IF 'listarray=0


            IF d$ = "," THEN l$ = l$ + sp2 + ",": GOTO dimnext

            dimshared = 0
            redimoption = 0
            IF dimstatic = 1 THEN dimstatic = 0

            layoutdone = 1
            IF LEN(layout$) = 0 THEN layout$ = l$ ELSE layout$ = layout$ + sp + l$

            GOTO finishedline
        END IF
    END IF











    'THEN [GOTO] linenumber?
    IF THENGOTO = 1 THEN
        IF n = 1 THEN
            l$ = ""
            a = ASC(LEFT$(firstelement$, 1))
            IF a = 46 OR (a >= 48 AND a <= 57) THEN a2$ = ca$: GOTO THENGOTO
        END IF
    END IF

    'goto
    IF n = 2 THEN
        IF getelement$(a$, 1) = "GOTO" THEN
            l$ = "GOTO"
            a2$ = getelement$(ca$, 2)
            THENGOTO:
            IF validlabel(a2$) = 0 THEN x = 36: GOTO errnum

v=HashFind(a2$,HASHFLAG_LABEL,ignore,r)
x=1
labchk2: 
if v then
s=labels(r).scope
if s=subfuncn or s=-1 then 'same scope?
if s=-1 then labels(r).scope=subfuncn 'acquire scope
x=0 'already defined
tlayout$=rtrim$(labels(r).cn)
else
if v=2 then v=HashFindCont(ignore,r): goto labchk2
end if
end if
if x then
'does not exist
nLabels=nLabels+1: if nLabels>Labels_Ubound then Labels_Ubound=Labels_Ubound*2: redim _preserve Labels(1 to Labels_Ubound) as Label_Type
Labels(nLabels)=Empty_label
hashadd a2$,HASHFLAG_LABEL,nLabels
r=nLabels
Labels(r).state=0
Labels(r).cn=tlayout$
Labels(r).scope=subfuncn
Labels(r).Error_Line=linenumber
end if 'x

            IF LEN(l$) THEN l$ = l$ + sp + tlayout$ ELSE l$ = tlayout$
            layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
            PRINT #12, "goto LABEL_" + a2$ + ";"
            GOTO finishedline
        END IF
    END IF



    IF firstelement$ = "RUN" THEN 'RUN
        l$ = "RUN"
        IF n = 1 THEN
            'no parameters
            PRINT #12, "sub_run_init();" 'note: called first to free up screen-locked image handles
            PRINT #12, "sub_clear(NULL,NULL);" 'use functionality of CLEAR
            IF LEN(subfunc$) THEN
                PRINT #12, "QBMAIN(NULL);"
            ELSE
                PRINT #12, "goto S_0;"
            END IF
        ELSE
            'parameter passed
            e$ = getelements$(ca$, 2, n)
            e$ = fixoperationorder$(e$)
            l2$ = tlayout$
            ignore$ = evaluate(e$, typ)
            IF n = 2 AND ((typ AND ISSTRING) = 0) THEN
                'assume it's a label or line number
                lbl$ = getelement$(ca$, 2)
                IF validlabel(lbl$) = 0 THEN x = 36: GOTO errnum 'invalid label

v=HashFind(lbl$,HASHFLAG_LABEL,ignore,r)
x=1
labchk501: 
if v then
s=labels(r).scope
if s=0 or s=-1 then 'main scope?
if s=-1 then labels(r).scope=0 'acquire scope
x=0 'already defined
tlayout$=rtrim$(labels(r).cn)
Labels(r).Scope_Restriction=subfuncn
Labels(r).Error_Line=linenumber
else
if v=2 then v=HashFindCont(ignore,r): goto labchk501
end if
end if
if x then
'does not exist
nLabels=nLabels+1: if nLabels>Labels_Ubound then Labels_Ubound=Labels_Ubound*2: redim _preserve Labels(1 to Labels_Ubound) as Label_Type
Labels(nLabels)=Empty_label
hashadd lbl$,HASHFLAG_LABEL,nLabels
r=nLabels
Labels(r).state=0
Labels(r).cn=tlayout$
Labels(r).scope=0
Labels(r).Error_Line=linenumber
Labels(r).Scope_Restriction=subfuncn
end if 'x

                l$ = l$ + sp + tlayout$
                PRINT #12, "sub_run_init();" 'note: called first to free up screen-locked image handles
                PRINT #12, "sub_clear(NULL,NULL);" 'use functionality of CLEAR
                IF LEN(subfunc$) THEN
                    PRINT #21, "if (run_from_line==" + str2(nextrunlineindex) + "){run_from_line=0;goto LABEL_" + lbl$ + ";}"
                    PRINT #12, "run_from_line=" + str2(nextrunlineindex) + ";"
                    nextrunlineindex = nextrunlineindex + 1
                    PRINT #12, "QBMAIN(NULL);"
                ELSE
                    PRINT #12, "goto LABEL_" + lbl$ + ";"
                END IF
            ELSE
                'assume it's a string containing a filename to execute
                e$ = evaluatetotyp(e$, ISSTRING)
                PRINT #12, "sub_run(" + e$ + ");"
                l$ = l$ + sp + l2$
            END IF 'isstring
        END IF 'n=1
        layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
        GOTO finishedline
    END IF 'run

    'KEY OFF (stub)
    IF n = 2 THEN
        IF firstelement$ = "KEY" THEN
            IF getelement$(a$, 2) = "OFF" THEN
                l$ = "KEY" + sp + "OFF"
                layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
                GOTO finishedline
            END IF
        END IF
    END IF '2

    'note: ABSOLUTE cannot be used without CALL
    cispecial = 0
    IF n > 1 THEN
        IF firstelement$ = "INTERRUPT" OR firstelement$ = "INTERRUPTX" THEN
            a$ = "CALL" + sp + firstelement$ + sp + "(" + sp + getelements$(a$, 2, n) + sp + ")"
            ca$ = "CALL" + sp + firstelement$ + sp + "(" + sp + getelements$(ca$, 2, n) + sp + ")"
            n = n + 3
            firstelement$ = "CALL"
            cispecial = 1
            'fall through
        END IF
    END IF

    usecall = 0
    IF firstelement$ = "CALL" THEN
        usecall = 1
        IF n = 1 THEN a$ = "Expected CALL sub-name [(...)]": GOTO errmes
        cn$ = getelement$(ca$, 2): n$ = UCASE$(cn$)

        IF n > 2 THEN

            IF n <= 4 THEN a$ = "Expected CALL sub-name (...)": GOTO errmes
            IF getelement$(a$, 3) <> "(" OR getelement$(a$, n) <> ")" THEN a$ = "Expected CALL sub-name (...)": GOTO errmes
            a$ = n$ + sp + getelements$(a$, 4, n - 1)
            ca$ = cn$ + sp + getelements$(ca$, 4, n - 1)


            IF n$ = "INTERRUPT" OR n$ = "INTERRUPTX" THEN 'assume CALL INTERRUPT[X] request
                'print "CI: call interrupt command reached":sleep 1
                IF n$ = "INTERRUPT" THEN PRINT #12, "call_interrupt("; ELSE PRINT #12, "call_interruptx(";
                argn = 0
                n = numelements(a$)
                b = 0
                e$ = ""
                FOR i = 2 TO n
                    e2$ = getelement$(ca$, i)
                    IF e2$ = "(" THEN b = b + 1
                    IF e2$ = ")" THEN b = b - 1
                    IF (e2$ = "," AND b = 0) OR i = n THEN
                        IF i = n THEN
                            IF e$ = "" THEN e$ = e2$ ELSE e$ = e$ + sp + e2$
                        END IF
                        argn = argn + 1
                        IF argn = 1 THEN 'interrupt number
                            e$ = fixoperationorder$(e$)
                            l$ = "CALL" + sp + n$ + sp2 + "(" + sp2 + tlayout$
                            IF cispecial = 1 THEN l$ = n$ + sp + tlayout$
                            e$ = evaluatetotyp(e$, 64&)
                            'print "CI: evaluated interrupt number as ["+e$+"]":sleep 1
                            PRINT #12, e$;
                        END IF
                        IF argn = 2 OR argn = 3 THEN 'inregs, outregs
                            e$ = fixoperationorder$(e$)
                            l$ = l$ + sp2 + "," + sp + tlayout$
                            e2$ = e$
                            e$ = evaluatetotyp(e$, -2) 'offset+size
                            'print "CI: evaluated in/out regs ["+e2$+"] as ["+e$+"]":sleep 1
                            PRINT #12, "," + e$;
                        END IF
                        e$ = ""
                    ELSE
                        IF e$ = "" THEN e$ = e2$ ELSE e$ = e$ + sp + e2$
                    END IF
                NEXT
                IF argn <> 3 THEN a$ = "Expected CALL INTERRUPT (interrupt-no, inregs, outregs)": GOTO errmes
                PRINT #12, ");"
                IF cispecial = 0 THEN l$ = l$ + sp2 + ")"
                layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
                'print "CI: done":sleep 1
                GOTO finishedline
            END IF 'call interrupt








            'call to CALL ABSOLUTE beyond reasonable doubt
            IF n$ = "ABSOLUTE" THEN
                l$ = "CALL" + sp + "ABSOLUTE" + sp2 + "(" + sp2
                argn = 0
                n = numelements(a$)
                b = 0
                e$ = ""
                FOR i = 2 TO n
                    e2$ = getelement$(ca$, i)
                    IF e2$ = "(" THEN b = b + 1
                    IF e2$ = ")" THEN b = b - 1
                    IF (e2$ = "," AND b = 0) OR i = n THEN
                        IF i < n THEN
                            IF e$ = "" THEN a$ = "Expected expression before , or )": GOTO errmes
                            '1. variable or value?
                            e$ = fixoperationorder$(e$)
                            l$ = l$ + tlayout$ + sp2 + "," + sp
                            ignore$ = evaluate(e$, typ)

                            IF (typ AND ISPOINTER) <> 0 AND (typ AND ISREFERENCE) <> 0 THEN

                                'assume standard variable
                                'assume not string/array/udt/etc
                                e$ = "VARPTR" + sp + "(" + sp + e$ + sp + ")"
                                e$ = evaluatetotyp(e$, UINTEGERTYPE - ISPOINTER)

                            ELSE

                                'assume not string
                                'single, double or integer64?
                                IF typ AND ISFLOAT THEN
                                    IF (typ AND 511) = 32 THEN
                                        e$ = evaluatetotyp(e$, SINGLETYPE - ISPOINTER)
                                        v$ = "pass" + str2$(uniquenumber)
                                        PRINT #defdatahandle, "float *" + v$ + "=NULL;"
                                        PRINT #13, "if(" + v$ + "==NULL){"
                                        PRINT #13, "cmem_sp-=4;"
                                        PRINT #13, v$ + "=(float*)(dblock+cmem_sp);"
                                        PRINT #13, "if (cmem_sp<qbs_cmem_sp) error(257);"
                                        PRINT #13, "}"
                                        e$ = "(uint16)(((uint8*)&(*" + v$ + "=" + e$ + "))-((uint8*)dblock))"
                                    ELSE
                                        e$ = evaluatetotyp(e$, DOUBLETYPE - ISPOINTER)
                                        v$ = "pass" + str2$(uniquenumber)
                                        PRINT #defdatahandle, "double *" + v$ + "=NULL;"
                                        PRINT #13, "if(" + v$ + "==NULL){"
                                        PRINT #13, "cmem_sp-=8;"
                                        PRINT #13, v$ + "=(double*)(dblock+cmem_sp);"
                                        PRINT #13, "if (cmem_sp<qbs_cmem_sp) error(257);"
                                        PRINT #13, "}"
                                        e$ = "(uint16)(((uint8*)&(*" + v$ + "=" + e$ + "))-((uint8*)dblock))"
                                    END IF
                                ELSE
                                    e$ = evaluatetotyp(e$, INTEGER64TYPE - ISPOINTER)
                                    v$ = "pass" + str2$(uniquenumber)
                                    PRINT #defdatahandle, "int64 *" + v$ + "=NULL;"
                                    PRINT #13, "if(" + v$ + "==NULL){"
                                    PRINT #13, "cmem_sp-=8;"
                                    PRINT #13, v$ + "=(int64*)(dblock+cmem_sp);"
                                    PRINT #13, "if (cmem_sp<qbs_cmem_sp) error(257);"
                                    PRINT #13, "}"
                                    e$ = "(uint16)(((uint8*)&(*" + v$ + "=" + e$ + "))-((uint8*)dblock))"
                                END IF

                            END IF

                            PRINT #12, "call_absolute_offsets[" + str2$(argn) + "]=" + e$ + ";"
                        ELSE
                            IF e$ = "" THEN e$ = e2$ ELSE e$ = e$ + sp + e2$
                            e$ = fixoperationorder(e$)
                            l$ = l$ + tlayout$ + sp2 + ")"
                            e$ = evaluatetotyp(e$, UINTEGERTYPE - ISPOINTER)
                            PRINT #12, "call_absolute(" + str2$(argn) + "," + e$ + ");"
                        END IF
                        argn = argn + 1
                        e$ = ""
                    ELSE
                        IF e$ = "" THEN e$ = e2$ ELSE e$ = e$ + sp + e2$
                    END IF
                NEXT
                layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
                GOTO finishedline
            END IF

        ELSE 'n>2

            a$ = n$
            ca$ = cn$
            usecall = 2

        END IF 'n>2

        n = numelements(a$)
        firstelement$ = getelement$(a$, 1)

        'valid SUB name
        validsub = 0
        findidsecondarg = "": IF n >= 2 THEN findidsecondarg = getelement$(a$, 2)
        try = findid(firstelement$)
        DO WHILE try
            IF id.subfunc = 2 THEN validsub = 1: EXIT DO
            IF try = 2 THEN
                findidsecondarg = "": IF n >= 2 THEN findidsecondarg = getelement$(a$, 2)
                findanotherid = 1
                try = findid(firstelement$)
            ELSE
                try = 0
            END IF
        LOOP
        IF validsub = 0 THEN a$ = "Expected CALL sub-name [(...)]": GOTO errmes
    END IF

    'sub?
    IF n >= 1 THEN

        IF firstelement$ = "?" THEN firstelement$ = "PRINT"

        findidsecondarg = "": IF n >= 2 THEN findidsecondarg = getelement$(a$, 2)

        try = findid(firstelement$)
        DO WHILE try
            IF id.subfunc = 2 THEN

IF firstelement$ = "OPEN" then
			'gwbasic or qbasic version?
			b=0
                        FOR x = 2 TO n
                            a2$ = getelement$(a$, x)
                            IF a2$ = "(" THEN b = b + 1
                            IF a2$ = ")" THEN b = b - 1
			    if a2$="FOR" or a2$="AS" then exit for 'qb style open verified
                            IF b = 0 and a2$="," THEN 'the gwbasic version includes a comma after the first string expression
				findanotherid = 1
				try = findid(firstelement$) 'id of sub_open_gwbasic
				exit for
                            END IF
			next
end if


                'IF findid(firstelement$) THEN
                'IF id.subfunc = 2 THEN


                IF firstelement$ = "CLOSE" OR firstelement$ = "RESET" THEN
                    IF firstelement$ = "RESET" THEN
                        IF n > 1 THEN a$ = "Syntax error": GOTO errmes
                    END IF
                    l$ = firstelement$
                    IF n = 1 THEN
                        PRINT #12, "sub_close(NULL,0);" 'closes all files
                    ELSE
                        l$ = l$ + sp
                        b = 0
                        s = 0
                        a3$ = ""
                        FOR x = 2 TO n
                            a2$ = getelement$(ca$, x)
                            IF a2$ = "(" THEN b = b + 1
                            IF a2$ = ")" THEN b = b - 1
                            IF a2$ = "#" AND b = 0 THEN
                                IF s = 0 THEN s = 1 ELSE x = 37: GOTO errnum
                                l$ = l$ + "#" + sp2
                                GOTO closenexta
                            END IF

                            IF a2$ = "," AND b = 0 THEN
                                IF s = 2 THEN
                                    e$ = fixoperationorder$(a3$)
                                    l$ = l$ + tlayout$ + sp2 + "," + sp
                                    e$ = evaluatetotyp(e$, 64&)
                                    PRINT #12, "sub_close(" + e$ + ",1);"
                                    a3$ = ""
                                    s = 0
                                    GOTO closenexta
                                ELSE
                                    x = 38: GOTO errnum
                                END IF
                            END IF

                            s = 2
                            IF a3$ = "" THEN a3$ = a2$ ELSE a3$ = a3$ + sp + a2$

                            closenexta:
                        NEXT

                        IF s = 2 THEN
                            e$ = fixoperationorder$(a3$)
                            l$ = l$ + tlayout$
                            e$ = evaluatetotyp(e$, 64&)
                            PRINT #12, "sub_close(" + e$ + ",1);"
                        ELSE
                            l$ = LEFT$(l$, LEN(l$) - 1)
                        END IF

                    END IF
                    layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
                    GOTO finishedline
                END IF 'close
















                'data, restore, read
                IF firstelement$ = "READ" THEN 'file input
                    xread ca$, n
                    'note: layout done in xread sub
                    GOTO finishedline
                END IF 'read





































                lineinput = 0
                IF n >= 2 THEN
                    IF firstelement$ = "LINE" AND secondelement$ = "INPUT" THEN
                        lineinput = 1
                        a$ = RIGHT$(a$, LEN(a$) - 5): ca$ = RIGHT$(ca$, LEN(ca$) - 5): n = n - 1 'remove "LINE"
                        firstelement$ = "INPUT"
                    END IF
                END IF

                IF firstelement$ = "INPUT" THEN 'file input
                    IF n > 1 THEN
                        IF getelement$(a$, 2) = "#" THEN
                            l$ = "INPUT" + sp + "#": IF lineinput THEN l$ = "LINE" + sp + l$

                            u$ = str2$(uniquenumber)
                            'which file?
                            IF n = 2 THEN x = 43: GOTO errnum
                            a3$ = ""
                            b = 0
                            FOR i = 3 TO n
                                a2$ = getelement$(ca$, i)
                                IF a2$ = "(" THEN b = b + 1
                                IF a2$ = ")" THEN b = b - 1
                                IF a2$ = "," AND b = 0 THEN
                                    IF a3$ = "" THEN x = 44: GOTO errnum
                                    GOTO inputgotfn
                                END IF
                                IF a3$ = "" THEN a3$ = a2$ ELSE a3$ = a3$ + sp + a2$
                            NEXT
                            inputgotfn:
                            e$ = fixoperationorder$(a3$)
                            l$ = l$ + sp2 + tlayout$
                            e$ = evaluatetotyp(e$, 64&)
                            PRINT #12, "tmp_fileno=" + e$ + ";"
                            PRINT #12, "if (new_error) goto skip" + u$ + ";"
                            i = i + 1
                            IF i > n THEN x = 45: GOTO errnum
                            a3$ = ""
                            b = 0
                            FOR i = i TO n
                                a2$ = getelement$(ca$, i)
                                IF a2$ = "(" THEN b = b + 1
                                IF a2$ = ")" THEN b = b - 1
                                IF i = n THEN
                                    IF a3$ = "" THEN a3$ = a2$ ELSE a3$ = a3$ + sp + a2$
                                    a2$ = ",": b = 0
                                END IF
                                IF a2$ = "," AND b = 0 THEN
                                    IF a3$ = "" THEN x = 46: GOTO errnum
                                    e$ = fixoperationorder$(a3$)
                                    l$ = l$ + sp2 + "," + sp + tlayout$
                                    e$ = evaluate(e$, t)
                                    IF (t AND ISREFERENCE) = 0 THEN x = 47: GOTO errnum
                                    IF (t AND ISSTRING) THEN
                                        e$ = refer(e$, t, 0)
                                        IF lineinput THEN
                                            PRINT #12, "sub_file_line_input_string(tmp_fileno," + e$ + ");"
                                            PRINT #12, "if (new_error) goto skip" + u$ + ";"
                                        ELSE
                                            PRINT #12, "sub_file_input_string(tmp_fileno," + e$ + ");"
                                            PRINT #12, "if (new_error) goto skip" + u$ + ";"
                                        END IF
                                        stringprocessinghappened = 1
                                    ELSE
                                        IF lineinput THEN a$ = "Expected string-variable": GOTO errmes
                                        'not a string!
                                        'e$ = refer(e$, t, 1)
                                        '***INPORTANT NOTE: Modify t for non-0 bit offsets found in UDTs & arrays too
                                        t2 = t
                                        IF (t2 AND ISPOINTER) THEN t2 = t2 - ISPOINTER
                                        IF (t2 AND ISINCONVENTIONALMEMORY) THEN t2 = t2 - ISINCONVENTIONALMEMORY
                                        IF (t2 AND ISREFERENCE) THEN t2 = t2 - ISREFERENCE
                                        'PRINT #12, "sub_file_input_value(tmp_long," + str2(t) + "," + e$ + ");"
                                        IF (t AND 511) = 64 THEN
                                            IF (t AND ISUNSIGNED) THEN
                                                setrefer e$, t, "func_file_input_uint64(tmp_fileno)", 1
                                            ELSE
                                                setrefer e$, t, "func_file_input_int64(tmp_fileno)", 1
                                            END IF
                                        ELSE
                                            setrefer e$, t, "func_file_input_float(tmp_fileno," + str2(t) + ")", 1
                                        END IF
                                        PRINT #12, "if (new_error) goto skip" + u$ + ";"
                                    END IF
                                    IF i = n THEN EXIT FOR
                                    IF lineinput THEN a$ = "Too many variables": GOTO errmes
                                    a3$ = "": a2$ = ""
                                END IF
                                IF a3$ = "" THEN a3$ = a2$ ELSE a3$ = a3$ + sp + a2$
                            NEXT
                            PRINT #12, "skip" + u$ + ":"
                            PRINT #12, "revert_input_check();"
                            IF stringprocessinghappened THEN PRINT #12, cleanupstringprocessingcall$ + "0);"
                            layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
                            GOTO finishedline
                        END IF
                    END IF
                END IF 'input#


                IF firstelement$ = "INPUT" THEN
                    l$ = "INPUT": IF lineinput THEN l$ = "LINE" + sp + l$
                    commaneeded = 0
                    i = 2

                    newline = 1: IF getelement$(a$, i) = ";" THEN newline = 0: i = i + 1: l$ = l$ + sp + ";"

                    a2$ = getelement$(ca$, i)
                    IF LEFT$(a2$, 1) = CHR$(34) THEN
                        e$ = fixoperationorder$(a2$): l$ = l$ + sp + tlayout$
                        PRINT #12, "qbs_print(qbs_new_txt_len(" + a2$ + "),0);"
                        i = i + 1
                        'MUST be followed by a ; or ,
                        a2$ = getelement$(ca$, i)
                        i = i + 1
                        l$ = l$ + sp2 + a2$
                        IF a2$ = ";" THEN
                            IF lineinput THEN GOTO finishedpromptstring
                            PRINT #12, "qbs_print(qbs_new_txt(" + CHR$(34) + "? " + CHR$(34) + "),0);"
                            GOTO finishedpromptstring
                        END IF
                        IF a2$ = "," THEN
                            GOTO finishedpromptstring
                        END IF
                        x = 48: GOTO errnum
                    END IF
                    'there was no promptstring, so print a ?
                    PRINT #12, "qbs_print(qbs_new_txt(" + CHR$(34) + "? " + CHR$(34) + "),0);"
                    finishedpromptstring:
                    numvar = 0
                    FOR i = i TO n
                        IF commaneeded = 1 THEN
                            a2$ = getelement$(ca$, i)
                            IF a2$ <> "," THEN x = 49: GOTO errnum
                        ELSE

                            b = 0
                            e$ = ""
                            FOR i2 = i TO n
                                e2$ = getelement$(ca$, i2)
                                IF e2$ = "(" THEN b = b + 1
                                IF e2$ = ")" THEN b = b - 1
                                IF e2$ = "," AND b = 0 THEN i2 = i2 - 1: EXIT FOR
                                e$ = e$ + sp + e2$
                            NEXT
                            i = i2: IF i > n THEN i = n
                            IF e$ = "" THEN a$ = "Expected variable": GOTO errmes
                            e$ = RIGHT$(e$, LEN(e$) - 1)
                            e$ = fixoperationorder$(e$)
                            l$ = l$ + sp + tlayout$: IF i <> n THEN l$ = l$ + sp2 + ","
                            e$ = evaluate(e$, t)
                            IF (t AND ISREFERENCE) = 0 THEN a$ = "Expected variable": GOTO errmes

                            IF (t AND ISSTRING) THEN
                                e$ = refer(e$, t, 0)
                                numvar = numvar + 1
                                IF lineinput THEN
                                    PRINT #12, "qbs_input_variabletypes[" + str2(numvar) + "]=ISSTRING+512;"
                                ELSE
                                    PRINT #12, "qbs_input_variabletypes[" + str2(numvar) + "]=ISSTRING;"
                                END IF
                                PRINT #12, "qbs_input_variableoffsets[" + str2(numvar) + "]=" + e$ + ";"
                                GOTO gotinputvar
                            END IF

                            IF lineinput THEN a$ = "Expected string variable": GOTO errmes
                            IF (t AND ISARRAY) THEN
                                IF (t AND ISOFFSETINBITS) THEN
                                    a$ = "INPUT cannot handle BIT array elements yet": GOTO errmes
                                END IF
                            END IF
                            e$ = "&(" + refer(e$, t, 0) + ")"

                            'remove assumed/unnecessary flags
                            IF (t AND ISPOINTER) THEN t = t - ISPOINTER
                            IF (t AND ISINCONVENTIONALMEMORY) THEN t = t - ISINCONVENTIONALMEMORY
                            IF (t AND ISREFERENCE) THEN t = t - ISREFERENCE

                            'IF (t AND ISOFFSETINBITS) THEN
                            'numvar = numvar + 1
                            'consider storing the bit offset in unused bits of t
                            'PRINT #12, "qbs_input_variabletypes[" + str2(numvar) + "]=" + str2(t) + ";"
                            'PRINT #12, "qbs_input_variableoffsets[" + str2(numvar) + "]=" + refer(ref$, typ, 1) + ";"
                            'GOTO gotinputvar
                            'END IF

                            'assume it is a regular variable
                            numvar = numvar + 1
                            PRINT #12, "qbs_input_variabletypes[" + str2(numvar) + "]=" + str2$(t) + ";"
                            PRINT #12, "qbs_input_variableoffsets[" + str2(numvar) + "]=" + e$ + ";"
                            GOTO gotinputvar

                        END IF
                        gotinputvar:
                        commaneeded = commaneeded + 1: IF commaneeded = 2 THEN commaneeded = 0
                    NEXT
                    IF numvar = 0 THEN x = 51: GOTO errnum
                    IF lineinput = 1 AND numvar > 1 THEN a$ = "Too many variables": GOTO errmes
                    PRINT #12, "qbs_input(" + str2(numvar) + "," + str2$(newline) + ");"
                    PRINT #12, "if (stop_program) end();"
                    PRINT #12, cleanupstringprocessingcall$ + "0);"
                    layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
                    GOTO finishedline
                END IF



                IF firstelement$ = "WRITE" THEN 'file write
                    IF n > 1 THEN
                        IF getelement$(a$, 2) = "#" THEN
                            xfilewrite ca$, n
                            GOTO finishedline
                        END IF '#
                    END IF 'n>1
                END IF '"write"

                IF firstelement$ = "WRITE" THEN 'write
                    xwrite ca$, n
                    GOTO finishedline
                END IF '"write"

                IF firstelement$ = "PRINT" THEN 'file print
                    IF n > 1 THEN
                        IF getelement$(a$, 2) = "#" THEN
                            xfileprint a$, ca$, n
                            l$ = tlayout$
                            layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
                            GOTO finishedline
                        END IF '#
                    END IF 'n>1
                END IF '"print"

                IF firstelement$ = "PRINT" or firstelement$ = "LPRINT" THEN
                    xprint a$, ca$, n
                    l$ = tlayout$
                    layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
                    GOTO finishedline
                END IF

                IF firstelement$ = "CLEAR" THEN
                    IF subfunc$ <> "" THEN a$ = "CLEAR cannot be used inside a SUB/FUNCTION": GOTO errmes
                END IF

                'any other "unique" subs can be processed above

                id2 = id

                targetid = currentid

if n>1 then
if id2.args=0 then a$ = "SUB does not require any arguments": GOTO errmes
end if

                passedneeded = seperateargs(getelements(a$, 2, n), getelements(ca$, 2, n), passed&)

                'backup args to local string array space before calling evaluate
                FOR i = 1 TO 60: separgs2(i) = "": NEXT 'save space!
                FOR i = 1 TO 61: separgslayout2(i) = "": NEXT
                FOR i = 1 TO id2.args: separgs2(i) = separgs(i): NEXT
                FOR i = 1 TO id2.args + 1: separgslayout2(i) = separgslayout(i): NEXT

                'note: seperateargs finds the arguments to pass and sets passed& as necessary
                '      FIXOPERTIONORDER is not called on these args yet
                '      what we need it to do is build a second array of layout info at the same time
                '   ref:DIM SHARED separgslayout(100) AS STRING
                '   the above array stores what layout info (if any) goes BEFORE the arg in question
                '       it has one extra index which is the arg after

                IF usecall THEN
                    IF usecall = 1 THEN l$ = "CALL" + sp + RTRIM$(id.cn) + RTRIM$(id.musthave) + sp2 + "(" + sp2
                    IF usecall = 2 THEN l$ = "CALL" + sp + RTRIM$(id.cn) + RTRIM$(id.musthave) + sp 'sp at end for easy parsing
                ELSE
                    l$ = RTRIM$(id.cn) + RTRIM$(id.musthave) + sp
                END IF

                subcall$ = RTRIM$(id.callname) + "("
                addedlayout = 0

fieldcall=0
'GET/PUT field exception
if rtrim$(id2.callname) = "sub_get" or rtrim$(id2.callname) = "sub_put" then
if passed and 2 then
'regular GET/PUT call with variable provided
passed=passed-2 'for complience with existing methods, remove 'passed' flag for the passing of a variable
else
'FIELD GET/PUT call with variable omited
if rtrim$(id2.callname) = "sub_get" then
fieldcall=1
subcall$="field_get("
else
fieldcall=2
subcall$="field_put("
end if
end if
end if 'field exception

if rtrim$(id2.callname) = "sub_timer" then 'spacing exception
if usecall=0 then
l$=left$(l$,len(l$)-1)+sp2
end if
end if

                FOR i = 1 TO id2.args
                    targettyp = CVL(MID$(id2.arg, -3 + i * 4, 4))
                    nele = ASC(MID$(id2.nele, i, 1))
                    nelereq = ASC(MID$(id2.nelereq, i, 1))

                    addlayout = 1 'omits option values in layout (eg. BINARY="2")
                    convertspacing = 0 'if an 'equation' is next, it will be preceeded by a space
                    x$ = separgslayout2$(i)
                    DO WHILE LEN(x$)
                        x = ASC(x$)
                        IF x THEN
                            convertspacing = 0
                            x2$ = MID$(x$, 2, x)
                            x$ = RIGHT$(x$, LEN(x$) - x - 1)

                            s = 0
                            an = 0
                            x3$ = RIGHT$(l$, 1)
                            IF x3$ = sp THEN s = 1
                            IF x3$ = sp2 THEN
                                s = 2
                                IF alphanumeric(ASC(RIGHT$(l$, 2))) THEN an = 1
                            ELSE
                                IF alphanumeric(ASC(x3$)) THEN an = 1
                            END IF
                            s1 = s

                            IF alphanumeric(ASC(x2$)) THEN convertspacing = 1

                            IF (an = 1 OR addedlayout = 1) AND alphanumeric(ASC(x2$)) <> 0 THEN
                                s = 1 'force space
                                x2$ = x2$ + sp2
                                GOTO customlaychar
                            END IF

                            IF x2$ = "=" THEN
                                s = 1
                                x2$ = x2$ + sp
                                GOTO customlaychar
                            END IF

                            IF x2$ = "#" THEN
                                s = 1
                                x2$ = x2$ + sp2
                                GOTO customlaychar
                            END IF

                            IF x2$ = "," THEN x2$ = x2$ + sp: GOTO customlaychar

                            'default solution sp2+?+sp2
                            x2$ = x2$ + sp2
                            customlaychar:
                            IF s = 0 THEN s = 2
                            IF s <> s1 THEN
                                IF s1 THEN l$ = LEFT$(l$, LEN(l$) - 1)
                                IF s = 1 THEN l$ = l$ + sp
                                IF s = 2 THEN l$ = l$ + sp2
                            END IF

if rtrim$(id2.callname) = "sub_timer" and i=id2.args then 'spacing exception
if x2$<>")"+sp2 then
l$=left$(l$,len(l$)-1)+sp
end if
end if

                            l$ = l$ + x2$
                        ELSE
                            addlayout = 0
                            x$ = RIGHT$(x$, LEN(x$) - 1)
                        END IF
                        addedlayout = 0
                    LOOP

                    addedlayout = 0





                    IF targettyp = -3 THEN
                        IF separgs2(i) = "NULL" THEN x = 56: GOTO errnum
                        'names of numeric arrays have ( ) automatically appended (nothing else)
                        e$ = separgs2(i)
                        IF INSTR(e$, sp) = 0 THEN 'one element only
                            try = findid(e$)
                            DO WHILE try
                                IF id.arraytype THEN
                                    IF (id.arraytype AND ISSTRING) = 0 THEN
                                        e$ = e$ + sp + "(" + sp + ")"
                                        EXIT DO
                                    END IF
                                END IF
                                IF try = 2 THEN findanotherid = 1: try = findid(e$) ELSE try = 0
                            LOOP
                        END IF
                        e$ = fixoperationorder$(e$)
                        IF convertspacing = 1 AND addlayout = 1 THEN l$ = LEFT$(l$, LEN(l$) - 1) + sp
                        IF addlayout THEN l$ = l$ + tlayout$: addedlayout = 1
                        e$ = evaluatetotyp(e$, -2)
                        GOTO sete
                    END IF '-3

                    IF targettyp = -2 THEN
                        e$ = fixoperationorder$(e$)
                        IF convertspacing = 1 AND addlayout = 1 THEN l$ = LEFT$(l$, LEN(l$) - 1) + sp
                        IF addlayout THEN l$ = l$ + tlayout$: addedlayout = 1
                        e$ = evaluatetotyp(e$, -2)
                        GOTO sete
                    END IF '-2

                    IF targettyp = -4 THEN

if fieldcall then
i=id2.args+1
exit for
end if

                        IF separgs2(i) = "NULL" THEN x = 61: GOTO errnum
                        e$ = fixoperationorder$(separgs2(i))
                        IF convertspacing = 1 AND addlayout = 1 THEN l$ = LEFT$(l$, LEN(l$) - 1) + sp
                        IF addlayout THEN l$ = l$ + tlayout$: addedlayout = 1

                        'GET/PUT RANDOM-ACCESS override
                        IF firstelement$ = "GET" OR firstelement$ = "PUT" THEN
                            e2$ = e$ 'backup
                            e$ = evaluate(e$, sourcetyp)
                            IF (sourcetyp AND ISSTRING) THEN
                                IF (sourcetyp AND ISFIXEDLENGTH) = 0 THEN
                                    'replace name of sub to call
                                    subcall$ = RIGHT$(subcall$, LEN(subcall$) - 7) 'delete original name
                                    'note: GET2 & PUT2 take differing input, following code is correct
                                    IF firstelement$ = "GET" THEN
                                        subcall$ = "sub_get2" + subcall$
                                        e$ = refer(e$, sourcetyp, 0) 'pass a qbs pointer instead
                                        GOTO sete
                                    ELSE
                                        subcall$ = "sub_put2" + subcall$
                                        'no goto sete required, fall through
                                    END IF
                                END IF
                            END IF
                            e$ = e2$ 'restore
                        END IF 'override

                        e$ = evaluatetotyp(e$, -4)
                        GOTO sete
                    END IF '-4

                    IF separgs2(i) = "NULL" THEN
                        e$ = "NULL"
                    ELSE

                        e2$ = fixoperationorder$(separgs2(i))
                        IF convertspacing = 1 AND addlayout = 1 THEN l$ = LEFT$(l$, LEN(l$) - 1) + sp
                        IF addlayout THEN l$ = l$ + tlayout$: addedlayout = 1
                        e$ = evaluate(e2$, sourcetyp)

                        IF RTRIM$(id2.callname) = "sub_paint" THEN
                            IF i = 4 THEN
                                IF (sourcetyp AND ISSTRING) THEN
                                    targettyp = ISSTRING
                                END IF
                            END IF
                        END IF

                        'pass by reference
                        IF (targettyp AND ISPOINTER) THEN
                            IF LEFT$(separgs2(i), 2) <> "(" + sp THEN 'check for '(' dereference


                                IF (targettyp AND ISARRAY) THEN
                                    IF (sourcetyp AND ISREFERENCE) = 0 THEN a$ = "Expected arrayname()": GOTO errmes

                                    idnum = VAL(LEFT$(e$, INSTR(e$, "³") - 1))
                                    getid idnum

                                    IF MID$(sfcmemargs(targetid), i, 1) = CHR$(1) THEN 'cmem required?
                                        IF cmemlist(idnum) = 0 THEN
                                            cmemlist(idnum) = 1
                                            recompile = 1
                                        END IF
                                    END IF

                                    'following check failed...
                                    IF (sourcetyp AND ISARRAY) = 0 THEN a$ = "Expected arrayname()": GOTO errmes

                                    IF sourcetyp AND ISUDT THEN
                                        'check u or e
                                    ELSE
                                        IF RIGHT$(e$, 2) <> "³0" THEN a$ = "Expected arrayname()": GOTO errmes
                                    END IF

                                    'check array is of same TYPE!

                                    targettypsize = CVL(MID$(id2.argsize, i * 4 - 4 + 1, 4))
                                    'targettypsize is ignored! but would be used for type checking fixed length string arrays


                                    IF id.linkid = 0 THEN
                                        'if id.linkid is 0, it means the number of array elements is definietly
                                        'known of the array being passed, this is not some "fake"/unknown array.
                                        'using the numer of array elements of a fake array would be dangerous!


                                        IF nelereq = 0 THEN
                                            'only continue if the number of array elements required is unknown
                                            'and it needs to be set

                                            IF id.arrayelements > 0 THEN '2009

                                                nelereq = id.arrayelements
                                                MID$(id2.nelereq, i, 1) = CHR$(nelereq)

                                            END IF

                                            'print rtrim$(id2.n)+">nelereq=";nelereq

                                            ids(targetid) = id2

                                        ELSE

                                            'the number of array elements required is known AND
                                            'the number of elements in the array to be passed is known

                                            IF id.arrayelements <> nelereq THEN a$ = "Passing arrays with a differing number of elements to a SUB/FUNCTION is not supported (yet)": GOTO errmes


                                        END IF
                                    END IF

                                    e$ = refer(e$, sourcetyp, 1)
                                    GOTO sete

                                END IF 'target is an array
                                'target is not an array

                                IF (targettyp AND ISSTRING) = 0 THEN 'not a string
                                    IF (sourcetyp AND ISREFERENCE) THEN
                                        idnum = VAL(LEFT$(e$, INSTR(e$, "³") - 1)) 'id# of sourcetyp

                                        'check to see if given reference is of the correct type
                                        'compare the source and dest. types
                                        'print targettyp , sourcetyp
                                        'print targettyp and 511, sourcetyp and 511
                                        'print targettyp and ISPOINTER, sourcetyp and ISPOINTER
                                        'print targettyp and ISUDT, sourcetyp and ISUDT
                                        'print targettyp and ISARRAY, sourcetyp and ISARRAY
                                        'print targettyp and ISREFERENCE, sourcetyp and ISREFERENCE
                                        targettyp2 = targettyp: sourcetyp2 = sourcetyp - ISREFERENCE
                                        IF (sourcetyp2 AND ISARRAY) THEN
                                            arr = 1: sourcetyp2 = sourcetyp2 - ISARRAY
                                        ELSE
                                            arr = 0
                                        END IF
                                        IF (sourcetyp2 AND ISPOINTER) = 0 THEN sourcetyp2 = sourcetyp2 + ISPOINTER
                                        IF (sourcetyp2 AND ISINCONVENTIONALMEMORY) THEN sourcetyp2 = sourcetyp2 - ISINCONVENTIONALMEMORY

'make signed/unsigned irrelavent
if targettyp2 and ISUNSIGNED then
if (sourcetyp2 and ISUNSIGNED)=0 then sourcetyp2=sourcetyp2+ISUNSIGNED
end if

'allow passinf of UDT element variable as normal variable
passudtelement=0
if (targettyp2 and ISUDT)=0 then
if sourcetyp2 and ISUDT then sourcetyp2=sourcetyp2-ISUDT: passudtelement=1
end if

                                        IF sourcetyp2 = targettyp2 THEN
                                            'print "Similar!"
                                            IF sourcetyp AND ISUDT THEN
                                                'udt/udt array

                                                getid VAL(e$)
                                                udtrefi = INSTR(e$, "³") 'skip id
                                                udtrefi = INSTR(udtrefi + 1, e$, "³") 'skip u
                                                udtrefi = INSTR(udtrefi + 1, e$, "³") 'skip e
                                                o$ = RIGHT$(e$, LEN(e$) - udtrefi) 'set o$ to the offset
                                                IF arr THEN
                                                    n$ = scope$ + "ARRAY_UDT_" + RTRIM$(id.n) + "[0]"
                                                ELSE
                                                    n$ = scope$ + "UDT_" + RTRIM$(id.n)
                                                END IF

                                                e$ = "(void*)( ((char*)(" + n$ + ")) + (" + RIGHT$(e$, LEN(e$) - udtrefi) + ") )"
                                                
'convert void* to target type*
if passudtelement then e$="("+typ2ctyp$(targettyp2-ISPOINTER,"")+"*)"+e$

                                                'print "passing:"+e$

                                            ELSE
                                                'not a udt
                                                IF arr THEN
                                                    IF (sourcetyp2 AND ISOFFSETINBITS) THEN a$ = "Cannot pass BIT array offsets yet": GOTO errmes
                                                    e$ = "(&(" + refer(e$, sourcetyp, 0) + "))"
                                                ELSE
                                                    e$ = refer(e$, sourcetyp, 1)
                                                END IF

                                            END IF

                                            IF MID$(sfcmemargs(targetid), i, 1) = CHR$(1) THEN 'cmem required?
                                                IF cmemlist(idnum) = 0 THEN
                                                    cmemlist(idnum) = 1
                                                    recompile = 1
                                                END IF
                                            END IF

                                            GOTO sete
                                        END IF 'similar
                                    END IF 'reference
else 'not a string
'its a string
IF (sourcetyp AND ISREFERENCE) THEN
idnum = VAL(LEFT$(e$, INSTR(e$, "³") - 1)) 'id# of sourcetyp
                                            IF MID$(sfcmemargs(targetid), i, 1) = CHR$(1) THEN 'cmem required?
                                                IF cmemlist(idnum) = 0 THEN
                                                    cmemlist(idnum) = 1
                                                    recompile = 1
                                                END IF
                                            END IF
END IF 'reference
END IF 'its a string

                            END IF 'dereference check
                        END IF 'target is a pointer

                        IF (sourcetyp AND ISREFERENCE) THEN
                            e$ = refer(e$, sourcetyp, 0)
                        END IF

                        'round to integer if required
                        IF (sourcetyp AND ISFLOAT) THEN
                            IF (targettyp AND ISFLOAT) = 0 THEN
                                '**32 rounding fix
                                bits = targettyp AND 511
                                IF bits <= 16 THEN e$ = "qbr_float_to_long(" + e$ + ")"
                                IF bits > 16 AND bits < 32 THEN e$ = "qbr_double_to_long(" + e$ + ")"
                                IF bits >= 32 THEN e$ = "qbr(" + e$ + ")"
                            END IF
                        END IF

                        IF (targettyp AND ISPOINTER) THEN 'pointer required
                            IF (targettyp AND ISSTRING) THEN GOTO sete 'no changes required
                            t$ = typ2ctyp$(targettyp, "")
                            v$ = "pass" + str2$(uniquenumber)
                            'assume numeric type
                            IF MID$(sfcmemargs(targetid), i, 1) = CHR$(1) THEN 'cmem required?
                                bytesreq = ((targettyp AND 511) + 7) \ 8
                                PRINT #defdatahandle, t$ + " *" + v$ + "=NULL;"
                                PRINT #13, "if(" + v$ + "==NULL){"
                                PRINT #13, "cmem_sp-=" + str2(bytesreq) + ";"
                                PRINT #13, v$ + "=(" + t$ + "*)(dblock+cmem_sp);"
                                PRINT #13, "if (cmem_sp<qbs_cmem_sp) error(257);"
                                PRINT #13, "}"
                                e$ = "&(*" + v$ + "=" + e$ + ")"
                            ELSE
                                PRINT #13, t$ + " " + v$ + ";"
                                e$ = "&(" + v$ + "=" + e$ + ")"
                            END IF
                            GOTO sete
                        END IF

                    END IF 'not "NULL"

                    sete:

                    IF RTRIM$(id2.callname) = "sub_paint" THEN
                        IF i = 4 THEN
                            IF (sourcetyp AND ISSTRING) THEN
                                e$ = "(qbs*)" + e$
                            ELSE
                                e$ = "(uint32)" + e$
                            END IF
                        END IF
                    END IF

if id2.ccall then

if targettyp AND ISSTRING then
e$="(char*)("+e$+")->chr"
end if

if ltrim$(rtrim$(e$))="0" then e$="NULL"

end if

                    IF i <> 1 THEN subcall$ = subcall$ + ","
                    subcall$ = subcall$ + e$
                NEXT

                'note: i=id.args+1
                x$ = separgslayout2$(i)
                DO WHILE LEN(x$)
                    x = ASC(x$)
                    IF x THEN
                        x2$ = MID$(x$, 2, x)
                        x$ = RIGHT$(x$, LEN(x$) - x - 1)

                        s = 0
                        an = 0
                        x3$ = RIGHT$(l$, 1)
                        IF x3$ = sp THEN s = 1
                        IF x3$ = sp2 THEN
                            s = 2
                            IF alphanumeric(ASC(RIGHT$(l$, 2))) THEN an = 1
                            'if asc(right$(l$,2))=34 then an=1
                        ELSE
                            IF alphanumeric(ASC(x3$)) THEN an = 1
                            'if asc(x3$)=34 then an=1
                        END IF
                        s1 = s

                        IF (an = 1 OR addedlayout = 1) AND alphanumeric(ASC(x2$)) <> 0 THEN
                            s = 1 'force space
                            x2$ = x2$ + sp2
                            GOTO customlaychar2
                        END IF

                        IF x2$ = "=" THEN
                            s = 1
                            x2$ = x2$ + sp
                            GOTO customlaychar2
                        END IF

                        IF x2$ = "#" THEN
                            s = 1
                            x2$ = x2$ + sp2
                            GOTO customlaychar2
                        END IF

                        IF x2$ = "," THEN x2$ = x2$ + sp: GOTO customlaychar2

                        'default solution sp2+?+sp2
                        x2$ = x2$ + sp2
                        customlaychar2:
                        IF s = 0 THEN s = 2
                        IF s <> s1 THEN
                            IF s1 THEN l$ = LEFT$(l$, LEN(l$) - 1)
                            IF s = 1 THEN l$ = l$ + sp
                            IF s = 2 THEN l$ = l$ + sp2
                        END IF
                        l$ = l$ + x2$

                    ELSE
                        addlayout = 0
                        x$ = RIGHT$(x$, LEN(x$) - 1)
                    END IF
                    addedlayout = 0
                LOOP






                IF passedneeded THEN
                    subcall$ = subcall$ + "," + str2$(passed&)
                END IF
                subcall$ = subcall$ + ");"
                PRINT #12, subcall$
                subcall$ = ""
                IF stringprocessinghappened THEN PRINT #12, cleanupstringprocessingcall$ + "0);"

                layoutdone = 1
                x$ = RIGHT$(l$, 1): IF x$ = sp OR x$ = sp2 THEN l$ = LEFT$(l$, LEN(l$) - 1)
                IF usecall = 1 THEN l$ = l$ + sp2 + ")"
                IF debug THEN PRINT #9, "SUB layout:[" + l$ + "]"
                IF LEN(layout$) = 0 THEN layout$ = l$ ELSE layout$ = layout$ + sp + l$
                GOTO finishedline


            END IF

            IF try = 2 THEN
                findidsecondarg = "": IF n >= 2 THEN findidsecondarg = getelement$(a$, 2)
                findanotherid = 1
                try = findid(firstelement$)
            ELSE
                try = 0
            END IF
        LOOP

    END IF




    IF n = 1 THEN
        IF firstelement$ = "END" THEN
            xend
            l$ = "END"
            layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
            GOTO finishedline
        END IF
    END IF

    IF n = 1 THEN
        IF firstelement$ = "SYSTEM" THEN
            PRINT #12, "close_program=1;"
            PRINT #12, "end();"
            l$ = "SYSTEM"
            layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
            GOTO finishedline
        END IF
    END IF

    IF n >= 1 THEN
        IF firstelement$ = "STOP" THEN
            l$ = "STOP"
            IF n > 1 THEN
                e$ = getelements$(ca$, 2, n)
                e$ = fixoperationorder$(e$)
                l$ = "STOP" + sp + tlayout$
                e$ = evaluatetotyp(e$, 64)
                'note: this value is currently ignored but evaluated for checking reasons
            END IF
            layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
            PRINT #12, "close_program=1;"
            PRINT #12, "end();"
            GOTO finishedline
        END IF
    END IF

    IF n = 2 THEN
        IF firstelement$ = "GOSUB" THEN
            xgosub ca$, n
            'note: layout implemented in xgosub
            GOTO finishedline
        END IF
    END IF

    IF n >= 1 THEN
        IF firstelement$ = "RETURN" THEN
            IF n = 1 THEN
                PRINT #12, "#include " + CHR$(34) + "ret" + str2$(subfuncn) + ".txt" + CHR$(34)
                l$ = "RETURN"
                layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
                GOTO finishedline
            ELSE
                'label/linenumber follows
                IF subfuncn <> 0 THEN a$ = "RETURN linelabel/linenumber invalid within a SUB/FUNCTION": GOTO errmes
                IF n > 2 THEN a$ = "Expected linelabel/linenumber after RETURN": GOTO errmes
                PRINT #12, "if (!next_return_point) error(3);" 'check return point available
                PRINT #12, "next_return_point--;" 'destroy return point
                a2$ = getelement$(ca$, 2)
                IF validlabel(a2$) = 0 THEN x = 36: GOTO errnum

v=HashFind(a2$,HASHFLAG_LABEL,ignore,r)
x=1
labchk505: 
if v then
s=labels(r).scope
if s=subfuncn or s=-1 then 'same scope?
if s=-1 then labels(r).scope=subfuncn 'acquire scope
x=0 'already defined
tlayout$=rtrim$(labels(r).cn)
else
if v=2 then v=HashFindCont(ignore,r): goto labchk505
end if
end if
if x then
'does not exist
nLabels=nLabels+1: if nLabels>Labels_Ubound then Labels_Ubound=Labels_Ubound*2: redim _preserve Labels(1 to Labels_Ubound) as Label_Type
Labels(nLabels)=Empty_label
hashadd a2$,HASHFLAG_LABEL,nLabels
r=nLabels
Labels(r).state=0
Labels(r).cn=tlayout$
Labels(r).scope=subfuncn
Labels(r).Error_Line=linenumber
end if 'x

                PRINT #12, "goto LABEL_" + a2$ + ";"
                l$ = "RETURN" + sp + tlayout$
                layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
                GOTO finishedline
            END IF
        END IF
    END IF

    IF n >= 1 THEN
        IF firstelement$ = "RESUME" THEN
            l$ = "RESUME"
            IF n = 1 THEN
                resumeprev:
                PRINT #12, "if (!error_handling){error(20);}else{error_retry=1; qbevent=1; error_handling=0; error_err=0; error_erl=0; return NULL;}"
                layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
                GOTO finishedline
            END IF
            IF n > 2 THEN x = 66: GOTO errnum
            s$ = getelement$(ca$, 2)
            IF UCASE$(s$) = "NEXT" THEN
                PRINT #12, "if (!error_handling){error(20);}else{error_handling=0; error_err=0; error_erl=0; return NULL;}"
                l$ = l$ + sp + "NEXT"
                layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
                GOTO finishedline
            END IF
            IF s$ = "0" THEN l$ = l$ + sp + "0": GOTO resumeprev
            IF validlabel(s$) = 0 THEN x = 67: GOTO errnum

v=HashFind(s$,HASHFLAG_LABEL,ignore,r)
x=1
labchk506: 
if v then
s=labels(r).scope
if s=subfuncn or s=-1 then 'same scope?
if s=-1 then labels(r).scope=subfuncn 'acquire scope
x=0 'already defined
tlayout$=rtrim$(labels(r).cn)
else
if v=2 then v=HashFindCont(ignore,r): goto labchk506
end if
end if
if x then
'does not exist
nLabels=nLabels+1: if nLabels>Labels_Ubound then Labels_Ubound=Labels_Ubound*2: redim _preserve Labels(1 to Labels_Ubound) as Label_Type
Labels(nLabels)=Empty_label
hashadd s$,HASHFLAG_LABEL,nLabels
r=nLabels
Labels(r).state=0
Labels(r).cn=tlayout$
Labels(r).scope=subfuncn
Labels(r).Error_Line=linenumber
end if 'x

            l$ = l$ + sp + tlayout$
            layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
            PRINT #12, "if (!error_handling){error(20);}else{error_handling=0; error_err=0; error_erl=0; goto LABEL_" + s$ + ";}"
            GOTO finishedline
        END IF
    END IF

    IF n = 4 THEN
        IF getelements(a$, 1, 3) = "ON" + sp + "ERROR" + sp + "GOTO" THEN
            l$ = "ON" + sp + "ERROR" + sp + "GOTO"
            lbl$ = getelement$(ca$, 4)
            IF lbl$ = "0" THEN
                PRINT #12, "error_goto_line=0;"
                l$ = l$ + sp + "0"
                layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
                GOTO finishedline
            END IF
            IF validlabel(lbl$) = 0 THEN x = 68: GOTO errnum

v=HashFind(lbl$,HASHFLAG_LABEL,ignore,r)
x=1
labchk6: 
if v then
s=labels(r).scope
if s=0 or s=-1 then 'main scope?
if s=-1 then labels(r).scope=0 'acquire scope
x=0 'already defined
tlayout$=rtrim$(labels(r).cn)
Labels(r).Scope_Restriction=subfuncn
Labels(r).Error_Line=linenumber
else
if v=2 then v=HashFindCont(ignore,r): goto labchk6
end if
end if
if x then
'does not exist
nLabels=nLabels+1: if nLabels>Labels_Ubound then Labels_Ubound=Labels_Ubound*2: redim _preserve Labels(1 to Labels_Ubound) as Label_Type
Labels(nLabels)=Empty_label
hashadd lbl$,HASHFLAG_LABEL,nLabels
r=nLabels
Labels(r).state=0
Labels(r).cn=tlayout$
Labels(r).scope=0
Labels(r).Error_Line=linenumber
Labels(r).Scope_Restriction=subfuncn
end if 'x


            l$ = l$ + sp + tlayout$
            layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
            errorlabels = errorlabels + 1
            PRINT #12, "error_goto_line=" + str2(errorlabels) + ";"
            PRINT #14, "if (error_goto_line==" + str2(errorlabels) + "){error_handling=1; goto LABEL_" + lbl$ + ";}"
            GOTO finishedline
        END IF
    END IF

    IF n >= 1 THEN
        IF firstelement$ = "RESTORE" THEN
            l$ = "RESTORE"
            IF n = 1 THEN
                PRINT #12, "data_offset=0;"
            ELSE
                IF n > 2 THEN x = 69: GOTO errnum
                lbl$ = getelement$(ca$, 2)
                IF validlabel(lbl$) = 0 THEN x = 70: GOTO errnum

'rule: a RESTORE label has no scope, therefore, only one instance of that label may exist
'how: enforced by a post check for duplicates
v=HashFind(lbl$,HASHFLAG_LABEL,ignore,r)
x=1
if v then 'already defined
x=0
tlayout$=rtrim$(labels(r).cn)
labels(r).Data_Referenced=1 'make sure the data referenced flag is set
if Labels(r).Error_Line=0 then Labels(r).Error_Line=linenumber
end if
if x then
nLabels=nLabels+1: if nLabels>Labels_Ubound then Labels_Ubound=Labels_Ubound*2: redim _preserve Labels(1 to Labels_Ubound) as Label_Type
Labels(nLabels)=Empty_label
hashadd lbl$,HASHFLAG_LABEL,nLabels
r=nLabels
Labels(r).state=0
Labels(r).cn=tlayout$
Labels(r).scope=-1 'modifyable scope
Labels(r).Error_Line=linenumber
labels(r).Data_Referenced=1
end if 'x

                l$ = l$ + sp + tlayout$
                PRINT #12, "data_offset=data_at_LABEL_" + lbl$ + ";"
            END IF
            layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
            GOTO finishedline
        END IF
    END IF


    IF n >= 1 THEN
        IF firstelement$ = "OPTION" THEN
            IF n <> 3 THEN x = 71: GOTO errnum
            IF getelement$(a$, 2) <> "BASE" THEN x = 72: GOTO errnum
            l$ = getelement$(a$, 3)
            IF l$ <> "0" AND l$ <> "1" THEN x = 73: GOTO errnum
            IF l$ = "1" THEN optionbase = 1 ELSE optionbase = 0
            l$ = "OPTION" + sp + "BASE" + sp + l$
            layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
            GOTO finishedline
        END IF
    END IF

    'ON ... GOTO/GOSUB
    IF n >= 1 THEN
        IF firstelement$ = "ON" THEN
            xongotogosub a$, ca$, n
            GOTO finishedline
        END IF
    END IF

    IF n >= 1 THEN
        IF firstelement$ = "LET" THEN
            IF n = 1 THEN x = 74: GOTO errnum
            ca$ = RIGHT$(ca$, LEN(ca$) - 4)
            n = n - 1
            l$ = "LET"
            IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
            'note: layoutdone=1 will be set later
            GOTO letused
        END IF
    END IF

    'LET ???=???
    IF n >= 3 THEN
        IF INSTR(a$, sp + "=" + sp) THEN
            letused:
            assign ca$, n
            layoutdone = 1
            IF LEN(layout$) = 0 THEN layout$ = tlayout$ ELSE layout$ = layout$ + sp + tlayout$
            GOTO finishedline
        END IF
    END IF '>=3
    IF RIGHT$(a$, 2) = sp + "=" THEN a$ = "Expected ... = expression": GOTO errmes

    'Syntax error
    x = 75: GOTO errnum

    finishedline:
    THENGOTO = 0
    finishedline2:

    IF arrayprocessinghappened = 1 THEN arrayprocessinghappened = 0

    IF nochecks = 0 THEN
        IF dynscope THEN
            dynscope = 0
            PRINT #12, "if(qbevent){evnt(" + str2$(linenumber) + ");if(r)goto S_" + str2$(statementn) + ";}"
        ELSE
            PRINT #12, "if(!qbevent)break;evnt(" + str2$(linenumber) + ");}while(r);"
        END IF
    END IF

    finishednonexec:

    IF layoutdone = 0 THEN layoutok = 0 'invalidate layout if not handled

    IF continuelinefrom = 0 THEN 'note: manager #2 requires this condition

        'Include Manager #2 '***
        IF LEN(addmetainclude$) THEN

if inclevel=0 then
'backup line formatting
layoutcomment_backup$=layoutcomment$
layoutok_backup=layoutok
layout_backup$=layout$
end if

            a$ = addmetainclude$: addmetainclude$ = "" 'read/clear message
            IF inclevel = 100 THEN qb64error "Too many indwelling INCLUDE files"
            '1. Verify file exists (location is either (a)relative to source file or (b)absolute)
            fh = 99 + inclevel + 1
            FOR try = 1 TO 2
                IF try = 1 THEN
                    IF inclevel = 0 THEN
                        IF idemode THEN p$ = idepath$ + pathsep$ ELSE p$ = getfilepath$(sourcefile$)
                    ELSE
                        p$ = getfilepath$(incname(inclevel))
                    END IF
                    f$ = p$ + a$
                END IF
                IF try = 2 THEN f$ = a$
                qberrorhappened = -2 '***
                OPEN f$ FOR INPUT AS #fh
                qberrorhappened2: '***
                IF qberrorhappened = -2 THEN EXIT FOR '***
                qberrorhappened = 0
            NEXT
            IF qberrorhappened <> -2 THEN qberrorhappened = 0: qb64error "File " + a$ + " not found" '***
            inclevel = inclevel + 1: incname$(inclevel) = f$: inclinenumber(inclevel) = 0
        END IF 'fall through to next section...
        '--------------------
        IF inclevel THEN
            feednextline2:
            fh = 99 + inclevel
            '2. Feed next line
            IF EOF(fh) = 0 THEN
                LINE INPUT #fh, x$
                a3$ = x$
                continuelinefrom = 0
                inclinenumber(inclevel) = inclinenumber(inclevel) + 1
                'create extended error string 'incerror$'
                e$ = " in line " + str2(inclinenumber(inclevel)) + " of " + incname$(inclevel) + " included"
                IF inclevel > 1 THEN
                    e$ = e$ + " (through "
                    FOR x = 1 TO inclevel - 1 STEP 1
                        e$ = e$ + incname$(x)
                        IF x < inclevel - 1 THEN 'a sep is req
                            IF x = inclevel - 2 THEN
                                e$ = e$ + " then "
                            ELSE
                                e$ = e$ + ", "
                            END IF
                        END IF
                    NEXT
                    e$ = e$ + ")"
                END IF
                incerror$ = e$
                linenumber = linenumber - 1 'lower official linenumber to counter later increment
                IF idemode THEN sendc$ = CHR$(10) + a3$: GOTO sendcommand 'passback
                GOTO includeline
            END IF
            '3. Close & return control
            CLOSE #fh
            inclevel = inclevel - 1
            if inclevel then goto feednextline2 'still indwelling

            'restore line formatting            
            layoutok=layoutok_backup
            layout$=layout_backup$
            layoutcomment$=layoutcomment_backup$

        END IF 'fall through to next section...
        '(end manager)

    END IF 'continuelinefrom=0


    IF debug THEN
        PRINT #9, "[layout check]"
        PRINT #9, "[" + layoutoriginal$ + "]"
        PRINT #9, "[" + layout$ + "]"
        PRINT #9, layoutok
        PRINT #9, "[end layout check]"
    END IF




    IF idemode THEN
        IF continuelinefrom <> 0 THEN GOTO ide4 'continue processing other commands on line

        IF LEN(layoutcomment$) THEN
            IF LEN(layout$) THEN layout$ = layout$ + sp + layoutcomment$ ELSE layout$ = layoutcomment$
        END IF

        IF layoutok = 0 THEN
            layout$ = layoutoriginal$
        ELSE

            'reverse '046' changes present in autolayout
            'replace fix046$ with .
            i = INSTR(layout$, fix046$)
            DO WHILE i
                layout$ = LEFT$(layout$, i - 1) + "." + RIGHT$(layout$, LEN(layout$) - (i + LEN(fix046$) - 1))
                i = INSTR(layout$, fix046$)
            LOOP

        END IF
        x = lhscontrollevel: IF controllevel < lhscontrollevel THEN x = controllevel
        if definingtype=2 then x=x+1
        if declaringlibrary=2 then x=x+1
        layout$ = SPACE$(x) + layout$
        IF linecontinuation THEN layout$ = ""

        GOTO ideret4 'return control to IDE
    END IF

    'layout is not currently used by the compiler (as appose to the IDE), if it was it would be used here

LOOP

ide5:
linenumber = 0

IF closedmain = 0 THEN closemain

if definingtype then linenumber=definingtypeerror: a$ = "TYPE without END TYPE": GOTO errmes

'check for open controls (copy #1)
if controllevel then
x=controltype(controllevel)
if x=1 then a$="IF without ENDIF"
if x=2 then a$="FOR without NEXT"
if x=3 or x=4 then a$="DO without LOOP"
if x=5 then a$="WHILE without WEND"
if (x>=10 and x<=17) or x=18 or x=19 then a$="SELECT CASE without END SELECT"
linenumber=controlref(controllevel)
GOTO errmes
end if

if len(subfunc) then a$ = "SUB/FUNCTION without END SUB/FUNCTION": GOTO errmes

'close the error handler (cannot be put in 'closemain' because subs/functions can also add error jumps to this file)
PRINT #14, "exit(99);" 'in theory this line should never be run!
PRINT #14, "}" 'close error jump handler

'create CLEAR method "CLEAR"
CLOSE #12 'close code handle
OPEN tmpdir$ + "clear.txt" FOR OUTPUT AS #12 'direct code to clear.txt

FOR i = 1 TO idn

    IF ids(i).staticscope THEN 'static scope?
        subfunc = RTRIM$(ids(i).insubfunc) 'set static scope
        GOTO clearstaticscope
    END IF

    a = ASC(ids(i).insubfunc)
    IF a = 0 OR a = 32 THEN 'global scope?
        subfunc = "" 'set global scope
        clearstaticscope:

        IF ids(i).arraytype THEN 'an array
            getid i
            IF id.arrayelements = -1 THEN GOTO clearerasereturned 'cannot erase non-existant array
            clearerasereturn = 1: GOTO clearerase
        END IF 'array

        IF ids(i).t THEN 'non-array variable
            getid i
            bytes$ = variablesize$(-1)
            'create a reference
            typ = id.t + ISREFERENCE
            IF typ AND ISUDT THEN
                e$ = str2(i) + "³" + str2(typ AND 511) + "³" + "0" + "³" + "0"
            ELSE
                e$ = str2(i)
            END IF
            e$ = refer$(e$, typ, 1)
            IF typ AND ISSTRING THEN
                IF typ AND ISFIXEDLENGTH THEN
                    PRINT #12, "memset((void*)(" + e$ + "->chr),0," + bytes$ + ");"
                    GOTO cleared
                ELSE
                    PRINT #12, e$ + "->len=0;"
                    GOTO cleared
                END IF
            END IF
            IF typ AND ISUDT THEN
                PRINT #12, "memset((void*)" + e$ + ",0," + bytes$ + ");"
            ELSE
                PRINT #12, "*" + e$ + "=0;"
            END IF
            GOTO cleared
        END IF 'non-array variable

    END IF 'scope

    cleared:
    clearerasereturned:
NEXT
CLOSE #12

IF debug THEN
    PRINT #9, "finished making program!"
    PRINT #9, "recompile="; recompile
END IF

'Set cmem flags for subs/functions requiring data passed in cmem
FOR i = 1 TO idn
    IF cmemlist(i) THEN 'must be in cmem

        getid i

        IF debug THEN PRINT #9, "recompiling cmem sf! checking:"; RTRIM$(id.n)

        IF id.sfid THEN 'it is an argument of a sub/function

            IF debug THEN PRINT #9, "recompiling cmem sf! It's a sub/func arg!"

            i2 = id.sfid
            x = id.sfarg

            IF debug THEN PRINT #9, "recompiling cmem sf! values:"; i2; x

            'check if cmem flag is set, if not then set it & force recompile
            IF MID$(sfcmemargs(i2), x, 1) <> CHR$(1) THEN
                MID$(sfcmemargs(i2), x, 1) = CHR$(1)


                IF debug THEN PRINT #9, "recompiling cmem sf! setting:"; i2; x


                recompile = 1
            END IF
        END IF
    END IF
NEXT i

unresolved = 0
FOR i = 1 TO idn
    getid i

    IF debug THEN PRINT #9, "checking id named:"; id.n

    IF id.subfunc THEN
        FOR i2 = 1 TO id.args
            t = CVL(MID$(id.arg, i2 * 4 - 3, 4))
            IF t > 0 THEN
                IF (t AND ISPOINTER) THEN
                    IF (t AND ISARRAY) THEN

                        IF debug THEN PRINT #9, "checking argument "; i2; " of "; id.args

                        nele = ASC(MID$(id.nele, i2, 1))
                        nelereq = ASC(MID$(id.nelereq, i2, 1))

                        IF debug THEN PRINT #9, "nele="; nele
                        IF debug THEN PRINT #9, "nelereq="; nelereq

                        IF nele <> nelereq THEN

                            IF debug THEN PRINT #9, "mismatch detected!"

                            unresolved = unresolved + 1
                            sflistn = sflistn + 1
                            sfidlist(sflistn) = i
                            sfarglist(sflistn) = i2
                            sfelelist(sflistn) = nelereq '0 means still unknown
                        END IF
                    END IF
                END IF
            END IF
        NEXT
    END IF
NEXT

'is recompilation required to resolve this?
IF unresolved > 0 THEN
    IF lastunresolved = -1 THEN
        'first pass
        recompile = 1
        IF debug THEN
            PRINT #9, "recompiling to resolve array elements (first time)"
            PRINT #9, "sflistn="; sflistn
            PRINT #9, "oldsflistn="; oldsflistn
        END IF
    ELSE
        'not first pass
        IF unresolved < lastunresolved THEN
            recompile = 1
            IF debug THEN
                PRINT #9, "recompiling to resolve array elements (not first time)"
                PRINT #9, "sflistn="; sflistn
                PRINT #9, "oldsflistn="; oldsflistn
            END IF
        END IF
    END IF
END IF 'unresolved
lastunresolved = unresolved

'IDEA!
'have a flag to record if anything gets resolved in a pass
'if not then it's time to stop
'the problem is the same amount of new problems may be created by a
'resolve as those that get fixed
'also/or.. could it be that previous fixes are overridden in a recompile
'          by a new fix? if so, it would give these effects



'could recompilation resolve this?
'IF sflistn <> -1 THEN
'IF sflistn <> oldsflistn THEN
'recompile = 1
'
'if debug then
'print #9,"recompile set to 1 to resolve array elements"
'print #9,"sflistn=";sflistn
'print #9,"oldsflistn=";oldsflistn
'end if
'
'END IF
'END IF

xi = 1
FOR x = 1 TO commonarraylistn
    varname$ = getelement$(commonarraylist, xi): xi = xi + 1
    typ$ = getelement$(commonarraylist, xi): xi = xi + 1
    dimmethod = VAL(getelement$(commonarraylist, xi)): xi = xi + 1
    dimshared = VAL(getelement$(commonarraylist, xi)): xi = xi + 1
    'find the array ID (try method)
    t = typname2typ(typ$)
    IF (t AND ISUDT) = 0 THEN varname$ = varname$ + type2symbol$(typ$)
    try = findid(varname$)
    DO WHILE try
        IF id.arraytype THEN GOTO foundcommonarray2
        IF try = 2 THEN findanotherid = 1: try = findid(varname$) ELSE try = 0
    LOOP
    foundcommonarray2:
    IF id.arrayelements = -1 THEN
        IF arrayelementslist(currentid) <> 0 THEN recompile = 1
        IF debug THEN PRINT #9, "Recompiling to resolve elements of:" + varname$
    END IF
NEXT

IF recompile THEN
    recompile = 0
    IF idemode THEN iderecompile = 1
    for closeall=1 to 255:CLOSE closeall:next
    OPEN tmpdir$ + "temp.bin" FOR OUTPUT LOCK READ WRITE AS #26 'relock
    GOTO recompile
END IF


for r=1 to nLabels

if Labels(r).Scope_Restriction then
a$=rtrim$(labels(r).cn)
ignore=validlabel(a$)
v=HashFind(a$,HASHFLAG_LABEL,ignore,r2)
addlabchk7: 
if v then
if labels(r2).scope=Labels(r).Scope_Restriction then
linenumber=labels(r).error_line:a$="Common label within a SUB/FUNCTION": goto errmes
end if
if v=2 then v=HashFindCont(ignore,r2): goto addlabchk7
end if 'v
end if 'restriction

'check for undefined labels
if labels(r).state=0 then linenumber=labels(r).error_line:a$="Label not defined": goto errmes

if labels(r).Data_Referenced then

'check for ambiguous RESTORE reference
x=0
a$=rtrim$(labels(r).cn)
ignore=validlabel(a$)
v=HashFind(a$,HASHFLAG_LABEL,ignore,r2)
addlabchk4: 
if v then
x=x+1
if v=2 then v=HashFindCont(ignore,r2): goto addlabchk4
end if 'v
if x<>1 then linenumber=labels(r).error_line:a$="Ambiguous DATA label": goto errmes

'add global data offset variable
PRINT #18, "ptrszint data_at_LABEL_" + a$ + "=" + str2(labels(r).data_offset) + ";"

end if 'data referenced

next



'if targettyp=-4 or targettyp=-5 then '? -> byte_element(offset,element size in bytes)
' IF (sourcetyp AND ISREFERENCE) = 0 THEN nerror (62)


'create include files for COMMON arrays

CLOSE #12

'return to 'main'
subfunc$ = ""
defdatahandle = 18
CLOSE #13: OPEN tmpdir$ + "maindata.txt" FOR APPEND AS #13
CLOSE #19: OPEN tmpdir$ + "mainfree.txt" FOR APPEND AS #19

'DATA_finalize
PRINT #18, "ptrszint data_size=" + str2(dataoffset) + ";"
if dataoffset=0 then
 print #18, "uint8 *data=(uint8*)calloc(1,1);"
else

if os$="WIN" then
 x$=chr$(0): put #16,,x$
 print #18, "extern "+chr$(34)+"C"+chr$(34)+"{"
 print #18, "extern char *binary_____temp"+tempfolderindexstr2$+"__data_bin_start;"
 print #18, "}"
 print #18, "uint8 *data=(uint8*)&binary_____temp"+tempfolderindexstr2$+"__data_bin_start;"
end if
if os$="LNX" then
 x$=chr$(0): put #16,,x$
 print #18, "extern "+chr$(34)+"C"+chr$(34)+"{"
 print #18, "extern char *_binary____temp"+tempfolderindexstr2$+"_data_bin_start;"
 print #18, "}"
 print #18, "uint8 *data=(uint8*)&_binary____temp"+tempfolderindexstr2$+"_data_bin_start;"
end if


end if




ncommontmp = 0
xi = 1
FOR x = 1 TO commonarraylistn
    varname$ = getelement$(commonarraylist, xi): xi = xi + 1
    typ$ = getelement$(commonarraylist, xi): xi = xi + 1
    dimmethod = VAL(getelement$(commonarraylist, xi)): xi = xi + 1
    dimshared = VAL(getelement$(commonarraylist, xi)): xi = xi + 1

    'find the array ID (try method)
    purevarname$ = varname$
    t = typname2typ(typ$)
    IF (t AND ISUDT) = 0 THEN varname$ = varname$ + type2symbol$(typ$)
    try = findid(varname$)
    DO WHILE try
        IF id.arraytype THEN GOTO foundcommonarray
        IF try = 2 THEN findanotherid = 1: try = findid(varname$) ELSE try = 0
    LOOP
    a$ = "COMMON array unlocatable": GOTO errmes 'should never happen
    foundcommonarray:


    i = currentid
    arraytype = id.arraytype
    arrayelements = id.arrayelements
    e$ = RTRIM$(id.n)
    IF (t AND ISUDT) = 0 THEN e$ = e$ + typevalue2symbol$(t)
    n$ = e$
    n2$ = RTRIM$(id.callname)
    tsize = id.tsize

    'select command
    com = 3 'fixed length elements
    IF t AND ISSTRING THEN
        IF (t AND ISFIXEDLENGTH) = 0 THEN
            com = 4 'var-len elements
        END IF
    END IF


    'if...
    'i) array elements are still undefined (ie. arrayelements=-1) pass the input content along
    '   if any existed or an array-placeholder
    'ii) if the array's elements were defined, any input content would have been loaded so the
    '    array (in whatever state it currently is) should be passed. If it is currently erased
    '    then it should be passed as a placeholder


    IF arrayelements = -1 THEN

        'load array (copies the array, if any, into a buffer for later)

        OPEN tmpdir$ + "inpchain" + str2$(i) + ".txt" FOR OUTPUT AS #12
        PRINT #12, "if (int32val==2){" 'array place-holder
        'create buffer to store array as-is in global.txt
        x$ = str2$(uniquenumber)
        x1$ = "chainarraybuf" + x$
        x2$ = "chainarraybufsiz" + x$
        PRINT #18, "static uint8 *" + x1$ + "=(uint8*)malloc(1);"
        PRINT #18, "static int64 " + x2$ + "=0;"
        'read next command
        PRINT #12, "sub_get(FF,NULL,byte_element((uint64)&int32val,4),0);"

        IF com = 3 THEN PRINT #12, "if (int32val==3){" 'fixed-length-element array
        IF com = 4 THEN PRINT #12, "if (int32val==4){" 'var-length-element array
        PRINT #12, x2$ + "+=4; " + x1$ + "=(uint8*)realloc(" + x1$ + "," + x2$ + "); *(int32*)(" + x1$ + "+" + x2$ + "-4)=int32val;"

        IF com = 3 THEN
            'read size in bits of one element, convert it to bytes
            PRINT #12, "sub_get(FF,NULL,byte_element((uint64)&int64val,8),0);"
            PRINT #12, x2$ + "+=8; " + x1$ + "=(uint8*)realloc(" + x1$ + "," + x2$ + "); *(int64*)(" + x1$ + "+" + x2$ + "-8)=int64val;"
            PRINT #12, "bytes=int64val>>3;"
        END IF 'com=3

        IF com = 4 THEN PRINT #12, "bytes=1;" 'bytes used to calculate number of elements

        'read number of dimensions
        PRINT #12, "sub_get(FF,NULL,byte_element((uint64)&int32val,4),0);"
        PRINT #12, x2$ + "+=4; " + x1$ + "=(uint8*)realloc(" + x1$ + "," + x2$ + "); *(int32*)(" + x1$ + "+" + x2$ + "-4)=int32val;"

        'read size of dimensions & calculate the size of the array in bytes
        PRINT #12, "while(int32val--){"
        PRINT #12, "sub_get(FF,NULL,byte_element((uint64)&int64val,8),0);" 'lbound
        PRINT #12, x2$ + "+=8; " + x1$ + "=(uint8*)realloc(" + x1$ + "," + x2$ + "); *(int64*)(" + x1$ + "+" + x2$ + "-8)=int64val;"
        PRINT #12, "sub_get(FF,NULL,byte_element((uint64)&int64val2,8),0);" 'ubound
        PRINT #12, x2$ + "+=8; " + x1$ + "=(uint8*)realloc(" + x1$ + "," + x2$ + "); *(int64*)(" + x1$ + "+" + x2$ + "-8)=int64val2;"
        PRINT #12, "bytes*=(int64val2-int64val+1);"
        PRINT #12, "}"

        IF com = 3 THEN
            'read the array data
            PRINT #12, x2$ + "+=bytes; " + x1$ + "=(uint8*)realloc(" + x1$ + "," + x2$ + ");"
            PRINT #12, "sub_get(FF,NULL,byte_element((uint64)(" + x1$ + "+" + x2$ + "-bytes),bytes),0);"
        END IF 'com=3

        IF com = 4 THEN
            PRINT #12, "bytei=0;"
            PRINT #12, "while(bytei<bytes){"
            PRINT #12, "sub_get(FF,NULL,byte_element((uint64)&int64val,8),0);" 'get size
            PRINT #12, x2$ + "+=8; " + x1$ + "=(uint8*)realloc(" + x1$ + "," + x2$ + "); *(int64*)(" + x1$ + "+" + x2$ + "-8)=int64val;"
            PRINT #12, x2$ + "+=(int64val>>3); " + x1$ + "=(uint8*)realloc(" + x1$ + "," + x2$ + ");"
            PRINT #12, "sub_get(FF,NULL,byte_element((uint64)(" + x1$ + "+" + x2$ + "-(int64val>>3)),(int64val>>3)),0);"
            PRINT #12, "bytei++;"
            PRINT #12, "}"
        END IF

        'get next command
        PRINT #12, "sub_get(FF,NULL,byte_element((uint64)&int32val,4),0);"
        PRINT #12, "}" 'command=3 or 4

        PRINT #12, "}" 'array place-holder
        CLOSE #12


        'save array (saves the buffered data, if any, for later)

        OPEN tmpdir$ + "chain" + str2$(i) + ".txt" FOR OUTPUT AS #12
        PRINT #12, "int32val=2;" 'placeholder
        PRINT #12, "sub_put(FF,NULL,byte_element((uint64)&int32val,4),0);"

        PRINT #12, "sub_put(FF,NULL,byte_element((uint64)" + x1$ + "," + x2$ + "),0);"
        CLOSE #12




    ELSE
        'note: arrayelements<>-1

        'load array

        OPEN tmpdir$ + "inpchain" + str2$(i) + ".txt" FOR OUTPUT AS #12

        PRINT #12, "if (int32val==2){" 'array place-holder
        PRINT #12, "sub_get(FF,NULL,byte_element((uint64)&int32val,4),0);"

        IF com = 3 THEN PRINT #12, "if (int32val==3){" 'fixed-length-element array
        IF com = 4 THEN PRINT #12, "if (int32val==4){" 'var-length-element array

        IF com = 3 THEN
            'get size in bits
            PRINT #12, "sub_get(FF,NULL,byte_element((uint64)&int64val,8),0);"
            '***assume correct***
        END IF

        'get number of elements
        PRINT #12, "sub_get(FF,NULL,byte_element((uint64)&int32val,4),0);"
        '***assume correct***

        e$ = ""
        IF com = 4 THEN PRINT #12, "bytes=1;" 'bytes counts the number of total elements
        FOR x2 = 1 TO arrayelements

            'create 'secret' variables to assist in passing common arrays
            IF x2 > ncommontmp THEN
                ncommontmp = ncommontmp + 1
                retval = dim2("_RESERVED_COMMON_LBOUND" + str2$(ncommontmp), "_INTEGER64", 0, "")
                retval = dim2("_RESERVED_COMMON_UBOUND" + str2$(ncommontmp), "_INTEGER64", 0, "")
            END IF

            PRINT #12, "sub_get(FF,NULL,byte_element((uint64)&int64val,8),0);"
            PRINT #12, "*__INTEGER64__RESERVED_COMMON_LBOUND" + str2$(x2) + "=int64val;"
            PRINT #12, "sub_get(FF,NULL,byte_element((uint64)&int64val2,8),0);"
            PRINT #12, "*__INTEGER64__RESERVED_COMMON_UBOUND" + str2$(x2) + "=int64val2;"
            IF com = 4 THEN PRINT #12, "bytes*=(int64val2-int64val+1);"
            IF x2 > 1 THEN e$ = e$ + sp + "," + sp
            e$ = e$ + "_RESERVED_COMMON_LBOUND" + str2$(x2) + sp + "TO" + sp + "_RESERVED_COMMON_UBOUND" + str2$(x2)
        NEXT
        redimoption = 1
        retval = dim2(purevarname$, typ$, 0, e$)
        redimoption = 0

        IF com = 3 THEN
            'use get to load in the array data
            varname$ = varname$ + sp + "(" + sp + ")"
            e$ = evaluatetotyp(fixoperationorder$(varname$), -4)
            PRINT #12, "sub_get(FF,NULL," + e$ + ",0);"
        END IF

        IF com = 4 THEN
            PRINT #12, "bytei=0;"
            PRINT #12, "while(bytei<bytes){"
            PRINT #12, "sub_get(FF,NULL,byte_element((uint64)&int64val,8),0);" 'get size
            PRINT #12, "tqbs=((qbs*)(((uint64*)(" + n2$ + "[0]))[bytei]));" 'get element
            PRINT #12, "qbs_set(tqbs,qbs_new(int64val>>3,1));" 'change string size
            PRINT #12, "sub_get(FF,NULL,byte_element((uint64)tqbs->chr,int64val>>3),0);" 'get size
            PRINT #12, "bytei++;"
            PRINT #12, "}"
        END IF

        'get next command
        PRINT #12, "sub_get(FF,NULL,byte_element((uint64)&int32val,4),0);"
        PRINT #12, "}"
        PRINT #12, "}"
        CLOSE #12

        'save array

        OPEN tmpdir$ + "chain" + str2$(i) + ".txt" FOR OUTPUT AS #12

        PRINT #12, "int32val=2;" 'placeholder
        PRINT #12, "sub_put(FF,NULL,byte_element((uint64)&int32val,4),0);"

        PRINT #12, "if (" + n2$ + "[2]&1){" 'don't add unless defined

        IF com = 3 THEN PRINT #12, "int32val=3;"
        IF com = 4 THEN PRINT #12, "int32val=4;"
        PRINT #12, "sub_put(FF,NULL,byte_element((uint64)&int32val,4),0);"

        IF com = 3 THEN
            'size of each element in bits
            bits = t AND 511
            IF t AND ISUDT THEN bits = udtxsize(t AND 511)
            IF t AND ISSTRING THEN bits = tsize * 8
            PRINT #12, "int64val=" + str2$(bits) + ";" 'size in bits
            PRINT #12, "sub_put(FF,NULL,byte_element((uint64)&int64val,8),0);"
        END IF 'com=3

        PRINT #12, "int32val=" + str2$(arrayelements) + ";" 'number of dimensions
        PRINT #12, "sub_put(FF,NULL,byte_element((uint64)&int32val,4),0);"

        IF com = 3 THEN

            FOR x2 = 1 TO arrayelements
                'simulate calls to lbound/ubound
                e$ = "LBOUND" + sp + "(" + sp + n$ + sp + "," + sp + str2$(x2) + sp + ")"
                e$ = evaluatetotyp(fixoperationorder$(e$), 64)
                PRINT #12, "int64val=" + e$ + ";"
                PRINT #12, "sub_put(FF,NULL,byte_element((uint64)&int64val,8),0);"
                e$ = "UBOUND" + sp + "(" + sp + n$ + sp + "," + sp + str2$(x2) + sp + ")"
                e$ = evaluatetotyp(fixoperationorder$(e$), 64)
                PRINT #12, "int64val=" + e$ + ";"
                PRINT #12, "sub_put(FF,NULL,byte_element((uint64)&int64val,8),0);"
            NEXT

            'array data
            e$ = evaluatetotyp(fixoperationorder$(n$ + sp + "(" + sp + ")"), -4)
            PRINT #12, "sub_put(FF,NULL," + e$ + ",0);"

        END IF 'com=3

        IF com = 4 THEN

            'store LBOUND/UBOUND values and calculate number of total elements/strings
            PRINT #12, "bytes=1;" 'note: bytes is actually the total number of elements
            FOR x2 = 1 TO arrayelements
                e$ = "LBOUND" + sp + "(" + sp + n$ + sp + "," + sp + str2$(x2) + sp + ")"
                e$ = evaluatetotyp(fixoperationorder$(e$), 64)
                PRINT #12, "int64val=" + e$ + ";"
                PRINT #12, "sub_put(FF,NULL,byte_element((uint64)&int64val,8),0);"
                e$ = "UBOUND" + sp + "(" + sp + n$ + sp + "," + sp + str2$(x2) + sp + ")"
                e$ = evaluatetotyp(fixoperationorder$(e$), 64)
                PRINT #12, "int64val2=" + e$ + ";"
                PRINT #12, "sub_put(FF,NULL,byte_element((uint64)&int64val2,8),0);"
                PRINT #12, "bytes*=(int64val2-int64val+1);"
            NEXT

            PRINT #12, "bytei=0;"
            PRINT #12, "while(bytei<bytes){"
            PRINT #12, "tqbs=((qbs*)(((uint64*)(" + n2$ + "[0]))[bytei]));" 'get element
            PRINT #12, "int64val=tqbs->len; int64val<<=3;"
            PRINT #12, "sub_put(FF,NULL,byte_element((uint64)&int64val,8),0);" 'size of element
            PRINT #12, "sub_put(FF,NULL,byte_element((uint64)tqbs->chr,tqbs->len),0);" 'element data
            PRINT #12, "bytei++;"
            PRINT #12, "}"

        END IF 'com=4

        PRINT #12, "}" 'don't add unless defined

        CLOSE #12




        'if chaincommonarray then
        'l2$=tlayout$
        'x=chaincommonarray
        '
        ''chain???.txt
        'open tmpdir$ + "chain" + str2$(x) + ".txt" for append as #22
        'if lof(22) then close #22: goto chaindone 'only add this once
        ''***assume non-var-len-string array***
        'print #22,"int32val=3;" 'non-var-len-element array
        'print #22,"sub_put(FF,NULL,byte_element((uint64)&int32val,4),0);"
        't=id.arraytype
        ''***check for UDT size if necessary***
        ''***check for string length if necessary***
        'bits=t and 511
        'print #22,"int64val="+str2$(bits)+";" 'size in bits
        'print #22,"sub_put(FF,NULL,byte_element((uint64)&int64val,8),0);"
        'print #22,"int32val="+str2$(id.arrayelements)+";" 'number of elements
        'print #22,"sub_put(FF,NULL,byte_element((uint64)&int32val,4),0);"
        'e$=rtrim$(id.n)
        'if (t and ISUDT)=0 then e$=e$+typevalue2symbol$(t)
        'n$=e$
        'for x2=1 to id.arrayelements
        ''simulate calls to lbound/ubound
        'e$="LBOUND"+sp+"("+sp+n$+sp+","+sp+str2$(x2)+sp+")"
        'e$=evaluatetotyp(fixoperationorder$(e$),64)
        'print #22,"int64val="+e$+";"'LBOUND
        'print #22,"sub_put(FF,NULL,byte_element((uint64)&int64val,8),0);"
        'e$="UBOUND"+sp+"("+sp+n$+sp+","+sp+str2$(x2)+sp+")"
        'e$=evaluatetotyp(fixoperationorder$(e$),64)
        'print #22,"int64val="+e$+";"'LBOUND
        'print #22,"sub_put(FF,NULL,byte_element((uint64)&int64val,8),0);"
        'next
        ''add array data
        'e$=evaluatetotyp(fixoperationorder$(n$+sp+"("+sp+")"),-4)
        'print #22,"sub_put(FF,NULL,"+e$+",0);"
        'close #22
        '
        ''inpchain???.txt
        'open tmpdir$ + "chain" + str2$(x) + ".txt" for append as #22
        'print #22,"if (int32val==1){" 'common declaration of an array
        'print #22,"sub_get(FF,NULL,byte_element((uint64)&int32val,4),0);"
        'print #22,"if (int32val==3){" 'fixed-length-element array
        '
        'print #22,"sub_get(FF,NULL,byte_element((uint64)&int64val,8),0);"
        ''***assume size correct and continue***
        '
        ''get number of elements
        'print #22,"sub_get(FF,NULL,byte_element((uint64)&int32val,4),0);"
        '
        ''call dim2 and tell it to redim an array
        '
        ''*********this should happen BEFORE the array (above) is actually dimensioned,
        ''*********where the common() declaration is
        '
        ''****although, if you never reference the array.............
        ''****ARGH! you can access an undimmed array just like in a sub/function
        ''****OUCH, OUCH, OUCH, OUCH, OUCH
        ''****MUMMY!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        '
        '
        '
        '
        'print #22,"}"
        'print #22,"}"
        'close #22
        '
        'chaindone:
        'tlayout$=l2$
        'end if 'chaincommonarray




        'OPEN tmpdir$ + "chain.txt" FOR APPEND AS #22
        ''include directive
        'print #22, "#include " + CHR$(34) + "chain" + str2$(x) + ".txt" + CHR$(34)
        'close #22
        ''create/clear include file
        'open tmpdir$ + "chain" + str2$(x) + ".txt" for output as #22:close #22
        '
        'OPEN tmpdir$ + "inpchain.txt" FOR APPEND AS #22
        ''include directive
        'print #22, "#include " + CHR$(34) + "inpchain" + str2$(x) + ".txt" + CHR$(34)
        'close #22
        ''create/clear include file
        'open tmpdir$ + "inpchain" + str2$(x) + ".txt" for output as #22:close #22






    END IF 'id.arrayelements=-1






NEXT




for closeall=1 to 255:CLOSE closeall:next
OPEN tmpdir$ + "temp.bin" FOR OUTPUT LOCK READ WRITE AS #26 'relock








IF idemode THEN GOTO ideret5
ide6:

IF idemode = 0 THEN
    PRINT

if os$="LNX" then
    PRINT "COMPILING C++ CODE INTO EXECUTABLE..."
else
    PRINT "COMPILING C++ CODE INTO EXE..."
end if

    ON ERROR GOTO qberror_test
    e = 0
    OPEN file$ + extension$ FOR OUTPUT AS #1
    ON ERROR GOTO qberror
    IF e = 1 THEN
        PRINT "CANNOT CREATE " + CHR$(34) + file$ + extension$ + CHR$(34) + " BECAUSE THE FILE IS ALREADY IN USE!"
        END
    ELSE
        CLOSE #1
    END IF

END IF 'idemode=0


IF os$ = "WIN" THEN

    if dataoffset then
    OPEN ".\internal\c\makedat.txt" FOR INPUT AS #150: LINE INPUT #150, a$: close #150
    a$=a$+" "+tmpdir2$+"data.bin "+tmpdir2$+"data.o"
    CHDIR ".\internal\c"
    SHELL _HIDE a$
    CHDIR "..\.."
    end if

comptime#=timer(0.001)
    
    OPEN ".\internal\c\makeline.txt" FOR INPUT AS #150
    LINE INPUT #150, a$
    CLOSE #150    
    IF RIGHT$(a$, 7) = " ..\..\" THEN a$ = LEFT$(a$, LEN(a$) - 6) 'makeline.txt patch (line will become unrequired in later versions)
    'change qbx.cpp to qbx999.cpp?
    x = INSTR(a$, "qbx.cpp"): IF x <> 0 AND tempfolderindex <> 1 THEN a$ = LEFT$(a$, x - 1) + "qbx" + str2$(tempfolderindex) + ".cpp" + RIGHT$(a$, LEN(a$) - (x + 6))

    'add data.o?
    if dataoffset then
    x = INSTR(a$, "-L.\l")
    if x then
    x=x+4
    a$=left$(a$,x)+" "+tmpdir2$+"data.o"+right$(a$,len(a$)-x)
    end if
    end if

    'add custom libraries
    'mylib$="..\..\"+x$+".lib"
if len(mylib$) then
    x = INSTR(a$, "-mwindows")
    if x then
    x=x+8
    a$=left$(a$,x)+" "+mylib$+right$(a$,len(a$)-x)
    end if
end if


    CHDIR ".\internal\c"
    a$=a$ + idezfilename$("..\..\" + file$ + extension$)
    SHELL _HIDE a$
    CHDIR "..\.."

END IF

IF os$ = "LNX" THEN
    


    if dataoffset then
    OPEN ".\internal\c\makedat_lnx.txt" FOR INPUT AS #150: LINE INPUT #150, a$: close #150
    a$=a$+" "+tmpdir2$+"data.bin "+tmpdir2$+"data.o"
    CHDIR ".\internal\c"
    SHELL _HIDE a$
    CHDIR "..\.."
    end if

    
    OPEN "./internal/c/makeline_lnx.txt" FOR INPUT AS #150
    LINE INPUT #150, a$
    CLOSE #150
    'change qbx.cpp to qbx999.cpp?
    x = INSTR(a$, "qbx.cpp"): IF x <> 0 AND tempfolderindex <> 1 THEN a$ = LEFT$(a$, x - 1) + "qbx" + str2$(tempfolderindex) + ".cpp" + RIGHT$(a$, LEN(a$) - (x + 6))

    'add data.o?
    if dataoffset then
    x = INSTR(a$, "-lSDL_image")
    if x then
    x=x+10
    a$=left$(a$,x)+" "+tmpdir2$+"data.o"+right$(a$,len(a$)-x)
    end if
    end if

    CHDIR "./internal/c"
    a$=a$ + idezfilename$("../../" + file$ + extension$)
    SHELL _HIDE a$
    CHDIR "../.."


END IF

'detect compilation failure
OPEN file$ + extension$ FOR BINARY AS #1
IF LOF(1) THEN compfailed = 0 ELSE compfailed = 1
CLOSE #1

IF compfailed THEN
if timer(0.001)<comptime#+4 and os$="WIN" then 'check time taken to fail (a long time indicates a different problem and a recompile would be very costly)

'ensure 'finished' report file does not exist
ON ERROR GOTO qberror_test
KILL "done_run"+tempfolderindexstr2+".bin"
ON ERROR GOTO qberror

'create batch file
open "run"+tempfolderindexstr2+".bat" for output as #1
print #1,"cd .\internal\c"
print #1,a$ 'the line to c++ compile
print #1,"copy ..\..\run"+tempfolderindexstr2+".bat ..\..\done_run"+tempfolderindexstr2+".bin" 'batch code complete
close #1

'copy qb64_run.exe to main qb64 folder as qb64_run999.exe (so it can access common DLL files)
SHELL _HIDE "copy .\internal\c\qb64_run.exe qb64_run"+tempfolderindexstr2+".exe"

SHELL "qb64_run"+tempfolderindexstr2+".exe run"+tempfolderindexstr2+".bat"

'wait for done_run to be created
ON ERROR GOTO qberror_test
DO
_LIMIT 4
e=0
open "done_run"+tempfolderindexstr2+".bin" for input as #1
LOOP until e=0
ON ERROR GOTO qberror
close #1

'remove temp files
ON ERROR GOTO qberror_test
KILL "qb64_run"+tempfolderindexstr2+".exe"
KILL "run"+tempfolderindexstr2+".bat"
KILL "done_run"+tempfolderindexstr2+".bin"
ON ERROR GOTO qberror

'detect compilation failure (2nd time)
OPEN file$ + extension$ FOR BINARY AS #1
IF LOF(1) THEN compfailed = 0 ELSE compfailed = 1
CLOSE #1

end if 'time limit
end if

IF compfailed THEN
    KILL file$ + extension$
    IF idemode THEN
        idemessage$ = "C++ Compilation failed"
        GOTO ideerror
    END IF
    if compfailed then PRINT "C++ COMPILATION FAILED!"
END IF

IF idemode THEN GOTO ideret6

if UpdateHandle then
ideupdatetimerval=TIMER
do until abs(TIMER-ideupdatetimerval)>=3
ContinueDownloads
IF DL(UpdateHandle).State=2 THEN 'download complete
update 2
UpdateHandle=0
goto qb64updated
end if
_limit 10
loop
close DL(UpdateHandle).handle: DL(UpdateHandle).state=0: UpdateHandle=0
qb64updated:
end if 'updatehandle

if compfailed then END
SYSTEM

qberror_test:
e = 1
RESUME NEXT

qberror:

IF ideerror THEN 'error happened inside the IDE
    sendc$ = CHR$(255) 'a runtime error has occurred
    RESUME sendcommand 'allow IDE to handle error recovery
END IF

IF ERR = 2 THEN RESUME ideerror 'qb64error purposefully generated error 2 (syntax error), only happens in idemode

qberrorhappenedvalue = qberrorhappened
qberrorhappened = 1

IF debug THEN PRINT #9, "QB ERROR!"
IF debug THEN PRINT #9, "ERR="; ERR
IF debug THEN PRINT #9, "ERL="; ERL

IF idemode AND qberrorhappenedvalue >= 0 THEN
    'real qb error occurred
    ideerrorline = linenumber
    idemessage$ = "Compiler error (check for syntax errors) (Reference:" + str2$(ERR) + "-" + str2$(_ERRORLINE) + ")"
    IF inclevel > 0 THEN idemessage$ = idemessage$ + incerror$
    RESUME ideerror
END IF

IF qberrorhappenedvalue >= 0 THEN
    x = 76: GOTO errnum 'internal comiler error
END IF


qberrorcode = ERR
qberrorline = ERL
IF qberrorhappenedvalue = -1 THEN RESUME qberrorhappened1
IF qberrorhappenedvalue = -2 THEN RESUME qberrorhappened2
IF qberrorhappenedvalue = -3 THEN RESUME qberrorhappened3
END

'directly GOTO'd to from supporting routines
errnum:
'set x to error's value
IF os$ = "WIN" THEN OPEN ".\internal\qb64\errormes.txt" FOR INPUT AS #50
IF os$ = "LNX" THEN OPEN "./internal/qb64/errormes.txt" FOR INPUT AS #50
FOR i = 1 TO x
    LINE INPUT #50, a$
NEXT
CLOSE #50
a$ = RIGHT$(a$, LEN(a$) - INSTR(a$, ","))
errmes: 'set a$ to message
layout$ = "": layoutok = 0 'invalidate layout
IF inclevel > 0 THEN a$ = a$ + incerror$
IF idemode THEN
    ideerrorline = linenumber
    idemessage$ = a$
    GOTO ideerror 'infinitely preferable to RESUME
END IF
'non-ide mode output
PRINT
PRINT a$
FOR i = 1 TO LEN(linefragment)
    IF MID$(linefragment, i, 1) = sp$ THEN MID$(linefragment, i, 1) = " "
NEXT
FOR i = 1 TO LEN(wholeline)
    IF MID$(wholeline, i, 1) = sp$ THEN MID$(wholeline, i, 1) = " "
NEXT
PRINT "Caused by (or after):" + linefragment
PRINT "LINE " + str2(linenumber) + ":" + wholeline

if UpdateHandle then
ideupdatetimerval=TIMER
do until abs(TIMER-ideupdatetimerval)>=3
ContinueDownloads
IF DL(UpdateHandle).State=2 THEN 'download complete
update 3
UpdateHandle=0
goto qb64updated2
end if
_limit 10
loop
close DL(UpdateHandle).handle: DL(UpdateHandle).state=0: UpdateHandle=0
qb64updated2:
end if 'updatehandle

END

FUNCTION allocarray (n2$, elements$, elementsize)
dimsharedlast = dimshared: dimshared = 0

IF autoarray = 1 THEN autoarray = 0: autoary = 1 'clear global value & set local value

f12$ = ""

'changelog:
'added 4 to [2] to indicate cmem array where appropriate

e$ = elements$: n$ = n2$
IF elementsize = -2147483647 THEN stringarray = 1: elementsize = 8

IF ASC(e$) = 63 THEN '?
    l$ = "(" + sp2 + ")"
    undefined = -1
    nume = 1
    IF LEN(e$) = 1 THEN GOTO undefinedarray
    undefined = 1
    nume = VAL(RIGHT$(e$, LEN(e$) - 1))
    GOTO undefinedarray
END IF


'work out how many elements there are (critical to later calculations)
nume = 1
n = numelements(e$)
FOR i = 1 TO n
    e2$ = getelement(e$, i)
    IF e2$ = "(" THEN b = b + 1
    IF b = 0 AND e2$ = "," THEN nume = nume + 1
    IF e2$ = ")" THEN b = b - 1
NEXT
IF debug THEN PRINT #9, "numelements count:"; nume

descstatic = 0
IF arraydesc THEN
    IF id.arrayelements <> nume THEN

        IF id.arrayelements = -1 THEN 'unknown
            IF arrayelementslist(currentid) <> 0 AND nume <> arrayelementslist(currentid) THEN nerror (85)
            IF nume = 1 THEN id.arrayelements = 1: ids(currentid).arrayelements = 1 'lucky guess!
            arrayelementslist(currentid) = nume
        ELSE
            nerror (85)
        END IF

    END IF
    IF id.staticarray THEN descstatic = 1
END IF

l$ = "(" + sp2

cr$ = CHR$(13) + CHR$(10)
sd$ = ""
constdimensions = 1
ei = 4 + nume * 4 - 4
cure = 1
e3$ = "": e3base$ = ""
FOR i = 1 TO n
    e2$ = getelement(e$, i)
    IF e2$ = "(" THEN b = b + 1
    IF (e2$ = "," AND b = 0) OR i = n THEN
        IF i = n THEN e3$ = e3$ + sp + e2$
        e3$ = RIGHT$(e3$, LEN(e3$) - 1)
        IF e3base$ <> "" THEN e3base$ = RIGHT$(e3base$, LEN(e3base$) - 1)
        'PRINT e3base$ + "[TO]" + e3$
        'set the base

        basegiven = 1
        IF e3base$ = "" THEN e3base$ = str2$(optionbase + 0): basegiven = 0
        constequation = 1

        e3base$ = fixoperationorder$(e3base$)
        IF basegiven THEN l$ = l$ + tlayout$ + sp + "TO" + sp
        e3base$ = evaluatetotyp$(e3base$, 64&)

        IF constequation = 0 THEN constdimensions = 0
        sd$ = sd$ + n$ + "[" + str2(ei) + "]=" + e3base$ + ";" + cr$
        'set the number of indexes
        constequation = 1

        e3$ = fixoperationorder$(e3$)
        l$ = l$ + tlayout$ + sp2
        IF i = n THEN l$ = l$ + ")" ELSE l$ = l$ + "," + sp
        e3$ = evaluatetotyp$(e3$, 64&)

        IF constequation = 0 THEN constdimensions = 0
        ei = ei + 1
        sd$ = sd$ + n$ + "[" + str2(ei) + "]=(" + e3$ + ")-" + n$ + "[" + str2(ei - 1) + "]+1;" + cr$
        ei = ei + 1
        'calc muliplier
        IF cure = 1 THEN
            'set only for the purpose of the calculating correct multipliers
            sd$ = sd$ + n$ + "[" + str2(ei) + "]=1;" + cr$
        ELSE
            sd$ = sd$ + n$ + "[" + str2(ei) + "]=" + n$ + "[" + str2(ei + 4) + "]*" + n$ + "[" + str2(ei + 3) + "];" + cr$
        END IF
        ei = ei + 1
        ei = ei + 1 'skip reserved
        ei = ei - 8
        cure = cure + 1
        e3$ = "": e3base$ = ""
        GOTO aanexte
    END IF
    IF e2$ = ")" THEN b = b - 1
    IF UCASE$(e2$) = "TO" AND b = 0 THEN
        e3base$ = e3$
        e3$ = ""
    ELSE
        e3$ = e3$ + sp + e2$
    END IF
    aanexte:
NEXT
sd$ = LEFT$(sd$, LEN(sd$) - 2)

undefinedarray:

'calc cmem
cmem = 0
IF arraydesc = 0 THEN
    IF cmemlist(idn + 1) THEN cmem = 1
ELSE
    IF cmemlist(arraydesc) THEN cmem = 1
END IF

staticarray = constdimensions
IF subfuncn <> 0 AND dimstatic = 0 THEN staticarray = 0 'arrays in SUBS/FUNCTIONS are DYNAMIC
IF dimstatic = 3 THEN staticarray = 0 'STATIC arrayname() listed arrays keep thier values but are dynamic in memory
IF dynamic THEN staticarray = 0
IF redimoption THEN staticarray = 0
IF arraydesc THEN
    IF staticarray = 1 THEN
        IF descstatic THEN nerror (86)
        staticarray = 0
    END IF
END IF






bytesperelement$ = str2(elementsize)
IF elementsize < 0 THEN
    elementsize = -elementsize
    bytesperelement$ = str2(elementsize) + "/8+1"
END IF


'Begin creation of array descriptor (if array has not been defined yet)
IF arraydesc = 0 THEN
    PRINT #defdatahandle, "ptrszint *" + n$ + "=NULL;"
    PRINT #13, "if (!" + n$ + "){"
    PRINT #13, n$ + "=(ptrszint*)mem_static_malloc(" + str2(4*nume + 4) + "*ptrsz);"
END IF

'generate sizestr$ & elesizestr$ (both are used in various places in following code)
sizestr$ = ""
FOR i = 1 TO nume
    IF i <> 1 THEN sizestr$ = sizestr$ + "*"
    sizestr$ = sizestr$ + n$ + "[" + str2(i * 4 - 4 + 5) + "]"
NEXT
elesizestr$ = sizestr$ 'elements in entire array
sizestr$ = sizestr$ + "*" + bytesperelement$ 'bytes in entire array



'------------------STATIC ARRAY CREATION--------------------------------
IF staticarray THEN
    'STATIC memory
    PRINT #13, sd$ 'setup new array dimension ranges
    'Example of sd$ for DIM a(10):
    '__ARRAY_SINGLE_A[4]= 0 ;
    '__ARRAY_SINGLE_A[5]=( 10 )-__ARRAY_SINGLE_A[4]+1;
    '__ARRAY_SINGLE_A[6]=1;
    IF cmem AND stringarray = 0 THEN
        'Note: A string array's pointers are always stored in 64bit memory
        '(static)CONVENTINAL memory
        PRINT #13, n$ + "[0]=(ptrszint)cmem_static_pointer;"
        'alloc mem & check if static memory boundry has oversteped dynamic memory boundry
        PRINT #13, "if ((cmem_static_pointer+=((" + sizestr$ + ")+15)&-16)>cmem_dynamic_base) error(257);"
        '64K check
        PRINT #13, "if ((" + sizestr$ + ")>65536) error(257);"
        'clear array
        PRINT #13, "memset((void*)(" + n$ + "[0]),0," + sizestr$ + ");"
        'set flags
        PRINT #13, n$ + "[2]=1+2+4;" 'init+static+cmem
    ELSE
        '64BIT MEMORY
        PRINT #13, n$ + "[0]=(ptrszint)mem_static_malloc(" + sizestr$ + ");"
        IF stringarray THEN
            'Init string pointers in the array
            PRINT #13, "tmp_long=" + elesizestr$ + ";"
            PRINT #13, "while(tmp_long--){"
            IF cmem THEN
                PRINT #13, "((uint64*)(" + n$ + "[0]))[tmp_long]=(uint64)qbs_new_cmem(0,0);"
            ELSE
                PRINT #13, "((uint64*)(" + n$ + "[0]))[tmp_long]=(uint64)qbs_new(0,0);"
            END IF
            PRINT #13, "}"
        ELSE
            'clear array
            PRINT #13, "memset((void*)(" + n$ + "[0]),0," + sizestr$ + ");"
        END IF
        PRINT #13, n$ + "[2]=1+2;" 'init+static
    END IF
    'Close static array desc
    PRINT #13, "}"
    allocarray = nume + 65536
END IF
'------------------END OF STATIC ARRAY CREATION-------------------------

'------------------DYNAMIC ARRAY CREATION-------------------------------
IF staticarray = 0 THEN

    IF undefined = 0 THEN



        'Generate error if array is static
        f12$ = f12$ + crlf + "if (" + n$ + "[2]&2){" 'static array
        f12$ = f12$ + crlf + "error(10);" 'cannot redefine a static array!
        f12$ = f12$ + crlf + "}else{"
        'Note: Array is either undefined or dynamically defined at this point


        'REDIM (not DIM) must be used to redefine an array
        IF redimoption = 0 THEN
            f12$ = f12$ + crlf + "if (" + n$ + "[2]&1){" 'array is defined
            f12$ = f12$ + crlf + "error(10);" 'cannot redefine an array without using REDIM!
            f12$ = f12$ + crlf + "}else{"
        ELSE
            '--------ERASE EXISTING ARRAY IF NECESSARY--------

            'IMPORTANT: If array is not going to be preserved, it should be cleared before
            '           creating the new array for memory considerations

            IF redimoption = 2 THEN
                f12$ = f12$ + crlf + "static int32 preserved_elements;" 'must be put here for scope considerations
            END IF

            'If array is defined, it must be destroyed first
            f12$ = f12$ + crlf + "if (" + n$ + "[2]&1){" 'array is defined

            IF redimoption = 2 THEN
                f12$ = f12$ + crlf + "preserved_elements=" + elesizestr$ + ";"
                GOTO skiperase
            END IF

            'Note: pointers to strings must be freed before array can be freed
            IF stringarray THEN
                f12$ = f12$ + crlf + "tmp_long=" + elesizestr$ + ";"
                f12$ = f12$ + crlf + "while(tmp_long--) qbs_free((qbs*)((uint64*)(" + n$ + "[0]))[tmp_long]);"
            END IF
            'Free array's memory
            IF stringarray THEN
                'Note: String arrays are never in cmem
                f12$ = f12$ + crlf + "free((void*)(" + n$ + "[0]));"
            ELSE
                'Note: Array may be in cmem!
                f12$ = f12$ + crlf + "if (" + n$ + "[2]&4){" 'array is in cmem
                f12$ = f12$ + crlf + "cmem_dynamic_free((uint8*)(" + n$ + "[0]));"
                f12$ = f12$ + crlf + "}else{" 'not in cmem
                f12$ = f12$ + crlf + "free((void*)(" + n$ + "[0]));"
                f12$ = f12$ + crlf + "}"
            END IF

            skiperase:

            f12$ = f12$ + crlf + "}" 'array was defined
            IF redimoption = 2 THEN
                f12$ = f12$ + crlf + "else preserved_elements=0;" 'if array wasn't defined, no elements are preserved
            END IF


            '--------ERASED ARRAY AS NECESSARY--------
        END IF 'redim specified


        '--------CREATE ARRAY & CLEAN-UP CODE--------
        'Overwrite existing array dimension sizes/ranges
        f12$ = f12$ + crlf + sd$
        IF stringarray THEN

            'Note: String arrays are always created in 64bit memory

            IF redimoption = 2 THEN
                f12$ = f12$ + crlf + "if (preserved_elements){"

                f12$ = f12$ + crlf + "static ptrszint tmp_long2;"

                'free any qbs strings which will be lost in the realloc
                f12$ = f12$ + crlf + "tmp_long=" + elesizestr$ + ";"
                f12$ = f12$ + crlf + "if (tmp_long<preserved_elements){"
                f12$ = f12$ + crlf + "for(tmp_long2=tmp_long;tmp_long2<preserved_elements;tmp_long2++) qbs_free((qbs*)((uint64*)(" + n$ + "[0]))[tmp_long2]);"
                f12$ = f12$ + crlf + "}"
                'reallocate the array
                f12$ = f12$ + crlf + n$ + "[0]=(ptrszint)realloc((void*)(" + n$ + "[0]),tmp_long*" + bytesperelement$ + ");"
                f12$ = f12$ + crlf + "if (!" + n$ + "[0]) error(257);" 'not enough memory
                f12$ = f12$ + crlf + "if (preserved_elements<tmp_long){"
                f12$ = f12$ + crlf + "for(tmp_long2=preserved_elements;tmp_long2<tmp_long;tmp_long2++){"
                f12$ = f12$ + crlf + "if (" + n$ + "[2]&4){" 'array is in cmem
                f12$ = f12$ + crlf + "((uint64*)(" + n$ + "[0]))[tmp_long2]=(uint64)qbs_new_cmem(0,0);"
                f12$ = f12$ + crlf + "}else{" 'not in cmem
                f12$ = f12$ + crlf + "((uint64*)(" + n$ + "[0]))[tmp_long2]=(uint64)qbs_new(0,0);"
                f12$ = f12$ + crlf + "}" 'not in cmem
                f12$ = f12$ + crlf + "}"
                f12$ = f12$ + crlf + "}"

                f12$ = f12$ + crlf + "}else{"
            END IF

            '1. Create string array
            f12$ = f12$ + crlf + n$ + "[0]=(ptrszint)malloc(" + sizestr$ + ");"
            f12$ = f12$ + crlf + "if (!" + n$ + "[0]) error(257);" 'not enough memory
            f12$ = f12$ + crlf + n$ + "[2]|=1;" 'ADD initialized flag
            f12$ = f12$ + crlf + "tmp_long=" + elesizestr$ + ";"


            'init individual strings
            f12$ = f12$ + crlf + "if (" + n$ + "[2]&4){" 'array is in cmem
            f12$ = f12$ + crlf + "while(tmp_long--) ((uint64*)(" + n$ + "[0]))[tmp_long]=(uint64)qbs_new_cmem(0,0);"
            f12$ = f12$ + crlf + "}else{" 'not in cmem
            f12$ = f12$ + crlf + "while(tmp_long--) ((uint64*)(" + n$ + "[0]))[tmp_long]=(uint64)qbs_new(0,0);"
            f12$ = f12$ + crlf + "}" 'not in cmem

            IF redimoption = 2 THEN
                f12$ = f12$ + crlf + "}"
            END IF


            '2. Generate "clean up" code (called when EXITING A SUB/FUNCTION)
            IF arraydesc = 0 THEN 'only add for first declaration of the array
                PRINT #19, "if (" + n$ + "[2]&1){" 'initialized?
                PRINT #19, "tmp_long=" + elesizestr$ + ";"
                PRINT #19, "while(tmp_long--) qbs_free((qbs*)((uint64*)(" + n$ + "[0]))[tmp_long]);"
                PRINT #19, "free((void*)(" + n$ + "[0]));"
                PRINT #19, "}"
            END IF


        ELSE 'not string array

            '1. Create array
            f12$ = f12$ + crlf + "if (" + n$ + "[2]&4){" 'array will be in cmem

            IF redimoption = 2 THEN
                f12$ = f12$ + crlf + "if (preserved_elements){"

                'reallocation method
                'backup data
                f12$ = f12$ + crlf + "memcpy(redim_preserve_cmem_buffer,(void*)(" + n$ + "[0]),preserved_elements*" + bytesperelement$ + ");"
                'free old array
                f12$ = f12$ + crlf + "cmem_dynamic_free((uint8*)(" + n$ + "[0]));"
                f12$ = f12$ + crlf + "tmp_long=" + elesizestr$ + ";"
                f12$ = f12$ + crlf + n$ + "[0]=(ptrszint)cmem_dynamic_malloc(tmp_long*" + bytesperelement$ + ");"
                f12$ = f12$ + crlf + "memcpy((void*)(" + n$ + "[0]),redim_preserve_cmem_buffer,preserved_elements*" + bytesperelement$ + ");"
                f12$ = f12$ + crlf + "if (preserved_elements<tmp_long) ZeroMemory(((uint8*)(" + n$ + "[0]))+preserved_elements*" + bytesperelement$ + ",(tmp_long*" + bytesperelement$+")-(preserved_elements*" + bytesperelement$ + "));"

                f12$ = f12$ + crlf + "}else{"
            END IF

            'standard cmem method
            f12$ = f12$ + crlf + n$ + "[0]=(ptrszint)cmem_dynamic_malloc(" + sizestr$ + ");"
            'clear array
            f12$ = f12$ + crlf + "memset((void*)(" + n$ + "[0]),0," + sizestr$ + ");"

            IF redimoption = 2 THEN
                f12$ = f12$ + crlf + "}"
            END IF


            f12$ = f12$ + crlf + "}else{" 'not in cmem

            IF redimoption = 2 THEN
                f12$ = f12$ + crlf + "if (preserved_elements){"
                'reallocation method
                f12$ = f12$ + crlf + "tmp_long=" + elesizestr$ + ";"
                f12$ = f12$ + crlf + n$ + "[0]=(ptrszint)realloc((void*)(" + n$ + "[0]),tmp_long*" + bytesperelement$ + ");"
                f12$ = f12$ + crlf + "if (!" + n$ + "[0]) error(257);" 'not enough memory
                f12$ = f12$ + crlf + "if (preserved_elements<tmp_long) ZeroMemory(((uint8*)(" + n$ + "[0]))+preserved_elements*" + bytesperelement$ + ",(tmp_long*" + bytesperelement$+")-(preserved_elements*" + bytesperelement$ + "));"

                f12$ = f12$ + crlf + "}else{"
            END IF
            'standard allocation method
            f12$ = f12$ + crlf + n$ + "[0]=(ptrszint)calloc(" + sizestr$ + ",1);"
            f12$ = f12$ + crlf + "if (!" + n$ + "[0]) error(257);" 'not enough memory
            IF redimoption = 2 THEN
                f12$ = f12$ + crlf + "}"
            END IF

            f12$ = f12$ + crlf + "}" 'not in cmem
            f12$ = f12$ + crlf + n$ + "[2]|=1;" 'ADD initialized flag

            '2. Generate "clean up" code (called when EXITING A SUB/FUNCTION)
            IF arraydesc = 0 THEN 'only add for first declaration of the array
                PRINT #19, "if (" + n$ + "[2]&1){" 'initialized?
                PRINT #19, "if (" + n$ + "[2]&4){" 'array is in cmem
                PRINT #19, "cmem_dynamic_free((uint8*)(" + n$ + "[0]));"
                PRINT #19, "}else{"
                PRINT #19, "free((void*)(" + n$ + "[0]));"
                PRINT #19, "}" 'cmem
                PRINT #19, "}" 'init
            END IF
        END IF 'not string array

    END IF 'undefined=0

    '----FINISH ARRAY DESCRIPTOR IF DEFINING FOR THE FIRST TIME----
    IF arraydesc = 0 THEN
        'Note: Array is init as undefined (& possibly a cmem flag)
        IF cmem THEN PRINT #13, n$ + "[2]=4;" ELSE PRINT #13, n$ + "[2]=0;"
        'set dimensions as undefined
        FOR i = 1 TO nume
            b = i * 4
            PRINT #13, n$ + "[" + str2(b) + "]=2147483647;" 'base
            PRINT #13, n$ + "[" + str2(b + 1) + "]=0;" 'num. index
            PRINT #13, n$ + "[" + str2(b + 2) + "]=0;" 'multiplier
        NEXT
        IF stringarray THEN
            'set array's data offset to the offset of the offset to nothingstring
            PRINT #13, n$ + "[0]=(ptrszint)&nothingstring;"
        ELSE
            'set array's data offset to "nothing"
            PRINT #13, n$ + "[0]=(ptrszint)nothingvalue;"
        END IF
        PRINT #13, "}" 'close array descriptor
    END IF 'arraydesc = 0

    IF undefined = 0 THEN

        IF redimoption = 0 THEN f12$ = f12$ + crlf + "}" 'if REDIM not specified the above is conditional
        f12$ = f12$ + crlf + "}" 'not static

    END IF 'undefined=0

    allocarray = nume
    IF undefined = -1 THEN allocarray = -1

END IF

IF autoary = 0 THEN PRINT #12, f12$

'[8] offset of data
'[8] reserved (could be used to store a bit offset)
'(the following repeats depending on the number of elements)
'[4] base-offset
'[4] number of indexes
'[4] multiplier (the last multiplier doesn't actually exist)
'[4] reserved

dimshared = dimsharedlast

tlayout$ = l$
END FUNCTION

FUNCTION arrayreference$ (indexes$, typ)
arrayprocessinghappened = 1
'*returns an array reference: idnumber³index$
'*does not take into consideration the type of the array
'*expects array id to be passed in the global id structure





idnumber$ = str2(currentid)

DIM id2 AS idstruct

id2 = id

a$ = indexes$
typ = id2.arraytype + ISARRAY + ISREFERENCE
n$ = RTRIM$(id2.callname)

IF a$ = "" THEN 'no indexes passed eg. a()
    r$ = "0"
    GOTO gotarrayindex
END IF

n = numelements(a$)

'find number of elements supplied
elements = 1
b = 0
FOR i = 1 TO n
    a = ASC(getelement(a$, i))
    IF a = 40 THEN b = b + 1
    IF a = 41 THEN b = b - 1
    IF a = 44 AND b = 0 THEN elements = elements + 1
NEXT

IF id2.arrayelements = -1 THEN
    IF arrayelementslist(currentid) <> 0 AND elements <> arrayelementslist(currentid) THEN nerror (85)
    IF elements = 1 THEN id2.arrayelements = 1: ids(currentid).arrayelements = 1 'lucky guess
    arrayelementslist(currentid) = elements
ELSE
    IF elements <> id2.arrayelements THEN nerror (85)
END IF

curarg = 1
firsti = 1
FOR i = 1 TO n
    l$ = getelement(a$, i)
    IF l$ = "(" THEN b = b + 1
    IF l$ = ")" THEN b = b - 1
    IF (l$ = "," AND b = 0) OR (i = n) THEN
        IF i = n THEN
            e$ = evaluatetotyp(getelements$(a$, firsti, i), 64&)
        ELSE
            e$ = evaluatetotyp(getelements$(a$, firsti, i - 1), 64&)
        END IF
        argi = (elements - curarg) * 4 + 4
        IF curarg = 1 THEN
            r$ = r$ + "array_check((" + e$ + ")-" + n$ + "[" + str2(argi) + "]," + n$ + "[" + str2(argi + 1) + "])+"
        ELSE
            r$ = r$ + "array_check((" + e$ + ")-" + n$ + "[" + str2(argi) + "]," + n$ + "[" + str2(argi + 1) + "])*" + n$ + "[" + str2(argi + 2) + "]+"
        END IF
        firsti = i + 1
        curarg = curarg + 1
    END IF
NEXT
r$ = LEFT$(r$, LEN(r$) - 1) 'remove trailing +
gotarrayindex:

r$ = idnumber$ + "³" + r$
arrayreference$ = r$
'PRINT "arrayreference returning:" + r$

END FUNCTION

SUB assign (a$, n)
FOR i = 1 TO n
    c = ASC(getelement$(a$, i))
    IF c = 40 THEN b = b + 1 '(
    IF c = 41 THEN b = b - 1 ')
    IF c = 61 AND b = 0 THEN '=
        IF i = 1 THEN qb64error "Expected ... ="
        IF i = n THEN qb64error "Expected = ..."

        a2$ = fixoperationorder(getelements$(a$, 1, i - 1))
        l$ = tlayout$ + sp + "=" + sp

        'note: evaluating a2$ will fail if it is setting a function's return value without this check (as the function, not the return-variable) will be found by evaluate)
        IF i = 2 THEN 'lhs has only 1 element
            try = findid(a2$)
            DO WHILE try
                IF id.t THEN
                    IF (id.t AND ISUDT) = 0 THEN
                        makeidrefer a2$, typ
                        GOTO assignsimplevariable
                    END IF
                END IF
                IF try = 2 THEN findanotherid = 1: try = findid(a2$) ELSE try = 0
            LOOP
        END IF

        a2$ = evaluate$(a2$, typ)
        assignsimplevariable:
        IF (typ AND ISREFERENCE) = 0 THEN qb64error "Expected variable ="
        setrefer a2$, typ, getelements$(a$, i + 1, n), 0
        tlayout$ = l$ + tlayout$

        EXIT SUB

    END IF '=,b=0
NEXT
qb64error "Expected ="
END SUB

SUB clearid
id = cleariddata
END SUB

SUB closemain
xend
PRINT #12, "return NULL;"

PRINT #12, "}"
PRINT #15, "}" 'end case
PRINT #15, "}"
PRINT #15, "if(event_return)return NULL;"
PRINT #15, "error(3);" 'no valid return possible

closedmain = 1

END SUB

FUNCTION countelements (a$)
n = numelements(a$)
c = 1
FOR i = 1 TO n
    e$ = getelement$(a$, i)
    IF e$ = "(" THEN b = b + 1
    IF e$ = ")" THEN b = b - 1
    IF b < 0 THEN qb64error "Unexpected ) encountered"
    IF e$ = "," AND b = 0 THEN c = c + 1
NEXT
countelements = c
END FUNCTION



FUNCTION dim2 (varname$, typ2$, method, elements$)

'notes: (DO NOT REMOVE THESE IMPORTANT USAGE NOTES)
'
'(shared)dimsfarray: Creates an ID only (no C++ code)
'                    Adds an index/'link' to the sub/function's argument
'                        ID.sfid=glinkid
'                        ID.sfarg=glinkarg
'                    Sets arrayelements=-1 'unknown' (if elements$="?") otherwise val(elements$)
'                    ***Does not refer to arrayelementslist()***
'
'(argument)method: 0 being created by a DIM name AS type
'                  1 being created by a DIM name+symbol
'                  or automatically without the use of DIM
'
'elements$="?": (see also dimsfarray for that special case)
'               Checks arrayelementslist() and;
'               if unknown(=0), creates an ID only
'               if known, creates a DYNAMIC array's C++ initialization code so it can be used later






typ$ = typ2$
dim2 = 1 'success

IF debug THEN PRINT #9, "dim2 called"

cvarname$ = varname$
l$ = cvarname$
varname$ = UCASE$(varname$)

IF dimsfarray = 1 THEN f = 0 ELSE f = 1

IF dimstatic <> 0 AND dimshared = 0 THEN
    'name will have include the sub/func name in its scope
    'variable/array will be created in main on startup
    defdatahandle = 18 'change from 13 to 18(global.txt)
    CLOSE #13: OPEN tmpdir$ + "maindata.txt" FOR APPEND AS #13
    CLOSE #19: OPEN tmpdir$ + "mainfree.txt" FOR APPEND AS #19
END IF


scope2$ = module$ + "_" + subfunc$ + "_"
'Note: when REDIMing a SHARED array in dynamic memory scope2$ must be modified

IF LEN(typ$) = 0 THEN nerror (102)

'UDT
'is it a udt?
FOR i = 1 TO lasttype
    IF typ$ = RTRIM$(udtxname(i)) THEN
        dim2typepassback$ = RTRIM$(udtxcname(i))

        n$ = "UDT_" + varname$

        'array of UDTs
        IF elements$ <> "" THEN
            arraydesc = 0
            IF f = 1 THEN
                try = findid(varname$)
                DO WHILE try
                    IF (id.arraytype) THEN
                        l$ = RTRIM$(id.cn)
                        arraydesc = currentid: scope2$ = scope$
                        EXIT DO
                    END IF
                    IF try = 2 THEN findanotherid = 1: try = findid(varname$) ELSE try = 0
                LOOP
            END IF
            n$ = scope2$ + "ARRAY_" + n$
            bits = udtxsize(i)
            IF udtxbytealign(i) THEN
                IF bits MOD 8 THEN bits = bits + 8 - (bits MOD 8)
            END IF

            IF f = 1 THEN

                IF LEN(elements$) = 1 AND ASC(elements$) = 63 THEN '"?"
                    e = arrayelementslist(idn + 1): IF e THEN elements$ = elements$ + str2$(e) 'eg. "?3" for a 3 dimensional array
                END IF
                nume = allocarray(n$, elements$, -bits)
                l$ = l$ + sp + tlayout$
                IF arraydesc THEN GOTO dim2exitfunc
                clearid

            ELSE
                clearid
                IF elements$ = "?" THEN
                    nume = -1
                    id.linkid = glinkid
                    id.linkarg = glinkarg
                ELSE
                    nume = VAL(elements$)
                END IF
            END IF

            id.arraytype = ISUDT + i
            IF cmemlist(idn + 1) THEN id.arraytype = id.arraytype + ISINCONVENTIONALMEMORY
            id.n = cvarname$

            IF nume > 65536 THEN nume = nume - 65536: id.staticarray = 1

            id.arrayelements = nume
            id.callname = n$
            regid
            GOTO dim2exitfunc
        END IF

        'not an array of UDTs
        bits = udtxsize(i): bytes = bits \ 8
        IF bits MOD 8 THEN
            bytes = bytes + 1
        END IF
        n$ = scope2$ + n$
        IF f THEN PRINT #defdatahandle, "void *" + n$ + "=NULL;"
        clearid
        id.n = cvarname$
        id.t = ISUDT + i
        IF cmemlist(idn + 1) THEN
            id.t = id.t + ISINCONVENTIONALMEMORY
            IF f THEN PRINT #13, "if(" + n$ + "==NULL){"
            IF f THEN PRINT #13, "cmem_sp-=" + str2(bytes) + ";"
            IF f THEN PRINT #13, "if (cmem_sp<qbs_cmem_sp) error(257);"
            IF f THEN PRINT #13, n$ + "=(void*)(dblock+cmem_sp);"
            IF f THEN PRINT #13, "memset(" + n$ + ",0," + str2(bytes) + ");"
            IF f THEN PRINT #13, "}"
        ELSE
            IF f THEN PRINT #13, "if(" + n$ + "==NULL){"
            IF f THEN PRINT #13, n$ + "=(void*)mem_static_malloc(" + str2$(bytes) + ");"
            IF f THEN PRINT #13, "memset(" + n$ + ",0," + str2(bytes) + ");"
            IF f THEN PRINT #13, "}"
        END IF
        regid
        GOTO dim2exitfunc
    END IF
NEXT i
'it isn't a udt

typ$ = symbol2fulltypename$(typ$)

'check if _UNSIGNED was specified
unsgn = 0
IF LEFT$(typ$, 10) = "_UNSIGNED " THEN
    unsgn = 1
    typ$ = RIGHT$(typ$, LEN(typ$) - 10)
    IF LEN(typ$) = 0 THEN nerror (108)
END IF

n$ = "" 'n$ is assumed to be "" after branching into the code for each type

IF LEFT$(typ$, 6) = "STRING" THEN

    IF LEN(typ$) > 6 THEN
        IF LEFT$(typ$, 9) <> "STRING * " THEN nerror (109)

        c$ = RIGHT$(typ$, LEN(typ$) - 9)
        IF isuinteger(c$) = 0 THEN nerror (110)
        IF LEN(c$) > 10 THEN nerror (111)
        bytes = VAL(c$)
        IF bytes = 0 THEN nerror (112)
        n$ = "STRING" + str2(bytes) + "_" + varname$

        'array of fixed length strings
        IF elements$ <> "" THEN
            arraydesc = 0
            IF f = 1 THEN
                try = findid(varname$ + "$")
                DO WHILE try
                    IF (id.arraytype) THEN
                        l$ = RTRIM$(id.cn)
                        arraydesc = currentid: scope2$ = scope$
                        EXIT DO
                    END IF
                    IF try = 2 THEN findanotherid = 1: try = findid(varname$ + "$") ELSE try = 0
                LOOP
            END IF
            n$ = scope2$ + "ARRAY_" + n$

            'nume = allocarray(n$, elements$, bytes)
            'IF arraydesc THEN goto dim2exitfunc 'id already exists!
            'clearid

            IF f = 1 THEN

                IF LEN(elements$) = 1 AND ASC(elements$) = 63 THEN '"?"
                    e = arrayelementslist(idn + 1): IF e THEN elements$ = elements$ + str2$(e) 'eg. "?3" for a 3 dimensional array
                END IF
                nume = allocarray(n$, elements$, bytes)
                l$ = l$ + sp + tlayout$
                IF arraydesc THEN GOTO dim2exitfunc
                clearid

            ELSE
                clearid
                IF elements$ = "?" THEN
                    nume = -1
                    id.linkid = glinkid
                    id.linkarg = glinkarg
                ELSE
                    nume = VAL(elements$)
                END IF
            END IF

            id.arraytype = STRINGTYPE + ISFIXEDLENGTH
            IF cmemlist(idn + 1) THEN id.arraytype = id.arraytype + ISINCONVENTIONALMEMORY
            id.n = cvarname$
            IF nume > 65536 THEN nume = nume - 65536: id.staticarray = 1

            id.arrayelements = nume
            id.callname = n$
            id.tsize = bytes
            IF method = 0 THEN
                id.mayhave = "$" + str2(bytes)
            END IF
            IF method = 1 THEN
                id.musthave = "$" + str2(bytes)
            END IF
            regid
            GOTO dim2exitfunc
        END IF

        'standard fixed length string
        n$ = scope2$ + n$
        IF f THEN PRINT #defdatahandle, "qbs *" + n$ + "=NULL;"
        IF f THEN PRINT #19, "qbs_free(" + n$ + ");" 'so descriptor can be freed
        clearid
        id.n = cvarname$
        id.t = STRINGTYPE + ISFIXEDLENGTH
        IF cmemlist(idn + 1) THEN
            id.t = id.t + ISINCONVENTIONALMEMORY
            IF f THEN PRINT #13, "if(" + n$ + "==NULL){"
            IF f THEN PRINT #13, "cmem_sp-=" + str2(bytes) + ";"
            IF f THEN PRINT #13, "if (cmem_sp<qbs_cmem_sp) error(257);"
            IF f THEN PRINT #13, n$ + "=qbs_new_fixed((uint8*)(dblock+cmem_sp)," + str2(bytes) + ",0);"
            IF f THEN PRINT #13, "memset(" + n$ + "->chr,0," + str2(bytes) + ");"
            IF f THEN PRINT #13, "}"
        ELSE
            IF f THEN PRINT #13, "if(" + n$ + "==NULL){"
            o$ = "(uint8*)mem_static_malloc(" + str2$(bytes) + ")"
            IF f THEN PRINT #13, n$ + "=qbs_new_fixed(" + o$ + "," + str2$(bytes) + ",0);"
            IF f THEN PRINT #13, "memset(" + n$ + "->chr,0," + str2$(bytes) + ");"
            IF f THEN PRINT #13, "}"
        END IF
        id.tsize = bytes
        IF method = 0 THEN
            id.mayhave = "$" + str2(bytes)
        END IF
        IF method = 1 THEN
            id.musthave = "$" + str2(bytes)
        END IF
        regid
        GOTO dim2exitfunc
    END IF

    'variable length string processing
    n$ = "STRING_" + varname$

    'array of variable length strings
    IF elements$ <> "" THEN
        arraydesc = 0
        IF f = 1 THEN
            try = findid(varname$ + "$")
            DO WHILE try
                IF (id.arraytype) THEN
                    l$ = RTRIM$(id.cn)
                    arraydesc = currentid: scope2$ = scope$
                    EXIT DO
                END IF
                IF try = 2 THEN findanotherid = 1: try = findid(varname$ + "$") ELSE try = 0
            LOOP
        END IF
        n$ = scope2$ + "ARRAY_" + n$

        'nume = allocarray(n$, elements$, -2147483647) '-2147483647=STRING
        'IF arraydesc THEN goto dim2exitfunc 'id already exists!
        'clearid

        IF f = 1 THEN

            IF LEN(elements$) = 1 AND ASC(elements$) = 63 THEN '"?"
                e = arrayelementslist(idn + 1): IF e THEN elements$ = elements$ + str2$(e) 'eg. "?3" for a 3 dimensional array
            END IF
            nume = allocarray(n$, elements$, -2147483647)
            l$ = l$ + sp + tlayout$
            IF arraydesc THEN GOTO dim2exitfunc
            clearid

        ELSE
            clearid
            IF elements$ = "?" THEN
                nume = -1
                id.linkid = glinkid
                id.linkarg = glinkarg
            ELSE
                nume = VAL(elements$)
            END IF
        END IF

        id.n = cvarname$
        id.arraytype = STRINGTYPE
        IF cmemlist(idn + 1) THEN id.arraytype = id.arraytype + ISINCONVENTIONALMEMORY
        IF nume > 65536 THEN nume = nume - 65536: id.staticarray = 1

        id.arrayelements = nume
        id.callname = n$
        IF method = 0 THEN
            id.mayhave = "$"
        END IF
        IF method = 1 THEN
            id.musthave = "$"
        END IF
        regid
        GOTO dim2exitfunc
    END IF

    'standard variable length string
    n$ = scope2$ + n$
    clearid
    id.n = cvarname$
    id.t = STRINGTYPE
    IF cmemlist(idn + 1) THEN
        IF f THEN PRINT #defdatahandle, "qbs *" + n$ + "=NULL;"
        IF f THEN PRINT #13, "if (!" + n$ + ")" + n$ + "=qbs_new_cmem(0,0);"
        id.t = id.t + ISINCONVENTIONALMEMORY
    ELSE
        IF f THEN PRINT #defdatahandle, "qbs *" + n$ + "=NULL;"
        IF f THEN PRINT #13, "if (!" + n$ + ")" + n$ + "=qbs_new(0,0);"
    END IF
    IF f THEN PRINT #19, "qbs_free(" + n$ + ");"
    IF method = 0 THEN
        id.mayhave = "$"
    END IF
    IF method = 1 THEN
        id.musthave = "$"
    END IF
    regid
    GOTO dim2exitfunc
END IF

IF LEFT$(typ$, 4) = "_BIT" THEN
    IF LEN(typ$) > 4 THEN
        IF LEFT$(typ$, 7) <> "_BIT * " THEN nerror (113)
        c$ = RIGHT$(typ$, LEN(typ$) - 7)
        IF isuinteger(c$) = 0 THEN nerror (114)
        IF LEN(c$) > 2 THEN nerror (115)
        bits = VAL(c$)
        IF bits = 0 THEN nerror (116)
        IF bits > 57 THEN nerror (117)
    ELSE
        bits = 1
    END IF
    IF bits <= 32 THEN ct$ = "int32" ELSE ct$ = "int64"
    IF unsgn THEN n$ = "U": ct$ = "u" + ct$
    n$ = n$ + "BIT" + str2(bits) + "_" + varname$

    'array of bit-length variables
    IF elements$ <> "" THEN
        arraydesc = 0
        cmps$ = varname$: IF unsgn THEN cmps$ = cmps$ + "~"
        cmps$ = cmps$ + "`" + str2(bits)
        IF f = 1 THEN
            try = findid(cmps$)
            DO WHILE try
                IF (id.arraytype) THEN
                    l$ = RTRIM$(id.cn)
                    arraydesc = currentid: scope2$ = scope$
                    EXIT DO
                END IF
                IF try = 2 THEN findanotherid = 1: try = findid(cmps$) ELSE try = 0
            LOOP
        END IF
        n$ = scope2$ + "ARRAY_" + n$

        'nume = allocarray(n$, elements$, -bits) 'passing a negative element size signifies bits not bytes
        'IF arraydesc THEN goto dim2exitfunc 'id already exists!
        'clearid

        IF f = 1 THEN

            IF LEN(elements$) = 1 AND ASC(elements$) = 63 THEN '"?"
                e = arrayelementslist(idn + 1): IF e THEN elements$ = elements$ + str2$(e) 'eg. "?3" for a 3 dimensional array
            END IF
            nume = allocarray(n$, elements$, -bits)
            l$ = l$ + sp + tlayout$
            IF arraydesc THEN GOTO dim2exitfunc
            clearid

        ELSE
            clearid
            IF elements$ = "?" THEN
                nume = -1
                id.linkid = glinkid
                id.linkarg = glinkarg
            ELSE
                nume = VAL(elements$)
            END IF
        END IF

        id.n = cvarname$
        id.arraytype = BITTYPE - 1 + bits
        IF unsgn THEN id.arraytype = id.arraytype + ISUNSIGNED
        IF cmemlist(idn + 1) THEN id.arraytype = id.arraytype + ISINCONVENTIONALMEMORY
        IF nume > 65536 THEN nume = nume - 65536: id.staticarray = 1

        id.arrayelements = nume
        id.callname = n$
        IF method = 0 THEN
            IF unsgn THEN id.mayhave = "~`" + str2(bits) ELSE id.mayhave = "`" + str2(bits)
        END IF
        IF method = 1 THEN
            IF unsgn THEN id.musthave = "~`" + str2(bits) ELSE id.musthave = "`" + str2(bits)
        END IF
        regid
        GOTO dim2exitfunc
    END IF
    'standard bit-length variable
    n$ = scope2$ + n$
    PRINT #defdatahandle, ct$ + " *" + n$ + "=NULL;"
    PRINT #13, "if(" + n$ + "==NULL){"
    PRINT #13, "cmem_sp-=4;"
    PRINT #13, "if (cmem_sp<qbs_cmem_sp) error(257);"
    PRINT #13, n$ + "=(" + ct$ + "*)(dblock+cmem_sp);"
    PRINT #13, "*" + n$ + "=0;"
    PRINT #13, "}"
    clearid
    id.n = cvarname$
    id.t = BITTYPE - 1 + bits + ISINCONVENTIONALMEMORY: IF unsgn THEN id.t = id.t + ISUNSIGNED
    IF method = 0 THEN
        IF unsgn THEN id.mayhave = "~`" + str2(bits) ELSE id.mayhave = "`" + str2(bits)
    END IF
    IF method = 1 THEN
        IF unsgn THEN id.musthave = "~`" + str2(bits) ELSE id.musthave = "`" + str2(bits)
    END IF
    regid
    GOTO dim2exitfunc
END IF

IF typ$ = "_BYTE" THEN
    ct$ = "int8"
    IF unsgn THEN n$ = "U": ct$ = "u" + ct$
    n$ = n$ + "BYTE_" + varname$
    IF elements$ <> "" THEN
        arraydesc = 0
        cmps$ = varname$: IF unsgn THEN cmps$ = cmps$ + "~"
        cmps$ = cmps$ + "%%"
        IF f = 1 THEN
            try = findid(cmps$)
            DO WHILE try
                IF (id.arraytype) THEN
                    l$ = RTRIM$(id.cn)
                    arraydesc = currentid: scope2$ = scope$
                    EXIT DO
                END IF
                IF try = 2 THEN findanotherid = 1: try = findid(cmps$) ELSE try = 0
            LOOP
        END IF
        n$ = scope2$ + "ARRAY_" + n$

        'nume = allocarray(n$, elements$, 1)
        'IF arraydesc THEN goto dim2exitfunc
        'clearid

        IF f = 1 THEN

            IF LEN(elements$) = 1 AND ASC(elements$) = 63 THEN '"?"
                e = arrayelementslist(idn + 1): IF e THEN elements$ = elements$ + str2$(e) 'eg. "?3" for a 3 dimensional array
            END IF
            nume = allocarray(n$, elements$, 1)
            l$ = l$ + sp + tlayout$
            IF arraydesc THEN GOTO dim2exitfunc
            clearid

        ELSE
            clearid
            IF elements$ = "?" THEN
                nume = -1
                id.linkid = glinkid
                id.linkarg = glinkarg
            ELSE
                nume = VAL(elements$)
            END IF
        END IF

        id.arraytype = BYTETYPE: IF unsgn THEN id.arraytype = id.arraytype + ISUNSIGNED
        IF cmemlist(idn + 1) THEN id.arraytype = id.arraytype + ISINCONVENTIONALMEMORY
        IF nume > 65536 THEN nume = nume - 65536: id.staticarray = 1

        id.arrayelements = nume
        id.callname = n$
    ELSE
        n$ = scope2$ + n$
        clearid
        id.t = BYTETYPE: IF unsgn THEN id.t = id.t + ISUNSIGNED
        IF f = 1 THEN PRINT #defdatahandle, ct$ + " *" + n$ + "=NULL;"
        IF f = 1 THEN PRINT #13, "if(" + n$ + "==NULL){"
        IF cmemlist(idn + 1) THEN
            id.t = id.t + ISINCONVENTIONALMEMORY
            IF f = 1 THEN PRINT #13, "cmem_sp-=1;"
            IF f = 1 THEN PRINT #13, n$ + "=(" + ct$ + "*)(dblock+cmem_sp);"
            IF f = 1 THEN PRINT #13, "if (cmem_sp<qbs_cmem_sp) error(257);"
        ELSE
            IF f = 1 THEN PRINT #13, n$ + "=(" + ct$ + "*)mem_static_malloc(1);"
        END IF
        IF f = 1 THEN PRINT #13, "*" + n$ + "=0;"
        IF f = 1 THEN PRINT #13, "}"
    END IF
    id.n = cvarname$
    IF method = 0 THEN
        IF unsgn THEN id.mayhave = "~%%" ELSE id.mayhave = "%%"
    END IF
    IF method = 1 THEN
        IF unsgn THEN id.musthave = "~%%" ELSE id.musthave = "%%"
    END IF
    regid
    GOTO dim2exitfunc
END IF

IF typ$ = "INTEGER" THEN
    ct$ = "int16"
    IF unsgn THEN n$ = "U": ct$ = "u" + ct$
    n$ = n$ + "INTEGER_" + varname$

    IF elements$ <> "" THEN
        arraydesc = 0
        cmps$ = varname$: IF unsgn THEN cmps$ = cmps$ + "~"
        cmps$ = cmps$ + "%"
        IF f = 1 THEN
            try = findid(cmps$)
            DO WHILE try
                IF (id.arraytype) THEN
                    l$ = RTRIM$(id.cn)
                    arraydesc = currentid: scope2$ = scope$
                    EXIT DO
                END IF
                IF try = 2 THEN findanotherid = 1: try = findid(cmps$) ELSE try = 0
            LOOP
        END IF
        n$ = scope2$ + "ARRAY_" + n$

        IF f = 1 THEN

            IF LEN(elements$) = 1 AND ASC(elements$) = 63 THEN '"?"
                e = arrayelementslist(idn + 1): IF e THEN elements$ = elements$ + str2$(e) 'eg. "?3" for a 3 dimensional array
            END IF
            nume = allocarray(n$, elements$, 2)
            l$ = l$ + sp + tlayout$
            IF arraydesc THEN GOTO dim2exitfunc
            clearid

        ELSE
            clearid
            IF elements$ = "?" THEN
                nume = -1
                id.linkid = glinkid
                id.linkarg = glinkarg
            ELSE
                nume = VAL(elements$)
            END IF
        END IF


        id.arraytype = INTEGERTYPE: IF unsgn THEN id.arraytype = id.arraytype + ISUNSIGNED
        IF cmemlist(idn + 1) THEN id.arraytype = id.arraytype + ISINCONVENTIONALMEMORY
        IF nume > 65536 THEN nume = nume - 65536: id.staticarray = 1

        id.arrayelements = nume
        id.callname = n$
    ELSE
        n$ = scope2$ + n$
        clearid
        id.t = INTEGERTYPE: IF unsgn THEN id.t = id.t + ISUNSIGNED
        IF f = 1 THEN PRINT #defdatahandle, ct$ + " *" + n$ + "=NULL;"
        IF f = 1 THEN PRINT #13, "if(" + n$ + "==NULL){"
        IF cmemlist(idn + 1) THEN
            id.t = id.t + ISINCONVENTIONALMEMORY
            IF f = 1 THEN PRINT #13, "cmem_sp-=2;"
            IF f = 1 THEN PRINT #13, n$ + "=(" + ct$ + "*)(dblock+cmem_sp);"
            IF f = 1 THEN PRINT #13, "if (cmem_sp<qbs_cmem_sp) error(257);"
        ELSE
            IF f = 1 THEN PRINT #13, n$ + "=(" + ct$ + "*)mem_static_malloc(2);"
        END IF
        IF f = 1 THEN PRINT #13, "*" + n$ + "=0;"
        IF f = 1 THEN PRINT #13, "}"
    END IF
    id.n = cvarname$
    IF method = 0 THEN
        IF unsgn THEN id.mayhave = "~%" ELSE id.mayhave = "%"
    END IF
    IF method = 1 THEN
        IF unsgn THEN id.musthave = "~%" ELSE id.musthave = "%"
    END IF
    regid
    GOTO dim2exitfunc
END IF

IF typ$ = "LONG" THEN
    ct$ = "int32"
    IF unsgn THEN n$ = "U": ct$ = "u" + ct$
    n$ = n$ + "LONG_" + varname$
    IF elements$ <> "" THEN
        arraydesc = 0
        cmps$ = varname$: IF unsgn THEN cmps$ = cmps$ + "~"
        cmps$ = cmps$ + "&"
        IF f = 1 THEN
            try = findid(cmps$)
            DO WHILE try
                IF (id.arraytype) THEN
                    l$ = RTRIM$(id.cn)
                    arraydesc = currentid: scope2$ = scope$
                    EXIT DO
                END IF
                IF try = 2 THEN findanotherid = 1: try = findid(cmps$) ELSE try = 0
            LOOP
        END IF
        n$ = scope2$ + "ARRAY_" + n$

        'nume = allocarray(n$, elements$, 4)
        'IF arraydesc THEN goto dim2exitfunc
        'clearid

        IF f = 1 THEN

            IF LEN(elements$) = 1 AND ASC(elements$) = 63 THEN '"?"
                e = arrayelementslist(idn + 1): IF e THEN elements$ = elements$ + str2$(e) 'eg. "?3" for a 3 dimensional array
            END IF
            nume = allocarray(n$, elements$, 4)
            l$ = l$ + sp + tlayout$
            IF arraydesc THEN GOTO dim2exitfunc
            clearid

        ELSE
            clearid
            IF elements$ = "?" THEN
                nume = -1
                id.linkid = glinkid
                id.linkarg = glinkarg
            ELSE
                nume = VAL(elements$)
            END IF
        END IF

        id.arraytype = LONGTYPE: IF unsgn THEN id.arraytype = id.arraytype + ISUNSIGNED
        IF cmemlist(idn + 1) THEN id.arraytype = id.arraytype + ISINCONVENTIONALMEMORY
        IF nume > 65536 THEN nume = nume - 65536: id.staticarray = 1

        id.arrayelements = nume
        id.callname = n$
    ELSE
        n$ = scope2$ + n$
        clearid
        id.t = LONGTYPE: IF unsgn THEN id.t = id.t + ISUNSIGNED
        IF f = 1 THEN PRINT #defdatahandle, ct$ + " *" + n$ + "=NULL;"
        IF f = 1 THEN PRINT #13, "if(" + n$ + "==NULL){"
        IF cmemlist(idn + 1) THEN
            id.t = id.t + ISINCONVENTIONALMEMORY
            IF f = 1 THEN PRINT #13, "cmem_sp-=4;"
            IF f = 1 THEN PRINT #13, n$ + "=(" + ct$ + "*)(dblock+cmem_sp);"
            IF f = 1 THEN PRINT #13, "if (cmem_sp<qbs_cmem_sp) error(257);"
        ELSE
            IF f = 1 THEN PRINT #13, n$ + "=(" + ct$ + "*)mem_static_malloc(4);"
        END IF
        IF f = 1 THEN PRINT #13, "*" + n$ + "=0;"
        IF f = 1 THEN PRINT #13, "}"
    END IF
    id.n = cvarname$
    IF method = 0 THEN
        IF unsgn THEN id.mayhave = "~&" ELSE id.mayhave = "&"
    END IF
    IF method = 1 THEN
        IF unsgn THEN id.musthave = "~&" ELSE id.musthave = "&"
    END IF
    regid
    GOTO dim2exitfunc
END IF

IF typ$ = "_INTEGER64" THEN
    ct$ = "int64"
    IF unsgn THEN n$ = "U": ct$ = "u" + ct$
    n$ = n$ + "INTEGER64_" + varname$
    IF elements$ <> "" THEN
        arraydesc = 0
        cmps$ = varname$: IF unsgn THEN cmps$ = cmps$ + "~"
        cmps$ = cmps$ + "&&"
        IF f = 1 THEN
            try = findid(cmps$)
            DO WHILE try
                IF (id.arraytype) THEN
                    l$ = RTRIM$(id.cn)
                    arraydesc = currentid: scope2$ = scope$
                    EXIT DO
                END IF
                IF try = 2 THEN findanotherid = 1: try = findid(cmps$) ELSE try = 0
            LOOP
        END IF
        n$ = scope2$ + "ARRAY_" + n$

        'nume = allocarray(n$, elements$, 8)
        'IF arraydesc THEN goto dim2exitfunc
        'clearid

        IF f = 1 THEN

            IF LEN(elements$) = 1 AND ASC(elements$) = 63 THEN '"?"
                e = arrayelementslist(idn + 1): IF e THEN elements$ = elements$ + str2$(e) 'eg. "?3" for a 3 dimensional array
            END IF
            nume = allocarray(n$, elements$, 8)
            l$ = l$ + sp + tlayout$
            IF arraydesc THEN GOTO dim2exitfunc
            clearid

        ELSE
            clearid
            IF elements$ = "?" THEN
                nume = -1
                id.linkid = glinkid
                id.linkarg = glinkarg
            ELSE
                nume = VAL(elements$)
            END IF
        END IF

        id.arraytype = INTEGER64TYPE: IF unsgn THEN id.arraytype = id.arraytype + ISUNSIGNED
        IF cmemlist(idn + 1) THEN id.arraytype = id.arraytype + ISINCONVENTIONALMEMORY
        IF nume > 65536 THEN nume = nume - 65536: id.staticarray = 1

        id.arrayelements = nume
        id.callname = n$
    ELSE
        n$ = scope2$ + n$
        clearid
        id.t = INTEGER64TYPE: IF unsgn THEN id.t = id.t + ISUNSIGNED
        IF f = 1 THEN PRINT #defdatahandle, ct$ + " *" + n$ + "=NULL;"
        IF f = 1 THEN PRINT #13, "if(" + n$ + "==NULL){"
        IF cmemlist(idn + 1) THEN
            id.t = id.t + ISINCONVENTIONALMEMORY
            IF f = 1 THEN PRINT #13, "cmem_sp-=8;"
            IF f = 1 THEN PRINT #13, n$ + "=(" + ct$ + "*)(dblock+cmem_sp);"
            IF f = 1 THEN PRINT #13, "if (cmem_sp<qbs_cmem_sp) error(257);"
        ELSE
            IF f = 1 THEN PRINT #13, n$ + "=(" + ct$ + "*)mem_static_malloc(8);"
        END IF
        IF f = 1 THEN PRINT #13, "*" + n$ + "=0;"
        IF f = 1 THEN PRINT #13, "}"
    END IF
    id.n = cvarname$
    IF method = 0 THEN
        IF unsgn THEN id.mayhave = "~&&" ELSE id.mayhave = "&&"
    END IF
    IF method = 1 THEN
        IF unsgn THEN id.musthave = "~&&" ELSE id.musthave = "&&"
    END IF
    regid
    GOTO dim2exitfunc
END IF

IF unsgn = 1 THEN nerror (118)

IF typ$ = "SINGLE" THEN
    ct$ = "float"
    n$ = n$ + "SINGLE_" + varname$
    IF elements$ <> "" THEN
        arraydesc = 0
        cmps$ = varname$ + "!"
        IF f = 1 THEN
            try = findid(cmps$)
            DO WHILE try
                IF (id.arraytype) THEN
                    l$ = RTRIM$(id.cn)
                    arraydesc = currentid: scope2$ = scope$
                    EXIT DO
                END IF
                IF try = 2 THEN findanotherid = 1: try = findid(cmps$) ELSE try = 0
            LOOP
        END IF
        n$ = scope2$ + "ARRAY_" + n$

        'nume = allocarray(n$, elements$, 4)
        'IF arraydesc THEN goto dim2exitfunc
        'clearid

        IF f = 1 THEN

            IF LEN(elements$) = 1 AND ASC(elements$) = 63 THEN '"?"
                e = arrayelementslist(idn + 1): IF e THEN elements$ = elements$ + str2$(e) 'eg. "?3" for a 3 dimensional array
            END IF
            nume = allocarray(n$, elements$, 4)
            l$ = l$ + sp + tlayout$
            IF arraydesc THEN GOTO dim2exitfunc
            clearid

        ELSE
            clearid
            IF elements$ = "?" THEN
                nume = -1
                id.linkid = glinkid
                id.linkarg = glinkarg
            ELSE
                nume = VAL(elements$)
            END IF
        END IF

        id.arraytype = SINGLETYPE
        IF cmemlist(idn + 1) THEN id.arraytype = id.arraytype + ISINCONVENTIONALMEMORY
        IF nume > 65536 THEN nume = nume - 65536: id.staticarray = 1

        id.arrayelements = nume
        id.callname = n$
    ELSE
        n$ = scope2$ + n$
        clearid
        id.t = SINGLETYPE
        IF f = 1 THEN PRINT #defdatahandle, ct$ + " *" + n$ + "=NULL;"
        IF f = 1 THEN PRINT #13, "if(" + n$ + "==NULL){"
        IF cmemlist(idn + 1) THEN
            id.t = id.t + ISINCONVENTIONALMEMORY
            IF f = 1 THEN PRINT #13, "cmem_sp-=4;"
            IF f = 1 THEN PRINT #13, n$ + "=(" + ct$ + "*)(dblock+cmem_sp);"
            IF f = 1 THEN PRINT #13, "if (cmem_sp<qbs_cmem_sp) error(257);"
        ELSE
            IF f = 1 THEN PRINT #13, n$ + "=(" + ct$ + "*)mem_static_malloc(4);"
        END IF
        IF f = 1 THEN PRINT #13, "*" + n$ + "=0;"
        IF f = 1 THEN PRINT #13, "}"
    END IF
    id.n = cvarname$
    IF method = 0 THEN
        id.mayhave = "!"
    END IF
    IF method = 1 THEN
        id.musthave = "!"
    END IF
    regid
    GOTO dim2exitfunc
END IF

IF typ$ = "DOUBLE" THEN
    ct$ = "double"
    n$ = n$ + "DOUBLE_" + varname$
    IF elements$ <> "" THEN
        arraydesc = 0
        cmps$ = varname$ + "#"
        IF f = 1 THEN
            try = findid(cmps$)
            DO WHILE try
                IF (id.arraytype) THEN
                    l$ = RTRIM$(id.cn)
                    arraydesc = currentid: scope2$ = scope$
                    EXIT DO
                END IF
                IF try = 2 THEN findanotherid = 1: try = findid(cmps$) ELSE try = 0
            LOOP
        END IF
        n$ = scope2$ + "ARRAY_" + n$

        'nume = allocarray(n$, elements$, 8)
        'IF arraydesc THEN goto dim2exitfunc
        'clearid

        IF f = 1 THEN

            IF LEN(elements$) = 1 AND ASC(elements$) = 63 THEN '"?"
                e = arrayelementslist(idn + 1): IF e THEN elements$ = elements$ + str2$(e) 'eg. "?3" for a 3 dimensional array
            END IF
            nume = allocarray(n$, elements$, 8)
            l$ = l$ + sp + tlayout$
            IF arraydesc THEN GOTO dim2exitfunc
            clearid

        ELSE
            clearid
            IF elements$ = "?" THEN
                nume = -1
                id.linkid = glinkid
                id.linkarg = glinkarg
            ELSE
                nume = VAL(elements$)
            END IF
        END IF

        id.arraytype = DOUBLETYPE
        IF cmemlist(idn + 1) THEN id.arraytype = id.arraytype + ISINCONVENTIONALMEMORY
        IF nume > 65536 THEN nume = nume - 65536: id.staticarray = 1

        id.arrayelements = nume
        id.callname = n$
    ELSE
        n$ = scope2$ + n$
        clearid
        id.t = DOUBLETYPE
        IF f = 1 THEN PRINT #defdatahandle, ct$ + " *" + n$ + "=NULL;"
        IF f = 1 THEN PRINT #13, "if(" + n$ + "==NULL){"
        IF cmemlist(idn + 1) THEN
            id.t = id.t + ISINCONVENTIONALMEMORY
            IF f = 1 THEN PRINT #13, "cmem_sp-=8;"
            IF f = 1 THEN PRINT #13, n$ + "=(" + ct$ + "*)(dblock+cmem_sp);"
            IF f = 1 THEN PRINT #13, "if (cmem_sp<qbs_cmem_sp) error(257);"
        ELSE
            IF f = 1 THEN PRINT #13, n$ + "=(" + ct$ + "*)mem_static_malloc(8);"
        END IF
        IF f = 1 THEN PRINT #13, "*" + n$ + "=0;"
        IF f = 1 THEN PRINT #13, "}"
    END IF
    id.n = cvarname$
    IF method = 0 THEN
        id.mayhave = "#"
    END IF
    IF method = 1 THEN
        id.musthave = "#"
    END IF
    regid
    GOTO dim2exitfunc
END IF

IF typ$ = "_FLOAT" THEN
    ct$ = "long double"
    n$ = n$ + "FLOAT_" + varname$
    IF elements$ <> "" THEN
        arraydesc = 0
        cmps$ = varname$ + "##"
        IF f = 1 THEN
            try = findid(cmps$)
            DO WHILE try
                IF (id.arraytype) THEN
                    l$ = RTRIM$(id.cn)
                    arraydesc = currentid: scope2$ = scope$
                    EXIT DO
                END IF
                IF try = 2 THEN findanotherid = 1: try = findid(cmps$) ELSE try = 0
            LOOP
        END IF
        n$ = scope2$ + "ARRAY_" + n$

        'nume = allocarray(n$, elements$, 32)
        'IF arraydesc THEN goto dim2exitfunc
        'clearid

        IF f = 1 THEN

            IF LEN(elements$) = 1 AND ASC(elements$) = 63 THEN '"?"
                e = arrayelementslist(idn + 1): IF e THEN elements$ = elements$ + str2$(e) 'eg. "?3" for a 3 dimensional array
            END IF
            nume = allocarray(n$, elements$, 32)
            l$ = l$ + sp + tlayout$
            IF arraydesc THEN GOTO dim2exitfunc
            clearid

        ELSE
            clearid
            IF elements$ = "?" THEN
                nume = -1
                id.linkid = glinkid
                id.linkarg = glinkarg
            ELSE
                nume = VAL(elements$)
            END IF
        END IF

        id.arraytype = FLOATTYPE
        IF cmemlist(idn + 1) THEN id.arraytype = id.arraytype + ISINCONVENTIONALMEMORY
        IF nume > 65536 THEN nume = nume - 65536: id.staticarray = 1

        id.arrayelements = nume
        id.callname = n$
    ELSE
        n$ = scope2$ + n$
        clearid
        id.t = FLOATTYPE
        IF f THEN PRINT #defdatahandle, ct$ + " *" + n$ + "=NULL;"
        IF f THEN PRINT #13, "if(" + n$ + "==NULL){"
        IF cmemlist(idn + 1) THEN
            id.t = id.t + ISINCONVENTIONALMEMORY
            IF f THEN PRINT #13, "cmem_sp-=32;"
            IF f THEN PRINT #13, n$ + "=(" + ct$ + "*)(dblock+cmem_sp);"
            IF f THEN PRINT #13, "if (cmem_sp<qbs_cmem_sp) error(257);"
        ELSE
            IF f THEN PRINT #13, n$ + "=(" + ct$ + "*)mem_static_malloc(32);"
        END IF
        IF f THEN PRINT #13, "*" + n$ + "=0;"
        IF f THEN PRINT #13, "}"
    END IF
    id.n = cvarname$
    IF method = 0 THEN
        id.mayhave = "##"
    END IF
    IF method = 1 THEN
        id.musthave = "##"
    END IF
    regid
    GOTO dim2exitfunc
END IF

nerror (119)
dim2exitfunc:

IF dimsfarray THEN
    ids(idn).sfid = glinkid
    ids(idn).sfarg = glinkarg
END IF

'restore STATIC state
IF dimstatic <> 0 AND dimshared = 0 THEN
    defdatahandle = 13
    CLOSE #13: OPEN tmpdir$ + "data" + str2$(subfuncn) + ".txt" FOR APPEND AS #13
    CLOSE #19: OPEN tmpdir$ + "free" + str2$(subfuncn) + ".txt" FOR APPEND AS #19
END IF

tlayout$ = l$

END FUNCTION


FUNCTION udtreference$ (o$, a$, typ AS LONG)
'UDT REFERENCE FORMAT
'idno|udtno|udtelementno|byteoffset
'     ^udt of the element, not of the id

obak$ = o$

'PRINT "called udtreference!"


r$ = str2$(currentid) + "³"


o = 0 'the fixed/known part of the offset

incmem = 0
IF id.t THEN
    u = id.t AND 511
    IF id.t AND ISINCONVENTIONALMEMORY THEN incmem = 1
ELSE
    u = id.arraytype AND 511
    IF id.arraytype AND ISINCONVENTIONALMEMORY THEN incmem = 1
END IF
e = 0

n = numelements(a$)
IF n = 0 THEN GOTO fulludt

i = 1
udtfindelenext:
IF getelement$(a$, i) <> "." THEN qb64error "Expected ."
i = i + 1
n$ = getelement$(a$, i)
nsym$ = removesymbol(n$): IF LEN(nsym$) THEN ntyp = typname2typ(nsym$): ntypsize = typname2typsize

IF n$ = "" THEN qb64error "Expected .elementname"
udtfindele:
IF e = 0 THEN e = udtxnext(u) ELSE e = udtenext(e)
IF e = 0 THEN qb64error "Element not defined"
n2$ = RTRIM$(udtename(e))
IF udtebytealign(e) THEN
    IF o MOD 8 THEN o = o + (8 - (o MOD 8))
END IF

IF n$ <> n2$ THEN
    'increment fixed offset
    o = o + udtesize(e)
    GOTO udtfindele
END IF

'check symbol after element's name (if given) is correct
IF LEN(nsym$) THEN

    IF udtetype(e) AND ISUDT THEN qb64error "Invalid symbol after user defined type"
    IF ntyp <> udtetype(e) OR ntypsize <> udtetypesize(e) THEN
        IF nsym$ = "$" AND ((udtetype(e) AND ISFIXEDLENGTH) <> 0) THEN GOTO correctsymbol
        qb64error "Incorrect symbol after element name"
    END IF
END IF
correctsymbol:

'Move into another UDT structure?
IF i <> n THEN
    IF (udtetype(e) AND ISUDT) = 0 THEN qb64error "Expected user defined type"
    u = udtetype(e) AND 511
    e = 0
    i = i + 1
    GOTO udtfindelenext
END IF

'Change e reference to u³0 reference?
IF udtetype(e) AND ISUDT THEN
    u = udtetype(e) AND 511
    e = 0
END IF

fulludt:

r$ = r$ + str2$(u) + "³" + str2$(e) + "³"

IF o MOD 8 THEN qb64error "QB64 cannot handle bit offsets within user defined types yet"
o = o \ 8

IF o$ <> "" THEN
    IF o <> 0 THEN 'dont add an unnecessary 0
        o$ = o$ + "+" + str2$(o)
    END IF
ELSE
    o$ = str2$(o)
END IF

r$ = r$ + o$

udtreference$ = r$
typ = udtetype(e) + ISUDT + ISREFERENCE

'full udt override:
IF e = 0 THEN
    typ = u + ISUDT + ISREFERENCE
END IF

IF obak$ <> "" THEN typ = typ + ISARRAY
IF incmem THEN typ = typ + ISINCONVENTIONALMEMORY

'print "UDTREF:"+r$+","+str2$(typ)

END FUNCTION

FUNCTION evaluate$ (a2$, typ AS LONG)
DIM block(1000) AS STRING
DIM evaledblock(1000) AS INTEGER
DIM blocktype(1000) AS LONG
'typ IS A RETURN VALUE
'''DIM cli(15) AS INTEGER
a$ = a2$
typ = -1

IF debug THEN PRINT #9, "evaluating:[" + a2$ + "]"






'''cl$ = classify(a$)

blockn = 0
n = numelements(a$)
b = 0 'bracketting level
FOR i = 1 TO n
    reevaluate:
    l$ = getelement(a$, i)
    IF i <> n THEN nextl$ = getelement(a$, i + 1) ELSE nextl$ = ""


    '''getclass cl$, i, cli()

    IF b = 0 THEN 'don't evaluate anything within brackets

        IF debug THEN PRINT #9, l$

        reattempt:

        try = findid(l$)
        DO WHILE try

            IF debug THEN PRINT #9, try



          

            IF id.t AND ISUDT THEN
                constequation = 0
                o$ = ""
                evaludt:
                b2 = 0
                i3 = i + 1
                FOR i2 = i3 TO n
                    e2$ = getelement(a$, i2)
                    IF e2$ = "(" THEN b2 = b2 + 1
                    IF b2 = 0 THEN
                        IF e2$ = ")" OR isoperator(e2$) THEN
                            i4 = i2 - 1
                            GOTO gotudt
                        END IF
                    END IF
                    IF e2$ = ")" THEN b2 = b2 - 1
                NEXT
                i4 = n
                gotudt:
                IF i4 < i3 THEN e$ = "" ELSE e$ = getelements$(a$, i3, i4)
                'PRINT "UDTREFERENCE:";l$; e$
                e$ = udtreference(o$, e$, typ2)
                i = i4
                blockn = blockn + 1
                block(blockn) = e$
                evaledblock(blockn) = 2
                blocktype(blockn) = typ2
                'is the following next necessary?
                'IF (typ2 AND ISSTRING) THEN stringprocessinghappened = 1
                GOTO evaled
            END IF

            'is l$ an array?
            IF nextl$ = "(" THEN
                IF id.arraytype THEN
                    arrayid = currentid
                    constequation = 0
                    i2 = i + 2
                    b2 = 0
                    evalnextele3:
                    l2$ = getelement(a$, i2)
                    IF l2$ = "(" THEN b2 = b2 + 1
                    IF l2$ = ")" THEN
                        b2 = b2 - 1
                        IF b2 = -1 THEN
                            c$ = arrayreference(getelements$(a$, i + 2, i2 - 1), typ2)
                            i = i2

                            'UDT
                            IF typ2 AND ISUDT THEN
                                'print "arrayref returned:"+c$
                                getid arrayid
                                o$ = RIGHT$(c$, LEN(c$) - INSTR(c$, "³"))
                                'change o$ to a byte offset if necessary
                                u = typ2 AND 511
                                s = udtxsize(u)
                                IF udtxbytealign(u) THEN
                                    IF s MOD 8 THEN s = s + (8 - (s MOD 8)) 'round up to nearest byte
                                    s = s \ 8
                                END IF
                                o$ = "(" + o$ + ")*" + str2$(s)
                                'print "calling evaludt with o$:"+o$
                                GOTO evaludt
                            END IF

                            GOTO evalednextele3
                        END IF
                    END IF
                    i2 = i2 + 1
                    GOTO evalnextele3
                    evalednextele3:
                    blockn = blockn + 1
                    block(blockn) = c$
                    evaledblock(blockn) = 2
                    blocktype(blockn) = typ2
                    IF (typ2 AND ISSTRING) THEN stringprocessinghappened = 1
                    GOTO evaled
                END IF
            END IF
            'no, it's not an array

            'is l$ a function?
            IF id.subfunc = 1 THEN
                constequation = 0
                IF getelement(a$, i + 1) = "(" THEN
                    i2 = i + 2
                    b2 = 0
                    args = 1
                    evalnextele:
                    l2$ = getelement(a$, i2)
                    IF l2$ = "(" THEN b2 = b2 + 1
                    IF l2$ = ")" THEN
                        b2 = b2 - 1
                        IF b2 = -1 THEN
                            IF i2 = i + 2 THEN nerror (87)
                            c$ = evaluatefunc(getelements$(a$, i + 2, i2 - 1), args, typ2)
                            i = i2
                            GOTO evalednextele
                        END IF
                    END IF
                    IF l2$ = "," AND b2 = 0 THEN args = args + 1
                    i2 = i2 + 1
                    GOTO evalnextele
                ELSE
                    'no brackets
                    c$ = evaluatefunc("", 0, typ2)
                END IF
                evalednextele:
                blockn = blockn + 1
                block(blockn) = c$
                evaledblock(blockn) = 2
                blocktype(blockn) = typ2
                IF (typ2 AND ISSTRING) THEN stringprocessinghappened = 1
                GOTO evaled
            END IF
            'no, it's not a function

            IF try = 2 THEN findanotherid = 1: try = findid(l$) ELSE try = 0
        LOOP

        'is l$ an undefined array?
        IF i <> n THEN
            IF getelement$(a$, i + 1) = "(" THEN
                IF isoperator(l$) = 0 THEN
                    IF isvalidvariable(l$) THEN
                        dtyp$ = removesymbol(l$)

                        'if no extension was given, add a DEFault one and retry
                        IF dtyp$ = "" THEN
                            IF LEFT$(l$, 1) = "_" THEN v = 27 ELSE v = ASC(UCASE$(l$)) - 64
                            're-attempt array access with extension
                            l$ = l$ + defineextaz(v)
                            GOTO reattempt
                        END IF

                        'count the number of elements
                        nume = 1
                        b2 = 0
                        FOR i2 = i + 2 TO n
                            e$ = getelement(a$, i2)
                            IF e$ = "(" THEN b2 = b2 + 1
                            IF b2 = 0 AND e$ = "," THEN nume = nume + 1
                            IF e$ = ")" THEN b2 = b2 - 1
                            IF b2 = -1 THEN EXIT FOR
                        NEXT


                        fakee$ = "10": FOR i2 = 2 TO nume: fakee$ = fakee$ + sp + "," + sp + "10": NEXT
                        IF debug THEN PRINT #9, "evaluate:creating undefined array using dim2(" + l$ + "," + dtyp$ + ",0," + fakee$ + ")"

                        olddimstatic = dimstatic

                        IF subfuncn THEN
                            autoarray = 1 'move dimensioning of auto array to data???.txt from inline

                            'static array declared by STATIC name()?
                            'check if varname is on the static list
                            xi = 1
                            FOR x = 1 TO staticarraylistn
                                varname2$ = getelement$(staticarraylist, xi): xi = xi + 1
                                typ2$ = getelement$(staticarraylist, xi): xi = xi + 1
                                dimmethod2 = VAL(getelement$(staticarraylist, xi)): xi = xi + 1
                                'check if they are similar
                                IF UCASE$(l$) = UCASE$(varname2$) THEN
                                    IF symbol2fulltypename$(dtyp$) = typ2$ THEN
                                        IF dimmethod2 = 1 THEN 'has to have been informally defined, because DEF symbol was applied above
                                            'match found!
                                            l$ = varname2$
                                            dimstatic = 3
                                        END IF
                                    END IF 'typ
                                END IF 'varname
                            NEXT

                        END IF 'subfuncn

                        ignore = dim2(l$, dtyp$, 0, fakee$)

                        dimstatic = olddimstatic

                        GOTO reevaluate
                    END IF
                END IF
            END IF
        END IF

    END IF 'b=0

    IF l$ = "(" THEN
        IF b = 0 THEN i1 = i + 1
        b = b + 1
    END IF

    IF b = 0 THEN
        blockn = blockn + 1
        block(blockn) = l$
        evaledblock(blockn) = 0
    END IF

    IF l$ = ")" THEN
        b = b - 1
        IF b = 0 THEN
            c$ = evaluate(getelements$(a$, i1, i - 1), typ2)
            IF (typ2 AND ISSTRING) THEN stringprocessinghappened = 1
            blockn = blockn + 1
            IF (typ2 AND ISPOINTER) THEN
                block(blockn) = c$
            ELSE
                block(blockn) = "(" + c$ + ")"
            END IF
            evaledblock(blockn) = 1
            blocktype(blockn) = typ2
        END IF
    END IF

    evaled:
NEXT

r$ = "" 'return value

IF debug THEN PRINT #9, "evaluated blocks:";
FOR i = 1 TO blockn
    IF i <> blockn THEN
        IF debug THEN PRINT #9, block(i) + CHR$(219);
    ELSE
        IF debug THEN PRINT #9, block(i)
    END IF
NEXT



'identify any referencable values
FOR i = 1 TO blockn
    IF isoperator(block(i)) = 0 THEN
        IF evaledblock(i) = 0 THEN

            'a number?
            c = ASC(LEFT$(block(i), 1))
            IF c = 45 OR (c >= 48 AND c <= 57) THEN
                num$ = block(i)
                'a float?
                f = 0
                x = INSTR(num$, "E")
                IF x THEN
                    f = 1: blocktype(i) = SINGLETYPE - ISPOINTER
                ELSE
                    x = INSTR(num$, "D")
                    IF x THEN
                        f = 2: blocktype(i) = DOUBLETYPE - ISPOINTER
                    ELSE
                        x = INSTR(num$, "F")
                        IF x THEN
                            f = 3: blocktype(i) = FLOATTYPE - ISPOINTER
                        END IF
                    END IF
                END IF
                IF f THEN
                    'float
                    IF f = 2 OR f = 3 THEN MID$(num$, x, 1) = "E" 'D,F invalid in C++
                ELSE
                    'integer
                    blocktype(i) = typname2typ(removesymbol$(num$))
                    IF blocktype(i) AND ISPOINTER THEN blocktype(i) = blocktype(i) - ISPOINTER
                    IF (blocktype(i) AND 511) > 32 THEN
                        IF blocktype(i) AND ISUNSIGNED THEN num$ = num$ + "ull" ELSE num$ = num$ + "ll"
                    END IF
                END IF
                block(i) = " " + num$ + " " 'pad with spaces to avoid C++ computation errors
                evaledblock(i) = 1
                GOTO evaledblock
            END IF

            'number?
            'fc = ASC(LEFT$(block(i), 1))
            'IF fc = 45 OR (fc >= 48 AND fc <= 57) THEN '- or 0-9
            ''it's a number
            ''check for an extension, if none, assume integer
            'blocktype(i) = INTEGER64TYPE - ISPOINTER
            'tblock$ = " " + block(i)
            'IF RIGHT$(tblock$, 2) = "##" THEN blocktype(i) = FLOATTYPE - ISPOINTER: block(i) = LEFT$(block(i), LEN(block$(i)) - 2): GOTO evfltnum
            'IF RIGHT$(tblock$, 1) = "#" THEN blocktype(i) = DOUBLETYPE - ISPOINTER: block(i) = LEFT$(block(i), LEN(block$(i)) - 1): GOTO evfltnum
            'IF RIGHT$(tblock$, 1) = "!" THEN blocktype(i) = SINGLETYPE - ISPOINTER: block(i) = LEFT$(block(i), LEN(block$(i)) - 1): GOTO evfltnum
            '
            ''C++ 32bit unsigned to signed 64bit
            'IF INSTR(block(i),".")=0 THEN
            '
            'negated=0
            'if left$(block(i),1)="-" then block(i)=right$(block(i),len(block(i))-1):negated=1
            '
            'if left$(block(i),2)="0x" then 'hex
            'if len(block(i))=10 then
            'if block(i)>="0x80000000" and block(i)<="0xFFFFFFFF" then block(i)="(int64)"+block(i): goto evnum
            'end if
            'if len(block(i))>10 then block(i)=block(i)+"ll": goto evnum
            'goto evnum
            'end if
            '
            'if left$(block(i),1)="0" then 'octal
            'if len(block(i))=12 then
            'if block(i)>="020000000000" and block(i)<="037777777777" then block(i)="(int64)"+block(i): goto evnum
            'if block(i)>"037777777777" then block(i)=block(i)+"ll": goto evnum
            'end if
            'if len(block(i))>12 then block(i)=block(i)+"ll": goto evnum
            'goto evnum
            'end if
            '
            ''decimal
            'if len(block(i))=10 then
            'if block(i)>="2147483648" and block(i)<="4294967295" then block(i)="(int64)"+block(i): goto evnum
            'if block(i)>"4294967295" then block(i)=block(i)+"ll": goto evnum
            'end if
            'if len(block(i))>10 then block(i)=block(i)+"ll"
            '
            'evnum:
            '
            'if negated=1 then block(i)="-"+block(i)
            '
            'END IF
            '
            'evfltnum:
            '
            'block(i) = " " + block(i)+" "
            'evaledblock(i) = 1
            'GOTO evaledblock
            'END IF

            'a typed string in ""
            IF LEFT$(block(i), 1) = CHR$(34) THEN
                IF RIGHT$(block(i), 1) <> CHR$(34) THEN
                    block(i) = "qbs_new_txt_len(" + block(i) + ")"
                ELSE
                    block(i) = "qbs_new_txt(" + block(i) + ")"
                END IF
                blocktype(i) = ISSTRING
                evaledblock(i) = 1
                GOTO evaledblock
            END IF

            'variable?
            ignore = findvariable(block(i))
            constequation = 0
            'create a reference to that variable
            makeidrefer block(i), blocktype(i)
            IF blockn = 1 THEN
                IF (blocktype(i) AND ISREFERENCE) THEN GOTO returnpointer
            END IF
            'reference value
            block(i) = refer(block(i), blocktype(i), 0)
            evaledblock(i) = 1
            GOTO evaledblock

        ELSE
            IF (blocktype(i) AND ISREFERENCE) THEN
                IF blockn = 1 THEN GOTO returnpointer

                'if blocktype(i) and ISUDT then PRINT "UDT passed to refer by evaluate"

                block(i) = refer(block(i), blocktype(i), 0)

            END IF

        END IF
    END IF
    evaledblock:
NEXT


'return a POINTER if possible
IF blockn = 1 THEN
    IF evaledblock(1) THEN
        IF (blocktype(1) AND ISREFERENCE) THEN
            returnpointer:
            IF (blocktype(1) AND ISSTRING) THEN stringprocessinghappened = 1
            IF debug THEN PRINT #9, "evaluated reference:" + block(1)
            typ = blocktype(1)
            evaluate$ = block(1)
            EXIT FUNCTION
        END IF
    END IF
END IF
'it cannot be returned as a pointer








IF debug THEN PRINT #9, "applying operators:";


IF typ = -1 THEN
    typ = blocktype(1) 'init typ with first blocktype


    IF isoperator(block(1)) THEN 'but what if it starts with a UNARY operator?
        typ = blocktype(2) 'init typ with second blocktype
    END IF
END IF

nonop=0
FOR i = 1 TO blockn

    IF evaledblock(i) = 0 THEN
        isop=isoperator(block(i))
        IF isop THEN
            nonop=0

            constequation = 0

            'operator found
            o$ = block(i)
            u = operatorusage(o$, typ, i$, lhstyp, rhstyp, result)

            if u<>5 then 'not unary
            if i=1 or evaledblock(i-1)=0 then
            if i=1 and blockn=1 and o$="-" then qb64error "Expected variable/value after operator" 'guess - is neg in this case
            qb64error "Expected variable/value before operator"
            end if
            end if
            if i=blockn or evaledblock(i+1)=0 then qb64error "Expected variable/value after operator"

            'lhstyp & rhstyp bit-field values
            '1=integeral
            '2=floating point
            '4=string
            '8=bool *only used for result

            oldtyp = typ
            newtyp = blocktype(i + 1)

            'IF block(i - 1) = "6" THEN
            'PRINT o$
            'PRINT oldtyp AND ISFLOAT
            'PRINT blocktype(i - 1) AND ISFLOAT
            'END
            'END IF



            'numeric->string is illegal!
            IF (typ AND ISSTRING) = 0 AND (newtyp AND ISSTRING) <> 0 THEN
                nerror (88)
            END IF

            'STEP 1: convert oldtyp and/or newtyp if required for the operator
            'convert lhs
            IF (oldtyp AND ISSTRING) THEN
                IF (lhstyp AND 4) = 0 THEN nerror (89)
            ELSE
                'oldtyp is numeric
                IF lhstyp = 4 THEN nerror (90)
                IF (oldtyp AND ISFLOAT) THEN
                    IF (lhstyp AND 2) = 0 THEN
                        'convert float to int
                        block(i - 1) = "qbr(" + block(i - 1) + ")"
                        oldtyp = 64&
                    END IF
                ELSE
                    'oldtyp is an int
                    IF (lhstyp AND 1) = 0 THEN
                        'convert int to float
                        block(i - 1) = "((long double)(" + block(i - 1) + "))"
                        oldtyp = 256& + ISFLOAT
                    END IF
                END IF
            END IF
            'convert rhs
            IF (newtyp AND ISSTRING) THEN
                IF (rhstyp AND 4) = 0 THEN nerror (91)
            ELSE
                'newtyp is numeric
                IF rhstyp = 4 THEN nerror (92)
                IF (newtyp AND ISFLOAT) THEN
                    IF (rhstyp AND 2) = 0 THEN
                        'convert float to int
                        block(i + 1) = "qbr(" + block(i + 1) + ")"
                        newtyp = 64&
                    END IF
                ELSE
                    'newtyp is an int
                    IF (rhstyp AND 1) = 0 THEN
                        'convert int to float
                        block(i + 1) = "((long double)(" + block(i + 1) + "))"
                        newtyp = 256& + ISFLOAT
                    END IF
                END IF
            END IF

            'Reduce floating point values to common base for comparison?
            if isop=7 then 'comparitive operator          
            'Corrects problems encountered such as:
            '    S = 2.1
            '    IF S = 2.1 THEN PRINT "OK" ELSE PRINT "ERROR S PRINTS AS"; S; "BUT IS SEEN BY QB64 AS..."
            '    IF S < 2.1 THEN PRINT "LESS THAN 2.1"
            'concerns:
            '1. Return value from TIMER will be reduced to a SINGLE in direct comparisons
            'solution: assess, and only apply to SINGLE variables/arrays
            '2. Comparison of a double higher/lower than single range may fail
            'solution: out of range values convert to +/-1.#INF, making comparison still possible
             IF (oldtyp AND ISFLOAT)<>0 and (newtyp AND ISFLOAT)<>0 then 'both floating point
              s1=oldtyp and 511: s2=newtyp and 511
              if s2<s1 then s1=s2
              if s1=32 then
               block(i - 1) = "((float)(" + block(i - 1) + "))": oldtyp = 32& + ISFLOAT
               block(i + 1) = "((float)(" + block(i +1) + "))": newtyp = 32& + ISFLOAT
              end if
              if s1=64 then
               block(i - 1) = "((double)(" + block(i - 1) + "))": oldtyp = 64& + ISFLOAT
               block(i + 1) = "((double)(" + block(i + 1) + "))": newtyp = 64& + ISFLOAT
              end if
             end if 'both floating point
            end if 'comparitive operator

            typ = newtyp

            'STEP 2: markup typ
            '        if either side is a float, markup typ to largest float
            '        if either side is integer, markup typ
            'Note: A markup is a GUESS of what the return type will be,
            '      'result' can override this markup
            IF (oldtyp AND ISSTRING) = 0 AND (newtyp AND ISSTRING) = 0 THEN
                IF (oldtyp AND ISFLOAT) <> 0 OR (newtyp AND ISFLOAT) <> 0 THEN
                    'float
                    b = 0: IF (oldtyp AND ISFLOAT) THEN b = oldtyp AND 511
                    IF (newtyp AND ISFLOAT) THEN
                        b2 = newtyp AND 511: IF b2 > b THEN b = b2
                    END IF
                    typ = ISFLOAT + b
                ELSE
                    'integer
                    '***THIS IS THE IDEAL MARKUP FOR A 64-BIT SYSTEM***
                    'In reality 32-bit C++ only marks-up to 32-bit integers
                    b = oldtyp AND 511: b2 = newtyp AND 511: IF b2 > b THEN b = b2
                    typ = 64&
                    IF b = 64 THEN
                        IF (oldtyp AND ISUNSIGNED) <> 0 AND (newtyp AND ISUNSIGNED) <> 0 THEN typ = 64& + ISUNSIGNED
                    END IF
                END IF
            END IF

            IF result = 1 THEN
                IF (typ AND ISFLOAT) <> 0 OR (typ AND ISSTRING) <> 0 THEN typ = 64 'otherwise keep markuped integer type
            END IF
            IF result = 2 THEN
                IF (typ AND ISFLOAT) = 0 THEN typ = ISFLOAT + 256
            END IF
            IF result = 4 THEN
                typ = ISSTRING
            END IF
            IF result = 8 THEN 'bool
                typ = 32
            END IF

            'override typ=ISFLOAT+256 to typ=ISFLOAT+64 for ^ operator's result
            IF u = 2 THEN
                IF i$ = "pow2" THEN

                    'QB-like conversion of math functions returning floating point values
                    'reassess oldtype & newtype
                    b = oldtyp AND 511
                    IF oldtyp AND ISFLOAT THEN
                        'no change to b
                    ELSE
                        IF b > 16 THEN b = 64 'larger than INTEGER? return DOUBLE
                        IF b > 32 THEN b = 256 'larger than LONG? return FLOAT
                        IF b <= 16 THEN b = 32
                    END IF
                    b2 = newtyp AND 511
                    IF newtyp AND ISFLOAT THEN
                        IF b2 > b THEN b = b2
                    ELSE
                        b3 = 32
                        IF b2 > 16 THEN b3 = 64 'larger than INTEGER? return DOUBLE
                        IF b2 > 32 THEN b3 = 256 'larger than LONG? return FLOAT
                        IF b3 > b THEN b = b3
                    END IF
                    typ = ISFLOAT + b

                END IF 'pow2
            END IF 'u=2

            'STEP 3: apply operator appropriately

            IF u = 5 THEN
                block(i + 1) = i$ + "(" + block(i + 1) + ")"
                block(i) = "": i = i + 1: GOTO operatorapplied
            END IF

            'binary operators

            IF u = 1 THEN
                block(i + 1) = block(i - 1) + i$ + block(i + 1)
                block(i - 1) = "": block(i) = "": i = i + 1: GOTO operatorapplied
            END IF

            IF u = 2 THEN
                block(i + 1) = i$ + "(" + block(i - 1) + "," + block(i + 1) + ")"
                block(i - 1) = "": block(i) = "": i = i + 1: GOTO operatorapplied
            END IF

            IF u = 3 THEN
                block(i + 1) = "-(" + block(i - 1) + i$ + block(i + 1) + ")"
                block(i - 1) = "": block(i) = "": i = i + 1: GOTO operatorapplied
            END IF

            IF u = 4 THEN
                block(i + 1) = "~" + block(i - 1) + i$ + block(i + 1)
                block(i - 1) = "": block(i) = "": i = i + 1: GOTO operatorapplied
            END IF


            '...more?...

            nerror (93) '<--should never happen!
            operatorapplied:

        ELSE
        nonop=nonop+1
        END IF
    ELSE
    nonop=nonop+1
    END IF
    if nonop>1 then qb64error "Expected operator in equation"
NEXT
IF debug THEN PRINT #9, ""

'join blocks
FOR i = 1 TO blockn
    r$ = r$ + block(i)
NEXT

IF debug THEN
    PRINT #9, "evaluated:" + r$ + " AS TYPE:";
    IF (typ AND ISSTRING) THEN PRINT #9, "[ISSTRING]";
    IF (typ AND ISFLOAT) THEN PRINT #9, "[ISFLOAT]";
    IF (typ AND ISUNSIGNED) THEN PRINT #9, "[ISUNSIGNED]";
    IF (typ AND ISPOINTER) THEN PRINT #9, "[ISPOINTER]";
    IF (typ AND ISFIXEDLENGTH) THEN PRINT #9, "[ISFIXEDLENGTH]";
    IF (typ AND ISINCONVENTIONALMEMORY) THEN PRINT #9, "[ISINCONVENTIONALMEMORY]";
    PRINT #9, "(size in bits=" + str2$(typ AND 511) + ")"
END IF


evaluate$ = r$



END FUNCTION




FUNCTION evaluatefunc$ (a2$, args AS LONG, typ AS LONG)
a$ = a2$

IF debug THEN PRINT #9, "evaluatingfunction:" + RTRIM$(id.n) + ":" + a$

DIM id2 AS idstruct

id2 = id
n$ = RTRIM$(id2.n)
typ = id2.ret
targetid = currentid

passomit = 0
skiparg = 0

f$ = RTRIM$(id2.specialformat)
IF LEN(f$) THEN 'special format given

    passomit = 1
    IF args < id2.args - 1 OR args > id2.args THEN nerror (120)
    f$ = f$ + " "
    a = 0
    FOR i = 1 TO LEN(f$) - 1
        IF MID$(f$, i, 1) = "?" THEN
            a = a + 1
            IF MID$(f$, i + 1, 1) = "]" THEN skiparg = a: EXIT FOR
        END IF
    NEXT
    IF id2.args = args THEN skiparg = 0 'all arguments were passed!
    IF args < id2.args - 1 OR args > id2.args THEN nerror (121)

ELSE 'no special format given

    IF n$ = "ASC" AND args = 2 THEN GOTO skipargnumchk
    IF id2.args <> args THEN nerror (121)

END IF

skipargnumchk:



r$ = RTRIM$(id2.callname) + "("
IF id2.args <> 0 THEN

    curarg = 1
    firsti = 1

    n = numelements(a$)
    IF n = 0 THEN i = 0: GOTO noargs

    FOR i = 1 TO n

        IF curarg = skiparg THEN
            noargs:
            targettyp = CVL(MID$(id2.arg, curarg * 4 - 4 + 1, 4))


            'IF (targettyp AND ISSTRING) THEN nerror (122)

            r$ = r$ + "NULL"
            curarg = curarg + 1
            IF i = n THEN EXIT FOR
            r$ = r$ + ","
        END IF

        l$ = getelement(a$, i)
        IF l$ = "(" THEN b = b + 1
        IF l$ = ")" THEN b = b - 1
        IF (l$ = "," AND b = 0) OR (i = n) THEN
            targettyp = CVL(MID$(id2.arg, curarg * 4 - 4 + 1, 4))

            IF i = n THEN
                e$ = getelements$(a$, firsti, i)
            ELSE
                e$ = getelements$(a$, firsti, i - 1)
            END IF

            IF LEFT$(e$, 2) = "(" + sp THEN dereference = 1 ELSE dereference = 0



            '*special case CVI,CVL,CVS,CVD,_CV (part #1)
            IF n$ = "_CV" THEN
                IF curarg = 1 THEN
                    cvtype$ = type2symbol$(e$)
                    e$ = ""
                    GOTO dontevaluate
                END IF
            END IF

            '*special case MKI,MKL,MKS,MKD,_MK (part #1)

            IF n$ = "_MK" THEN
                IF RTRIM$(id2.musthave) = "$" THEN
                    IF curarg = 1 THEN
                        mktype$ = type2symbol$(e$)
                        IF debug THEN PRINT #9, "_MK:[" + e$ + "]:[" + mktype$ + "]"
                        e$ = ""
                        GOTO dontevaluate
                    END IF
                END IF
            END IF

            IF n$ = "UBOUND" OR n$ = "LBOUND" THEN
                IF curarg = 1 THEN
                    'perform a "fake" evaluation of the array
                    e$ = e$ + sp + "(" + sp + ")"
                    e$ = evaluate(e$, sourcetyp)
                    IF (sourcetyp AND ISREFERENCE) = 0 THEN nerror (123)
                    IF (sourcetyp AND ISARRAY) = 0 THEN nerror (124)
                    'make a note of the array's index for later
                    ulboundarray$ = e$
                    ulboundarraytyp = sourcetyp
                    e$ = ""
                    r$ = ""
                    GOTO dontevaluate
                END IF
            END IF


            '*special case: INPUT$ function
            IF n$ = "INPUT" THEN
                IF RTRIM$(id2.musthave) = "$" THEN
                    IF curarg = 2 THEN
                        IF LEFT$(e$, 2) = "#" + sp THEN e$ = RIGHT$(e$, LEN(e$) - 2)
                    END IF
                END IF
            END IF


            '*special case*
            IF n$ = "ASC" THEN
                IF curarg = 2 THEN
                    e$ = evaluatetotyp$(e$, 32&)
                    typ& = LONGTYPE - ISPOINTER
                    r$ = r$ + e$ + ")"
                    GOTO evalfuncspecial
                END IF
            END IF

            '------------------------------------------------------------------------------------------------------------
            e2$ = e$
            e$ = evaluate(e$, sourcetyp)
            '------------------------------------------------------------------------------------------------------------

            '*special case*
            IF n$ = "ENVIRON" THEN
                IF sourcetyp AND ISSTRING THEN
                    IF sourcetyp AND ISREFERENCE THEN e$ = refer(e$, sourcetyp, 0)
                    GOTO dontevaluate
                END IF
            END IF

            '*special case*
            IF n$ = "LEN" THEN
                typ& = LONGTYPE - ISPOINTER
                IF (sourcetyp AND ISREFERENCE) = 0 THEN
                    'could be a string expression
                    IF sourcetyp AND ISSTRING THEN
                        r$ = "((int32)(" + e$ + ")->len)"
                        GOTO evalfuncspecial
                    END IF
                    qb64error "String expression or variable name required in LEN statement"
                END IF
                r$ = evaluatetotyp$(e2$, -5) 'use evaluatetotyp to get 'element' size
                GOTO evalfuncspecial
            END IF

            '*special case*
            IF n$ = "OCT" THEN
                IF RTRIM$(id2.musthave) = "$" THEN
                    bits = sourcetyp AND 511
                    IF (sourcetyp AND ISSTRING) THEN nerror (125)
                    wasref = 0
                    IF (sourcetyp AND ISREFERENCE) THEN e$ = refer(e$, sourcetyp, 0): wasref = 1
                    bits = sourcetyp AND 511
                    IF (sourcetyp AND ISOFFSETINBITS) THEN
                        e$ = "func_oct(" + e$ + "," + str2$(bits) + ")"
                    ELSE
                        IF (sourcetyp AND ISFLOAT) THEN
                            e$ = "func_oct_float(" + e$ + ")"
                        ELSE
                            IF bits = 64 THEN
                                IF wasref = 0 THEN bits = 0
                            END IF
                            e$ = "func_oct(" + e$ + "," + str2$(bits) + ")"
                        END IF
                    END IF
                    typ& = STRINGTYPE - ISPOINTER
                    r$ = e$
                    GOTO evalfuncspecial
                END IF
            END IF



            '*special case*
            IF n$ = "HEX" THEN
                IF RTRIM$(id2.musthave) = "$" THEN
                    bits = sourcetyp AND 511
                    IF (sourcetyp AND ISSTRING) THEN nerror (126)
                    wasref = 0
                    IF (sourcetyp AND ISREFERENCE) THEN e$ = refer(e$, sourcetyp, 0): wasref = 1
                    bits = sourcetyp AND 511
                    IF (sourcetyp AND ISOFFSETINBITS) THEN
                        chars = (bits + 3) \ 4
                        e$ = "func_hex(" + e$ + "," + str2$(chars) + ")"
                    ELSE
                        IF (sourcetyp AND ISFLOAT) THEN
                            e$ = "func_hex_float(" + e$ + ")"
                        ELSE
                            IF bits = 8 THEN chars = 2
                            IF bits = 16 THEN chars = 4
                            IF bits = 32 THEN chars = 8
                            IF bits = 64 THEN
                                IF wasref = 1 THEN chars = 16 ELSE chars = 0
                            END IF
                            e$ = "func_hex(" + e$ + "," + str2$(chars) + ")"
                        END IF
                    END IF
                    typ& = STRINGTYPE - ISPOINTER
                    r$ = e$
                    GOTO evalfuncspecial
                END IF
            END IF









            '*special case*
            IF n$ = "EXP" THEN
                bits = sourcetyp AND 511
                IF (sourcetyp AND ISSTRING) THEN nerror (127)
                IF (sourcetyp AND ISREFERENCE) THEN e$ = refer(e$, sourcetyp, 0)
                bits = sourcetyp AND 511
                typ& = SINGLETYPE - ISPOINTER
                IF (sourcetyp AND ISFLOAT) THEN
                    IF bits = 32 THEN e$ = "func_exp_single(" + e$ + ")" ELSE e$ = "func_exp_float(" + e$ + ")": typ& = FLOATTYPE - ISPOINTER
                ELSE
                    IF (sourcetyp AND ISOFFSETINBITS) THEN
                        e$ = "func_exp_float(" + e$ + ")": typ& = FLOATTYPE - ISPOINTER
                    ELSE
                        IF bits <= 16 THEN e$ = "func_exp_single(" + e$ + ")" ELSE e$ = "func_exp_float(" + e$ + ")": typ& = FLOATTYPE - ISPOINTER
                    END IF
                END IF
                r$ = e$
                GOTO evalfuncspecial
            END IF

            '*special case*
            IF n$ = "INT" THEN
                IF (sourcetyp AND ISSTRING) THEN nerror (128)
                IF (sourcetyp AND ISREFERENCE) THEN e$ = refer(e$, sourcetyp, 0)
                'establish which function (if any!) should be used
                IF (sourcetyp AND ISFLOAT) THEN e$ = "floor(" + e$ + ")" else e$="("+e$+")"
                r$ = e$
                typ& = sourcetyp
                GOTO evalfuncspecial
            END IF

            '*special case*
            IF n$ = "FIX" THEN
                IF (sourcetyp AND ISSTRING) THEN nerror (129)
                IF (sourcetyp AND ISREFERENCE) THEN e$ = refer(e$, sourcetyp, 0)
                'establish which function (if any!) should be used
                bits = sourcetyp AND 511
                IF (sourcetyp AND ISFLOAT) THEN
                    IF bits > 64 THEN e$ = "func_fix_float(" + e$ + ")" ELSE e$ = "func_fix_double(" + e$ + ")"
		else
                e$="("+e$+")"
                END IF
                r$ = e$
                typ& = sourcetyp
                GOTO evalfuncspecial
            END IF

            '*special case*
            IF n$ = "_ROUND" THEN
                IF (sourcetyp AND ISSTRING) THEN nerror (130)
                IF (sourcetyp AND ISREFERENCE) THEN e$ = refer(e$, sourcetyp, 0)
                'establish which function (if any!) should be used
                IF (sourcetyp AND ISFLOAT) THEN
                    bits = sourcetyp AND 511
                    IF bits > 64 THEN e$ = "func_round_float(" + e$ + ")" ELSE e$ = "func_round_double(" + e$ + ")"
                else
                    e$="("+e$+")"
                END IF
                r$ = e$
                typ& = 64&
                GOTO evalfuncspecial
            END IF


            '*special case*
            IF n$ = "CDBL" THEN
                IF (sourcetyp AND ISSTRING) THEN nerror (131)
                IF (sourcetyp AND ISREFERENCE) THEN e$ = refer(e$, sourcetyp, 0)
                'establish which function (if any!) should be used
                bits = sourcetyp AND 511
                IF (sourcetyp AND ISFLOAT) THEN
                    IF bits > 64 THEN e$ = "func_cdbl_float(" + e$ + ")"
                ELSE
                    e$ = "((double)(" + e$ + "))"
                END IF
                r$ = e$
                typ& = DOUBLETYPE - ISPOINTER
                GOTO evalfuncspecial
            END IF

            '*special case*
            IF n$ = "CSNG" THEN
                IF (sourcetyp AND ISSTRING) THEN nerror (132)
                IF (sourcetyp AND ISREFERENCE) THEN e$ = refer(e$, sourcetyp, 0)
                'establish which function (if any!) should be used
                bits = sourcetyp AND 511
                IF (sourcetyp AND ISFLOAT) THEN
                    IF bits = 64 THEN e$ = "func_csng_double(" + e$ + ")"
                    IF bits > 64 THEN e$ = "func_csng_float(" + e$ + ")"
                ELSE
                    e$ = "((double)(" + e$ + "))"
                END IF
                r$ = e$
                typ& = SINGLETYPE - ISPOINTER
                GOTO evalfuncspecial
            END IF


            '*special case*
            IF n$ = "CLNG" THEN
                IF (sourcetyp AND ISSTRING) THEN nerror (133)
                IF (sourcetyp AND ISREFERENCE) THEN e$ = refer(e$, sourcetyp, 0)
                'establish which function (if any!) should be used
                bits = sourcetyp AND 511
                IF (sourcetyp AND ISFLOAT) THEN
                    IF bits > 64 THEN e$ = "func_clng_float(" + e$ + ")" ELSE e$ = "func_clng_double(" + e$ + ")"
                ELSE 'integer
                    IF (sourcetyp AND ISUNSIGNED) THEN
                        IF bits = 32 THEN e$ = "func_clng_ulong(" + e$ + ")"
                        IF bits > 32 THEN e$ = "func_clng_uint64(" + e$ + ")"
                    ELSE 'signed
                        IF bits > 32 THEN e$ = "func_clng_int64(" + e$ + ")"
                    END IF
                END IF
                r$ = e$
                typ& = 32&
                GOTO evalfuncspecial
            END IF

            '*special case*
            IF n$ = "CINT" THEN
                IF (sourcetyp AND ISSTRING) THEN nerror (134)
                IF (sourcetyp AND ISREFERENCE) THEN e$ = refer(e$, sourcetyp, 0)
                'establish which function (if any!) should be used
                bits = sourcetyp AND 511
                IF (sourcetyp AND ISFLOAT) THEN
                    IF bits > 64 THEN e$ = "func_cint_float(" + e$ + ")" ELSE e$ = "func_cint_double(" + e$ + ")"
                ELSE 'integer
                    IF (sourcetyp AND ISUNSIGNED) THEN
                        IF bits > 15 AND bits <= 32 THEN e$ = "func_cint_ulong(" + e$ + ")"
                        IF bits > 32 THEN e$ = "func_cint_uint64(" + e$ + ")"
                    ELSE 'signed
                        IF bits > 16 AND bits <= 32 THEN e$ = "func_cint_long(" + e$ + ")"
                        IF bits > 32 THEN e$ = "func_cint_int64(" + e$ + ")"
                    END IF
                END IF
                r$ = e$
                typ& = 16&
                GOTO evalfuncspecial
            END IF

            '*special case MKI,MKL,MKS,MKD,_MK (part #2)
            mktype = 0
            size = 0
            IF n$ = "MKI" THEN mktype = 1: mktype$ = "%"
            IF n$ = "MKL" THEN mktype = 2: mktype$ = "&"
            IF n$ = "MKS" THEN mktype = 3: mktype$ = "!"
            IF n$ = "MKD" THEN mktype = 4: mktype$ = "#"
            IF n$ = "_MK" THEN mktype = -1
            IF mktype THEN
                IF mktype <> -1 OR curarg = 2 THEN
                    'both _MK and trad. process the following
                    qtyp& = 0
                    IF mktype$ = "%%" THEN ctype$ = "b": qtyp& = BYTETYPE - ISPOINTER
                    IF mktype$ = "~%%" THEN ctype$ = "ub": qtyp& = UBYTETYPE - ISPOINTER
                    IF mktype$ = "%" THEN ctype$ = "i": qtyp& = INTEGERTYPE - ISPOINTER
                    IF mktype$ = "~%" THEN ctype$ = "ui": qtyp& = UINTEGERTYPE - ISPOINTER
                    IF mktype$ = "&" THEN ctype$ = "l": qtyp& = LONGTYPE - ISPOINTER
                    IF mktype$ = "~&" THEN ctype$ = "ul": qtyp& = ULONGTYPE - ISPOINTER
                    IF mktype$ = "&&" THEN ctype$ = "i64": qtyp& = INTEGER64TYPE - ISPOINTER
                    IF mktype$ = "~&&" THEN ctype$ = "ui64": qtyp& = UINTEGER64TYPE - ISPOINTER
                    IF mktype$ = "!" THEN ctype$ = "s": qtyp& = SINGLETYPE - ISPOINTER
                    IF mktype$ = "#" THEN ctype$ = "d": qtyp& = DOUBLETYPE - ISPOINTER
                    IF mktype$ = "##" THEN ctype$ = "f": qtyp& = FLOATTYPE - ISPOINTER
                    IF LEFT$(mktype$, 2) = "~`" THEN ctype$ = "ubit": qtyp& = UINTEGER64TYPE - ISPOINTER: size = VAL(RIGHT$(mktype$, LEN(mktype$) - 2))
                    IF LEFT$(mktype$, 1) = "`" THEN ctype$ = "bit": qtyp& = INTEGER64TYPE - ISPOINTER: size = VAL(RIGHT$(mktype$, LEN(mktype$) - 1))
                    IF qtyp& = 0 THEN nerror (135)
                    IF size THEN
                        r$ = ctype$ + "2string(" + str2(size) + ","
                    ELSE
                        r$ = ctype$ + "2string("
                    END IF
                    nocomma = 1
                    targettyp = qtyp&
                END IF
            END IF

            '*special case CVI,CVL,CVS,CVD,_CV (part #2)
            cvtype = 0
            IF n$ = "CVI" THEN cvtype = 1: cvtype$ = "%"
            IF n$ = "CVL" THEN cvtype = 2: cvtype$ = "&"
            IF n$ = "CVS" THEN cvtype = 3: cvtype$ = "!"
            IF n$ = "CVD" THEN cvtype = 4: cvtype$ = "#"
            IF n$ = "_CV" THEN cvtype = -1
            IF cvtype THEN
                IF cvtype <> -1 OR curarg = 2 THEN
                    IF (sourcetyp AND ISSTRING) = 0 THEN qb64error n$ + " requires a STRING argument"
                    IF (sourcetyp AND ISREFERENCE) THEN e$ = refer(e$, sourcetyp, 0)
                    typ& = 0
                    IF cvtype$ = "%%" THEN ctype$ = "b": typ& = BYTETYPE - ISPOINTER
                    IF cvtype$ = "~%%" THEN ctype$ = "ub": typ& = UBYTETYPE - ISPOINTER
                    IF cvtype$ = "%" THEN ctype$ = "i": typ& = INTEGERTYPE - ISPOINTER
                    IF cvtype$ = "~%" THEN ctype$ = "ui": typ& = UINTEGERTYPE - ISPOINTER
                    IF cvtype$ = "&" THEN ctype$ = "l": typ& = LONGTYPE - ISPOINTER
                    IF cvtype$ = "~&" THEN ctype$ = "ul": typ& = ULONGTYPE - ISPOINTER
                    IF cvtype$ = "&&" THEN ctype$ = "i64": typ& = INTEGER64TYPE - ISPOINTER
                    IF cvtype$ = "~&&" THEN ctype$ = "ui64": typ& = UINTEGER64TYPE - ISPOINTER
                    IF cvtype$ = "!" THEN ctype$ = "s": typ& = SINGLETYPE - ISPOINTER
                    IF cvtype$ = "#" THEN ctype$ = "d": typ& = DOUBLETYPE - ISPOINTER
                    IF cvtype$ = "##" THEN ctype$ = "f": typ& = FLOATTYPE - ISPOINTER
                    IF LEFT$(cvtype$, 2) = "~`" THEN ctype$ = "ubit": typ& = UINTEGER64TYPE - ISPOINTER: size = VAL(RIGHT$(cvtype$, LEN(cvtype$) - 2))
                    IF LEFT$(cvtype$, 1) = "`" THEN ctype$ = "bit": typ& = INTEGER64TYPE - ISPOINTER: size = VAL(RIGHT$(cvtype$, LEN(cvtype$) - 1))
                    IF typ& = 0 THEN nerror (136)
                    IF ctype$ = "bit" OR ctype$ = "ubit" THEN
                        r$ = "string2" + ctype$ + "(" + e$ + "," + str2(size) + ")"
                    ELSE
                        r$ = "string2" + ctype$ + "(" + e$ + ")"
                    END IF
                    GOTO evalfuncspecial
                END IF
            END IF

            '*special case
            IF RTRIM$(id2.n) = "STRING" THEN
                IF curarg = 2 THEN
                    IF (sourcetyp AND ISSTRING) THEN
                        IF (sourcetyp AND ISREFERENCE) THEN e$ = refer(e$, sourcetyp, 0)
                        sourcetyp = 64&
                        e$ = "(" + e$ + "->chr[0])"
                    END IF
                END IF
            END IF

            '*special case
            IF RTRIM$(id2.n) = "SADD" THEN
                IF (sourcetyp AND ISREFERENCE) = 0 THEN
                    nerror (137)
                END IF
                IF (sourcetyp AND ISFIXEDLENGTH) THEN
                    nerror (138)
                END IF
                IF (sourcetyp AND ISINCONVENTIONALMEMORY) = 0 THEN
                    recompile = 1
                    cmemlist(VAL(e$)) = 1
                    r$ = "[CONVENTIONAL_MEMORY_REQUIRED]"
                    typ& = 64&
                    GOTO evalfuncspecial
                END IF
                r$ = refer(e$, sourcetyp, 0)
                r$ = "((unsigned short)(" + r$ + "->chr-&cmem[1280]))"
                typ& = 64&
                GOTO evalfuncspecial
            END IF

            '*special case
            IF RTRIM$(id2.n) = "VARPTR" THEN
                IF (sourcetyp AND ISREFERENCE) = 0 THEN
                    nerror (139)
                END IF

                IF RTRIM$(id2.musthave) = "$" THEN
                    IF (sourcetyp AND ISINCONVENTIONALMEMORY) = 0 THEN
                        recompile = 1
                        cmemlist(VAL(e$)) = 1
                        r$ = "[CONVENTIONAL_MEMORY_REQUIRED]"
                        typ& = ISSTRING
                        GOTO evalfuncspecial
                    END IF

                    IF (sourcetyp AND ISARRAY) THEN
                        IF (sourcetyp AND ISSTRING) = 0 THEN nerror (140)
                        IF (sourcetyp AND ISFIXEDLENGTH) THEN nerror (141)
                    END IF

                    'must be a simple variable
                    '!assuming it is in cmem in DBLOCK
                    r$ = refer(e$, sourcetyp, 1)
                    IF (sourcetyp AND ISSTRING) THEN
                        IF (sourcetyp AND ISARRAY) THEN r$ = refer(e$, sourcetyp, 0)
                        r$ = r$ + "->cmem_descriptor_offset"
                        t = 3
                    ELSE
                        r$ = "((unsigned short)(((uint8*)" + r$ + ")-&cmem[1280]))"
                        '*top bit on=unsigned
                        '*second top bit on=bit-value (lower bits indicate the size)
                        'BYTE=1
                        'INTEGER=2
                        'STRING=3
                        'SINGLE=4
                        'INT64=5
                        'FLOAT=6
                        'DOUBLE=8
                        'LONG=20
                        'BIT=64+n
                        t = 0
                        IF (sourcetyp AND ISUNSIGNED) THEN t = t + 128
                        IF (sourcetyp AND ISOFFSETINBITS) THEN
                            t = t + 64
                            t = t + (sourcetyp AND 63)
                        ELSE
                            bits = sourcetyp AND 511
                            IF (sourcetyp AND ISFLOAT) THEN
                                IF bits = 32 THEN t = t + 4
                                IF bits = 64 THEN t = t + 8
                                IF bits = 256 THEN t = t + 6
                            ELSE
                                IF bits = 8 THEN t = t + 1
                                IF bits = 16 THEN t = t + 2
                                IF bits = 32 THEN t = t + 20
                                IF bits = 64 THEN t = t + 5
                            END IF
                        END IF
                    END IF
                    r$ = "func_varptr_helper(" + str2(t) + "," + r$ + ")"
                    typ& = ISSTRING
                    GOTO evalfuncspecial
                END IF 'end of varptr$











                'VARPTR
                IF (sourcetyp AND ISINCONVENTIONALMEMORY) = 0 THEN
                    recompile = 1
                    cmemlist(VAL(e$)) = 1
                    r$ = "[CONVENTIONAL_MEMORY_REQUIRED]"
                    typ& = 64&
                    GOTO evalfuncspecial
                END IF

                IF (sourcetyp AND ISARRAY) THEN
                    IF (sourcetyp AND ISOFFSETINBITS) THEN nerror (142)

                    'string array?
                    IF (sourcetyp AND ISSTRING) THEN
                        IF (sourcetyp AND ISFIXEDLENGTH) THEN
                            getid VAL(e$)
                            m = id.tsize
                            index$ = RIGHT$(e$, LEN(e$) - INSTR(e$, "³"))
                            typ = 64&
                            r$ = "((" + index$ + ")*" + str2(m) + ")"
                            GOTO evalfuncspecial
                        ELSE
                            'return the offset of the string's descriptor
                            r$ = refer(e$, sourcetyp, 0)
                            r$ = r$ + "->cmem_descriptor_offset"
                            typ = 64&
                            GOTO evalfuncspecial
                        END IF
                    END IF

                    IF sourcetyp AND ISUDT THEN
                        e$ = RIGHT$(e$, LEN(e$) - INSTR(e$, "³")) 'skip idnumber
                        e$ = RIGHT$(e$, LEN(e$) - INSTR(e$, "³")) 'skip u
                        o$ = RIGHT$(e$, LEN(e$) - INSTR(e$, "³")) 'skip e
                        typ = 64&
                        r$ = "(" + o$ + ")"
                        GOTO evalfuncspecial
                    END IF

                    'non-UDT array
                    m = (sourcetyp AND 511) \ 8 'calculate size multiplier
                    index$ = RIGHT$(e$, LEN(e$) - INSTR(e$, "³"))
                    typ = 64&
                    r$ = "((" + index$ + ")*" + str2(m) + ")"
                    GOTO evalfuncspecial

                END IF

                'not an array

                IF sourcetyp AND ISUDT THEN
                    r$ = refer(e$, sourcetyp, 1)
                    e$ = RIGHT$(e$, LEN(e$) - INSTR(e$, "³")) 'skip idnumber
                    e$ = RIGHT$(e$, LEN(e$) - INSTR(e$, "³")) 'skip u
                    o$ = RIGHT$(e$, LEN(e$) - INSTR(e$, "³")) 'skip e
                    typ = 64&

                    'if sub/func arg, may not be in DBLOCK
                    getid VAL(e$)
                    IF id.sfarg THEN 'could be in DBLOCK
                        'note: segment could be the closest segment to UDT element or the base of DBLOCK
                        r$ = "varptr_dblock_check(((uint8*)" + r$ + ")+(" + o$ + "))"
                    ELSE 'definitely in DBLOCK
                        'give offset relative to DBLOCK
                        r$ = "((unsigned short)(((uint8*)" + r$ + ") - &cmem[1280] + (" + o$ + ") ))"
                    END IF

                    GOTO evalfuncspecial
                END IF

                typ = 64&
                r$ = refer(e$, sourcetyp, 1)
                IF (sourcetyp AND ISSTRING) THEN
                    IF (sourcetyp AND ISFIXEDLENGTH) THEN

                        'if sub/func arg, may not be in DBLOCK
                        getid VAL(e$)
                        IF id.sfarg THEN 'could be in DBLOCK
                            r$ = "varptr_dblock_check(" + r$ + "->chr)"
                        ELSE 'definitely in DBLOCK
                            r$ = "((unsigned short)(" + r$ + "->chr-&cmem[1280]))"
                        END IF

                    ELSE
                        r$ = r$ + "->cmem_descriptor_offset"
                    END IF
                    GOTO evalfuncspecial
                END IF

                'single, simple variable
                'if sub/func arg, may not be in DBLOCK
                getid VAL(e$)
                IF id.sfarg THEN 'could be in DBLOCK
                    r$ = "varptr_dblock_check((uint8*)" + r$ + ")"
                ELSE 'definitely in DBLOCK
                    r$ = "((unsigned short)(((uint8*)" + r$ + ")-&cmem[1280]))"
                END IF

                GOTO evalfuncspecial
            END IF

            '*special case*
            IF RTRIM$(id2.n) = "VARSEG" THEN
                IF (sourcetyp AND ISREFERENCE) = 0 THEN
                    nerror (143)
                END IF
                IF (sourcetyp AND ISINCONVENTIONALMEMORY) = 0 THEN
                    recompile = 1
                    cmemlist(VAL(e$)) = 1
                    r$ = "[CONVENTIONAL_MEMORY_REQUIRED]"
                    typ& = 64&
                    GOTO evalfuncspecial
                END IF
                'array?
                IF (sourcetyp AND ISARRAY) THEN
                    IF (sourcetyp AND ISFIXEDLENGTH) = 0 THEN
                        IF (sourcetyp AND ISSTRING) THEN
                            r$ = "80"
                            typ = 64&
                            GOTO evalfuncspecial
                        END IF
                    END IF
                    typ = 64&
                    r$ = "( ( ((ptrszint)(" + refer(e$, sourcetyp, 1) + "[0])) - ((ptrszint)(&cmem[0])) ) /16)"
                    GOTO evalfuncspecial
                END IF

                'single variable/(var-len)string/udt? (usually stored in DBLOCK)
                typ = 64&
                'if sub/func arg, may not be in DBLOCK
                getid VAL(e$)
                IF id.sfarg <> 0 AND (sourcetyp AND ISSTRING) = 0 THEN
                    IF sourcetyp AND ISUDT THEN
                        r$ = refer(e$, sourcetyp, 1)
                        e$ = RIGHT$(e$, LEN(e$) - INSTR(e$, "³")) 'skip idnumber
                        e$ = RIGHT$(e$, LEN(e$) - INSTR(e$, "³")) 'skip u
                        o$ = RIGHT$(e$, LEN(e$) - INSTR(e$, "³")) 'skip e
                        r$ = "varseg_dblock_check(((uint8*)" + r$ + ")+(" + o$ + "))"
                    ELSE
                        r$ = "varseg_dblock_check((uint8*)" + refer(e$, sourcetyp, 1) + ")"
                    END IF
                ELSE
                    'can be assumed to be in DBLOCK
                    r$ = "80"
                END IF
                GOTO evalfuncspecial
            END IF 'varseg


            'any numeric variable, but it must be type-speficied

            explicitreference = 0
            IF targettyp = -1 THEN
                explicitreference = 1
                IF (sourcetyp AND ISSTRING) THEN nerror (144)
                targettyp = sourcetyp
                IF (targettyp AND ISPOINTER) THEN targettyp = targettyp - ISPOINTER
            END IF

            'pointer?
            IF (targettyp AND ISPOINTER) THEN
                IF dereference = 0 THEN 'check deferencing wasn't used

                    'PRINT "Target is a pointer!"

                    IF (targettyp AND ISARRAY) THEN

                        IF (sourcetyp AND ISREFERENCE) = 0 THEN qb64error "Expected arrayname()"

                        'following check failed...
                        IF (sourcetyp AND ISARRAY) = 0 THEN qb64error "Expected arrayname()"

                        IF sourcetyp AND ISUDT THEN
                            'check u or e
                        ELSE
                            IF RIGHT$(e$, 2) <> "³0" THEN qb64error "Expected arrayname()"
                        END IF

                        'check array is of same TYPE!

                        targettypsize = CVL(MID$(id2.argsize, curarg * 4 - 4 + 1, 4))
                        'targettypsize is ignored! but would be used for type checking fixed length string arrays

                        idnum = VAL(LEFT$(e$, INSTR(e$, "³") - 1))
                        getid idnum

                        '20090703
                        IF MID$(sfcmemargs(targetid), curarg, 1) = CHR$(1) THEN 'cmem required?
                            IF cmemlist(idnum) = 0 THEN
                                cmemlist(idnum) = 1
                                recompile = 1
                            END IF
                        END IF



                        IF id.linkid = 0 THEN
                            'if id.linkid is 0, it means the number of array elements is definietly
                            'known of the array being passed, this is not some "fake"/unknown array.
                            'using the numer of array elements of a fake array would be dangerous!

                            IF nelereq = 0 THEN
                                'only continue if the number of array elements required is unknown
                                'and it needs to be set

                                IF id.arrayelements <> -1 THEN
                                    nelereq = id.arrayelements
                                    MID$(id2.nelereq, curarg, 1) = CHR$(nelereq)
                                END IF

                                ids(targetid) = id2

                            ELSE

                                'the number of array elements required is known AND
                                'the number of elements in the array to be passed is known



                                'REMOVED FOR TESTING PURPOSES ONLY!!! SHOULD BE UNREM'd!
                                'print id.arrayelements,nelereq
                                '             1       ,  2

                                IF id.arrayelements <> nelereq THEN qb64error "Passing arrays with a differing number of elements to a SUB/FUNCTION is not supported (yet)"


                            END IF
                        END IF


                        e$ = refer(e$, sourcetyp, 1)
                        GOTO dontevaluate
                    END IF

                    'target is not an array

                    IF (targettyp AND ISSTRING) = 0 THEN
                        IF (sourcetyp AND ISREFERENCE) THEN
                            '20090703
                            idnum = VAL(LEFT$(e$, INSTR(e$, "³") - 1)) 'id# of sourcetyp

                            '
                            'compare the source and dest. types
                            'print targettyp , sourcetyp
                            'print targettyp and 511, sourcetyp and 511
                            'print targettyp and ISPOINTER, sourcetyp and ISPOINTER
                            'print targettyp and ISUDT, sourcetyp and ISUDT
                            'print targettyp and ISARRAY, sourcetyp and ISARRAY
                            'print targettyp and ISREFERENCE, sourcetyp and ISREFERENCE
                            targettyp2 = targettyp: sourcetyp2 = sourcetyp - ISREFERENCE
                            IF (sourcetyp2 AND ISARRAY) THEN
                                arr = 1: sourcetyp2 = sourcetyp2 - ISARRAY
                            ELSE
                                arr = 0
                            END IF
                            IF (sourcetyp2 AND ISPOINTER) = 0 THEN sourcetyp2 = sourcetyp2 + ISPOINTER
                            IF (sourcetyp2 AND ISINCONVENTIONALMEMORY) THEN sourcetyp2 = sourcetyp2 - ISINCONVENTIONALMEMORY

'make signed/unsigned irrelavent
if targettyp2 and ISUNSIGNED then
if (sourcetyp2 and ISUNSIGNED)=0 then sourcetyp2=sourcetyp2+ISUNSIGNED
end if

'allow passinf of UDT element variable as normal variable
passudtelement=0
if (targettyp2 and ISUDT)=0 then
if sourcetyp2 and ISUDT then sourcetyp2=sourcetyp2-ISUDT: passudtelement=1
end if

                            IF sourcetyp2 = targettyp2 THEN
                                'print "Similar!"
                                IF sourcetyp AND ISUDT THEN
                                    'udt/udt array
                                    getid VAL(e$)
                                    udtrefi = INSTR(e$, "³") 'skip id
                                    udtrefi = INSTR(udtrefi + 1, e$, "³") 'skip u
                                    udtrefi = INSTR(udtrefi + 1, e$, "³") 'skip e
                                    o$ = RIGHT$(e$, LEN(e$) - udtrefi) 'set o$ to the offset
                                    IF arr THEN
                                        n$ = scope$ + "ARRAY_UDT_" + RTRIM$(id.n) + "[0]"
                                    ELSE
                                        n$ = scope$ + "UDT_" + RTRIM$(id.n)
                                    END IF

                                    e$ = "(void*)( ((char*)(" + n$ + ")) + (" + RIGHT$(e$, LEN(e$) - udtrefi) + ") )"

'convert void* to target type*
if passudtelement then e$="("+typ2ctyp$(targettyp2-ISPOINTER,"")+"*)"+e$

                                    'print "passing:"+e$

                                ELSE
                                    'not a udt
                                    IF arr THEN
                                        IF (sourcetyp2 AND ISOFFSETINBITS) THEN qb64error "Cannot pass BIT array offsets yet"
                                        e$ = "(&(" + refer(e$, sourcetyp, 0) + "))"
                                    ELSE
                                        e$ = refer(e$, sourcetyp, 1)
                                    END IF

                                END IF

                                '20090703
                                IF MID$(sfcmemargs(targetid), curarg, 1) = CHR$(1) THEN 'cmem required?
                                    IF cmemlist(idnum) = 0 THEN
                                        cmemlist(idnum) = 1
                                        recompile = 1
                                    END IF
                                END IF

                                GOTO dontevaluate
                            END IF 'similar

                            'IF sourcetyp2 = targettyp2 THEN
                            'IF arr THEN
                            'IF (sourcetyp2 AND ISOFFSETINBITS) THEN qb64error "Cannot pass BIT array offsets yet"
                            'e$ = "(&(" + refer(e$, sourcetyp, 0) + "))"
                            'ELSE
                            'e$ = refer(e$, sourcetyp, 1)
                            'END IF
                            'GOTO dontevaluate
                            'END IF

                        END IF
                    END IF

                END IF 'dereference
            END IF 'pointer




            'IF (targettyp AND ISSTRING) = 0 THEN
            'IF (sourcetyp AND ISREFERENCE) THEN
            'targettyp2 = targettyp: sourcetyp2 = sourcetyp - ISREFERENCE
            'IF (sourcetyp2 AND ISINCONVENTIONALMEMORY) THEN sourcetyp2 = sourcetyp2 - ISINCONVENTIONALMEMORY
            'IF sourcetyp2 = targettyp2 THEN e$ = refer(e$, sourcetyp, 1): GOTO dontevaluate
            'END IF
            'END IF
            'END IF

            'change to "non-pointer" value
            IF (sourcetyp AND ISREFERENCE) THEN
                e$ = refer(e$, sourcetyp, 0)
            END IF

            'round to integer if required
            IF (sourcetyp AND ISFLOAT) THEN
                IF (targettyp AND ISFLOAT) = 0 THEN
                    '**32 rounding fix
                    bits = targettyp AND 511
                    IF bits <= 16 THEN e$ = "qbr_float_to_long(" + e$ + ")"
                    IF bits > 16 AND bits < 32 THEN e$ = "qbr_double_to_long(" + e$ + ")"
                    IF bits >= 32 THEN e$ = "qbr(" + e$ + ")"
                END IF
            END IF

            IF explicitreference THEN
                IF (targettyp AND ISOFFSETINBITS) THEN
                    'integer value can fit inside int64
                    e$ = "(int64)(" + e$ + ")"
                ELSE
                    IF (targettyp AND ISFLOAT) THEN
                        IF (targettyp AND 511) = 32 THEN e$ = "(float)(" + e$ + ")"
                        IF (targettyp AND 511) = 64 THEN e$ = "(double)(" + e$ + ")"
                        IF (targettyp AND 511) = 256 THEN e$ = "(long double)(" + e$ + ")"
                    ELSE
                        IF (targettyp AND ISUNSIGNED) THEN
                            IF (targettyp AND 511) = 8 THEN e$ = "(uint8)(" + e$ + ")"
                            IF (targettyp AND 511) = 16 THEN e$ = "(uint16)(" + e$ + ")"
                            IF (targettyp AND 511) = 32 THEN e$ = "(uint32)(" + e$ + ")"
                            IF (targettyp AND 511) = 64 THEN e$ = "(uint64)(" + e$ + ")"
                        ELSE
                            IF (targettyp AND 511) = 8 THEN e$ = "(int8)(" + e$ + ")"
                            IF (targettyp AND 511) = 16 THEN e$ = "(int16)(" + e$ + ")"
                            IF (targettyp AND 511) = 32 THEN e$ = "(int32)(" + e$ + ")"
                            IF (targettyp AND 511) = 64 THEN e$ = "(int64)(" + e$ + ")"
                        END IF
                    END IF 'float?
                END IF 'offset in bits?
            END IF 'explicit?

            IF (targettyp AND ISPOINTER) THEN 'pointer required
                IF (targettyp AND ISSTRING) THEN GOTO dontevaluate 'no changes required
                '20090703
                t$ = typ2ctyp$(targettyp, "")
                v$ = "pass" + str2$(uniquenumber)
                'assume numeric type
                IF MID$(sfcmemargs(targetid), curarg, 1) = CHR$(1) THEN 'cmem required?
                    bytesreq = ((targettyp AND 511) + 7) \ 8
                    PRINT #defdatahandle, t$ + " *" + v$ + "=NULL;"
                    PRINT #13, "if(" + v$ + "==NULL){"
                    PRINT #13, "cmem_sp-=" + str2(bytesreq) + ";"
                    PRINT #13, v$ + "=(" + t$ + "*)(dblock+cmem_sp);"
                    PRINT #13, "if (cmem_sp<qbs_cmem_sp) error(257);"
                    PRINT #13, "}"
                    e$ = "&(*" + v$ + "=" + e$ + ")"
                ELSE
                    PRINT #13, t$ + " " + v$ + ";"
                    e$ = "&(" + v$ + "=" + e$ + ")"
                END IF
                GOTO dontevaluate
            END IF

            dontevaluate:

if id2.ccall then

if targettyp AND ISSTRING then
e$="(char*)("+e$+")->chr"
end if

if ltrim$(rtrim$(e$))="0" then e$="NULL"

end if



            r$ = r$ + e$
            IF i <> n AND nocomma = 0 THEN r$ = r$ + ","
            nocomma = 0
            firsti = i + 1
            curarg = curarg + 1
        END IF

        IF curarg = skiparg AND i = n THEN
            targettyp = CVL(MID$(id2.arg, curarg * 4 - 4 + 1, 4))
            'IF (targettyp AND ISSTRING) THEN nerror (149)
            r$ = r$ + ",NULL"
            curarg = curarg + 1
        END IF

    NEXT
END IF

IF n$ = "UBOUND" OR n$ = "LBOUND" THEN
    IF r$ = ",NULL" THEN r$ = ",1"
    IF n$ = "UBOUND" THEN r2$ = "func_ubound(" ELSE r2$ = "func_lbound("
    e$ = refer$(ulboundarray$, sourcetyp, 1)
    'note: ID contins refer'ed array info

    arrayelements = id.arrayelements '2009
    IF arrayelements = -1 THEN arrayelements = 1 '2009

    r$ = r2$ + e$ + r$ + "," + str2$(arrayelements) + ")"
    typ& = INTEGER64TYPE - ISPOINTER
    GOTO evalfuncspecial
END IF

IF passomit THEN
    IF skiparg THEN r$ = r$ + ",0" ELSE r$ = r$ + ",1"
END IF
r$ = r$ + ")"

evalfuncspecial:

IF n$ = "ABS" THEN typ& = sourcetyp 'ABS Note: ABS() returns argument #1's type

'QB-like conversion of math functions returning floating point values
IF n$ = "SIN" OR n$ = "COS" OR n$ = "TAN" OR n$ = "ATN" OR n$ = "SQR" OR n$ = "LOG" THEN
    b = sourcetyp AND 511
    IF sourcetyp AND ISFLOAT THEN
        'Default is FLOATTYPE
        IF b = 64 THEN typ& = DOUBLETYPE - ISPOINTER
        IF b = 32 THEN typ& = SINGLETYPE - ISPOINTER
    ELSE
        'Default is FLOATTYPE
        IF b <= 32 THEN typ& = DOUBLETYPE - ISPOINTER
        IF b <= 16 THEN typ& = SINGLETYPE - ISPOINTER
    END IF
END IF

IF debug THEN PRINT #9, "evaluatefunc:out:"; r$
evaluatefunc$ = r$
END FUNCTION

FUNCTION variablesize$ (i AS LONG) 'ID or -1 (if ID already 'loaded')
'Note: assumes whole bytes, no bit offsets/sizes
IF i <> -1 THEN getid i
'find base size from type
t = id.t: IF t = 0 THEN t = id.arraytype
bytes = (t AND 511) \ 8

IF t AND ISUDT THEN 'correct size for UDTs
    u = t AND 511
    bytes = udtxsize(u) \ 8
END IF

IF t AND ISSTRING THEN 'correct size for strings
    IF t AND ISFIXEDLENGTH THEN
        bytes = id.tsize
    ELSE
        IF id.arraytype THEN qb64error "Cannot determine size of variable-length string array"
        variablesize$ = scope$ + "STRING_" + RTRIM$(id.n) + "->len"
        EXIT FUNCTION
    END IF
END IF

IF id.arraytype THEN 'multiply size for arrays
    n$ = RTRIM$(id.callname)
    s$ = str2(bytes) + "*(" + n$ + "[2]&1)" 'note: multiplying by 0 if array not currently defined (affects dynamic arrays)
    arrayelements = id.arrayelements: IF arrayelements = -1 THEN arrayelements = 1 '2009
    FOR i2 = 1 TO arrayelements
        s$ = s$ + "*" + n$ + "[" + str2(i2 * 4 - 4 + 5) + "]"
    NEXT
    variablesize$ = "(" + s$ + ")"
    EXIT FUNCTION
END IF

variablesize$ = str2(bytes)
END FUNCTION



FUNCTION evaluatetotyp$ (a2$, targettyp AS LONG)
'note: 'evaluatetotyp' no longer performs 'fixoperationorder' on a2$ (in many cases, this has already been done)
a$ = a2$
e$ = evaluate(a$, sourcetyp)

IF targettyp = -4 OR targettyp = -5 THEN '? -> byte_element(offset,element size in bytes)
    IF (sourcetyp AND ISREFERENCE) = 0 THEN nerror (62)
    IF (sourcetyp AND ISOFFSETINBITS) THEN nerror (63)

    ' print "-4: evaluated as ["+e$+"]":sleep 1

    IF (sourcetyp AND ISUDT) THEN 'User Defined Type -> byte_element(offset,bytes)
        idnumber = VAL(e$)
        i = INSTR(e$, "³"): e$ = RIGHT$(e$, LEN(e$) - i)
        u = VAL(e$) 'closest parent
        i = INSTR(e$, "³"): e$ = RIGHT$(e$, LEN(e$) - i)
        e = VAL(e$)
        i = INSTR(e$, "³"): e$ = RIGHT$(e$, LEN(e$) - i)
        o$ = e$
        getid idnumber
        n$ = "UDT_" + RTRIM$(id.n)
        IF id.arraytype THEN
            n$ = "ARRAY_" + n$ + "[0]"
            'whole array reference examplename()?
            IF LEFT$(o$, 3) = "(0)" THEN
                'use -2 type method
                GOTO method2usealludt
            END IF
        END IF
        'determine size of element
        IF e = 0 THEN 'no specific element, use size of entire type
            bytes$ = str2(udtxsize(u) \ 8)
        ELSE 'a specific element
            bytes$ = str2(udtesize(e) \ 8)
        END IF
        dst$ = "(((char*)" + scope$ + n$ + ")+(" + o$ + "))"
        evaluatetotyp$ = "byte_element((uint64)" + dst$ + "," + bytes$ + ")"
        IF targettyp = -5 THEN evaluatetotyp$ = bytes$
        EXIT FUNCTION
    END IF

    IF (sourcetyp AND ISARRAY) THEN 'Array reference -> byte_element(offset,bytes)
        'whole array reference examplename()?
        IF RIGHT$(e$, 2) = "³0" THEN
            'use -2 type method
            IF sourcetyp AND ISSTRING THEN
                IF (sourcetyp AND ISFIXEDLENGTH) = 0 THEN
                    qb64error "Cannot pass array of variable-length strings"
                END IF
            END IF
            GOTO method2useall
        END IF
        'assume a specific element
        IF sourcetyp AND ISSTRING THEN
            IF sourcetyp AND ISFIXEDLENGTH THEN
                idnumber = VAL(e$)
                getid idnumber
                bytes$ = str2(id.tsize)
                e$ = refer(e$, sourcetyp, 0)
                evaluatetotyp$ = "byte_element((uint64)" + e$ + "->chr," + bytes$ + ")"
                IF targettyp = -5 THEN evaluatetotyp$ = bytes$
            ELSE
                e$ = refer(e$, sourcetyp, 0)
                evaluatetotyp$ = "byte_element((uint64)" + e$ + "->chr," + e$ + "->len)"
                IF targettyp = -5 THEN evaluatetotyp$ = e$ + "->len"
            END IF
            EXIT FUNCTION
        END IF
        e$ = refer(e$, sourcetyp, 0)
        e$ = "(&(" + e$ + "))"
        bytes$ = str2((sourcetyp AND 511) \ 8)
        evaluatetotyp$ = "byte_element((uint64)" + e$ + "," + bytes$ + ")"
        IF targettyp = -5 THEN evaluatetotyp$ = bytes$
        EXIT FUNCTION
    END IF

    IF sourcetyp AND ISSTRING THEN 'String -> byte_element(offset,bytes)
        IF sourcetyp AND ISFIXEDLENGTH THEN
            idnumber = VAL(e$)
            getid idnumber
            bytes$ = str2(id.tsize)
            e$ = refer(e$, sourcetyp, 0)
        ELSE
            e$ = refer(e$, sourcetyp, 0)
            bytes$ = e$ + "->len"
        END IF
        evaluatetotyp$ = "byte_element((uint64)" + e$ + "->chr," + bytes$ + ")"
        IF targettyp = -5 THEN evaluatetotyp$ = bytes$
        EXIT FUNCTION
    END IF

    'Standard variable -> byte_element(offset,bytes)
    e$ = refer(e$, sourcetyp, 1) 'get the variable's formal name
    size = (sourcetyp AND 511) \ 8 'calculate its size in bytes
    evaluatetotyp$ = "byte_element((uint64)" + e$ + "," + str2(size) + ")"
    IF targettyp = -5 THEN evaluatetotyp$ = str2(size)
    EXIT FUNCTION

END IF '-4



IF targettyp = -2 THEN '? -> byte_element(offset,max possible bytes)
    method2useall:
    ' print "CI: eval2typ detected target type of -2 for ["+a2$+"] evaluated as ["+e$+"]":sleep 1

    IF (sourcetyp AND ISREFERENCE) = 0 THEN nerror (62)
    IF (sourcetyp AND ISOFFSETINBITS) THEN nerror (63)

    'User Defined Type -> byte_element(offset,bytes)
    IF (sourcetyp AND ISUDT) THEN
        '           print "CI: -2 type from a UDT":sleep 1
        idnumber = VAL(e$)
        i = INSTR(e$, "³"): e$ = RIGHT$(e$, LEN(e$) - i)
        u = VAL(e$) 'closest parent
        i = INSTR(e$, "³"): e$ = RIGHT$(e$, LEN(e$) - i)
        e = VAL(e$)
        i = INSTR(e$, "³"): e$ = RIGHT$(e$, LEN(e$) - i)
        o$ = e$
        getid idnumber
        n$ = "UDT_" + RTRIM$(id.n): IF id.arraytype THEN n$ = "ARRAY_" + n$ + "[0]"
        method2usealludt:
        bytes$ = variablesize$(-1) + "-(" + o$ + ")"
        dst$ = "(((char*)" + scope$ + n$ + ")+(" + o$ + "))"
        evaluatetotyp$ = "byte_element((uint64)" + dst$ + "," + bytes$ + ")"
        IF targettyp = -5 THEN evaluatetotyp$ = bytes$
        EXIT FUNCTION
    END IF

    'Array reference -> byte_element(offset,bytes)
    IF (sourcetyp AND ISARRAY) THEN
        'array of variable length strings (special case, can only refer to single element)
        IF sourcetyp AND ISSTRING THEN
            IF (sourcetyp AND ISFIXEDLENGTH) = 0 THEN
                e$ = refer(e$, sourcetyp, 0)
                evaluatetotyp$ = "byte_element((uint64)" + e$ + "->chr," + e$ + "->len)"
                IF targettyp = -5 THEN evaluatetotyp$ = e$ + "->len"
                EXIT FUNCTION
            END IF
        END IF
        idnumber = VAL(e$)
        getid idnumber
        tsize = id.tsize 'used later to determine element size of fixed length strings
        'note: array references consist of idnumber|unmultiplied-element-index
        index$ = RIGHT$(e$, LEN(e$) - INSTR(e$, "³")) 'get element index
        bytes$ = variablesize$(-1)
        e$ = refer(e$, sourcetyp, 0)
        e$ = "(&(" + e$ + "))"
        '           print "CI: array: e$["+e$+"], bytes$["+bytes$+"]":sleep 1
        'calculate size of elements
        IF sourcetyp AND ISSTRING THEN
            bytes = tsize
        ELSE
            bytes = (sourcetyp AND 511) \ 8
        END IF
        bytes$ = bytes$ + "-(" + str2(bytes) + "*(" + index$ + "))"
        evaluatetotyp$ = "byte_element((uint64)" + e$ + "," + bytes$ + ")"
        IF targettyp = -5 THEN evaluatetotyp$ = bytes$
        '           print "CI: array ->["+"byte_element((uint64)" + e$ + "," + bytes$+ ")"+"]":sleep 1
        EXIT FUNCTION
    END IF

    'String -> byte_element(offset,bytes)
    IF sourcetyp AND ISSTRING THEN
        IF sourcetyp AND ISFIXEDLENGTH THEN
            idnumber = VAL(e$)
            getid idnumber
            bytes$ = str2(id.tsize)
            e$ = refer(e$, sourcetyp, 0)
        ELSE
            e$ = refer(e$, sourcetyp, 0)
            bytes$ = e$ + "->len"
        END IF
        evaluatetotyp$ = "byte_element((uint64)" + e$ + "->chr," + bytes$ + ")"
        IF targettyp = -5 THEN evaluatetotyp$ = bytes$
        EXIT FUNCTION
    END IF

    'Standard variable -> byte_element(offset,bytes)
    e$ = refer(e$, sourcetyp, 1) 'get the variable's formal name
    size = (sourcetyp AND 511) \ 8 'calculate its size in bytes
    evaluatetotyp$ = "byte_element((uint64)" + e$ + "," + str2(size) + ")"
    IF targettyp = -5 THEN evaluatetotyp$ = str2(size)
    EXIT FUNCTION

END IF '-2 byte_element(offset,bytes)



'string?
IF (sourcetyp AND ISSTRING) <> (targettyp AND ISSTRING) THEN
    nerror (77)
END IF

IF (sourcetyp AND ISSTRING) THEN
    evaluatetotyp$ = e$
    IF (sourcetyp AND ISREFERENCE) THEN
        evaluatetotyp$ = refer(e$, sourcetyp, 0)
    END IF
    EXIT FUNCTION
END IF

'pointer required?
IF (targettyp AND ISPOINTER) THEN
    nerror (78)
    '...
    nerror (79)
END IF

'change to "non-pointer" value
IF (sourcetyp AND ISREFERENCE) THEN
    e$ = refer(e$, sourcetyp, 0)
END IF
'check if successful
IF (sourcetyp AND ISPOINTER) THEN
    nerror (80)
END IF

'round to integer if required
IF (sourcetyp AND ISFLOAT) THEN
    IF (targettyp AND ISFLOAT) = 0 THEN
        bits = targettyp AND 511
        '**32 rounding fix
        IF bits <= 16 THEN e$ = "qbr_float_to_long(" + e$ + ")"
        IF bits > 16 AND bits < 32 THEN e$ = "qbr_double_to_long(" + e$ + ")"
        IF bits >= 32 THEN e$ = "qbr(" + e$ + ")"
    END IF
END IF

evaluatetotyp$ = e$
END FUNCTION

FUNCTION findid& (n2$)
n$ = UCASE$(n2$) 'case insensitive

'return all strings as 'not found'
IF ASC(n$) = 34 THEN GOTO noid

'if findidsecondarg was set, it will be used for finding the name of a sub (not a func or variable)
secondarg$ = findidsecondarg: findidsecondarg = ""

'if findanotherid was set, findid will continue scan from last index, otherwise, it will begin a new search
findanother = findanotherid: findanotherid = 0
IF findanother <> 0 AND findidinternal <> 2 THEN nerror (81) 'cannot continue search, no more indexes left!
'(the above should never happen)
findid& = 2 '2=not finished searching all indexes

'seperate symbol from name (if a symbol has been added), this is the only way symbols can be passed to findid
i = 0
i = INSTR(n$, "~"): IF i THEN GOTO gotsc
i = INSTR(n$, "`"): IF i THEN GOTO gotsc
i = INSTR(n$, "%"): IF i THEN GOTO gotsc
i = INSTR(n$, "&"): IF i THEN GOTO gotsc
i = INSTR(n$, "!"): IF i THEN GOTO gotsc
i = INSTR(n$, "#"): IF i THEN GOTO gotsc
i = INSTR(n$, "$"): IF i THEN GOTO gotsc
gotsc:
IF i THEN
    sc$ = RIGHT$(n$, LEN(n$) - i + 1): n$ = LEFT$(n$, i - 1)
    IF sc$ = "`" OR sc$ = "~`" THEN sc$ = sc$ + "1" 'clarify abbreviated 1 bit reference
ELSE
    'no symbol passed, so check what symbol could be assumed under the current DEF...
    v = ASC(n$): IF v = 95 THEN v = 27 ELSE v = v - 64
    IF v >= 1 AND v <= 27 THEN 'safeguard against n$ not being a standard name
        couldhavesc$ = defineextaz(v)
        IF couldhavesc$ = "`" OR couldhavesc$ = "~`" THEN couldhavesc$ = couldhavesc$ + "1" 'clarify abbreviated 1 bit reference
    END IF 'safeguard
END IF

'optomizations for later comparisons
insf$ = subfunc + SPACE$(256 - LEN(subfunc))
secondarg$ = secondarg$ + SPACE$(256 - LEN(secondarg$))
IF LEN(sc$) THEN scpassed = 1: sc$ = sc$ + SPACE$(8 - LEN(sc$)) ELSE scpassed = 0
IF LEN(couldhavesc$) THEN couldhavesc$ = couldhavesc$ + SPACE$(8 - LEN(couldhavesc$)): couldhavescpassed = 1 ELSE couldhavescpassed = 0
IF LEN(n$) < 256 THEN n$ = n$ + SPACE$(256 - LEN(n$))

'FUNCTION HashFind (a$, searchflags, resultflags, resultreference)
'(0,1,2)z=hashfind[rev]("RUMI",Hashflag_label,resflag,resref)
'0=doesn't exist
'1=found, no more items to scan
'2=found, more items still to scan

'NEW HASH SYSTEM
n$=rtrim$(n$)
if findanother then
hashretry:
z=HashFindCont(unrequired,i)
else
z=HashFindRev(n$,1,unrequired,i)
end if
findidinternal=z
if z=0 then goto noid
findid = z


'continue from previous position?
''IF findanother THEN start = findidinternal ELSE start = idn

''FOR i = start TO 1 STEP -1

''    findidinternal = i - 1
''    IF findidinternal = 0 THEN findid& = 1 '1=found id, but no more to search

''    IF ids(i).n = n$ THEN 'same name?

        'in scope?
        IF ids(i).subfunc = 0 AND ids(i).share = 0 THEN 'scope check required (not a shared variable or the name of a sub/function)
            IF ids(i).insubfunc <> insf$ THEN GOTO findidnomatch
        END IF

        'some subs require a second argument (eg. PUT #, DEF SEG, etc.)
        IF ids(i).subfunc = 2 THEN
            IF ASC(ids(i).secondargmustbe) <> 32 THEN 'exists?
                IF secondarg$ <> ids(i).secondargmustbe THEN GOTO findidnomatch
            END IF
            IF ASC(ids(i).secondargcantbe) <> 32 THEN 'exists?
                IF secondarg$ = ids(i).secondargcantbe THEN GOTO findidnomatch
            END IF
        END IF 'second sub argument possible

        'must have symbol?
        'typically for variables defined automatically or by a symbol and not the full type name
        imusthave = CVI(ids(i).musthave) 'speed up checks of first 2 characters
        amusthave = imusthave AND 255 'speed up checks of first character
        IF amusthave <> 32 THEN
            IF scpassed THEN
                IF sc$ = ids(i).musthave THEN GOTO findidok
            END IF
            IF couldhavescpassed THEN
                IF couldhavesc$ = ids(i).musthave THEN GOTO findidok
            END IF
            'note: symbol defined fixed length strings cannot be referred to by $ without an extension
            'note: sc$ and couldhavesc$ are already changed from ` to `1 to match stored musthave
            GOTO findidnomatch
        END IF

        'may have symbol?
        'typically for variables formally dim'd
        'note: couldhavesc$ needn't be considered for mayhave checks
        IF scpassed THEN 'symbol was passed, so it must match the mayhave symbol
            imayhave = CVI(ids(i).mayhave) 'speed up checks of first 2 characters
            amayhave = imayhave AND 255 'speed up checks of first character
            IF amayhave = 32 THEN GOTO findidnomatch 'it cannot have the symbol passed (nb. musthave symbols have already been ok'd)
            'note: variable length strings are not a problem here, as they can only have one possible extension
            IF amayhave = 36 THEN '"$"
                IF imayhave <> 8228 THEN '"$ "
                    'it is a fixed length string
                    IF CVI(sc$) = 8228 THEN GOTO findidok 'allow myvariable$ to become myvariable$10
                    'allow later comparison to verify if extension is correct
                END IF
            END IF
            IF sc$ <> ids(i).mayhave THEN GOTO findidnomatch
        END IF 'scpassed

        'return id
        findidok:

        id = ids(i)

        currentid = i
        EXIT FUNCTION

    'END IF 'same name
    findidnomatch:
'NEXT
if z=2 then goto hashretry

'totally unclassifiable
noid:
findid& = 0
currentid = -1
END FUNCTION

FUNCTION findvariable (secure$)
'only used in const equation and for statement. consider making redundant.

n$ = secure$
IF debug THEN PRINT #9, "func findvariable:in:" + n$

'assumes the variable is not an array!

'sets idz to hold info about the variable wanted
'also creates variables if they don't exist

'establish whether v$ includes an extension
i = INSTR(n$, "~"): IF i THEN sc$ = RIGHT$(n$, LEN(n$) - i + 1): n$ = LEFT$(n$, i - 1): GOTO gotsc2
i = INSTR(n$, "`"): IF i THEN sc$ = RIGHT$(n$, LEN(n$) - i + 1): n$ = LEFT$(n$, i - 1): GOTO gotsc2
i = INSTR(n$, "%"): IF i THEN sc$ = RIGHT$(n$, LEN(n$) - i + 1): n$ = LEFT$(n$, i - 1): GOTO gotsc2
i = INSTR(n$, "&"): IF i THEN sc$ = RIGHT$(n$, LEN(n$) - i + 1): n$ = LEFT$(n$, i - 1): GOTO gotsc2
i = INSTR(n$, "!"): IF i THEN sc$ = RIGHT$(n$, LEN(n$) - i + 1): n$ = LEFT$(n$, i - 1): GOTO gotsc2
i = INSTR(n$, "#"): IF i THEN sc$ = RIGHT$(n$, LEN(n$) - i + 1): n$ = LEFT$(n$, i - 1): GOTO gotsc2
i = INSTR(n$, "$"): IF i THEN sc$ = RIGHT$(n$, LEN(n$) - i + 1): n$ = LEFT$(n$, i - 1): GOTO gotsc2
gotsc2:
n2$ = n$ + sc$

IF sc$ <> "" THEN
    'has an extension
    'note! findid must unambiguify ` to `5 or $ to $10 where applicable
    'pass variable with extension
    try = findid(n2$)
    DO WHILE try
        IF id.t THEN 'check it is a variable and not something else
            'id is already set correctly, so simply return found variable
            EXIT FUNCTION
        END IF
        IF try = 2 THEN findanotherid = 1: try = findid(n2$) ELSE try = 0
    LOOP
    GOTO createunknownvariable
    EXIT FUNCTION
ELSE
    'no extension
    '1. pass as is, without any extension



    try = findid(n2$)
    DO WHILE try
        IF id.t THEN 'check it is a variable and not something else
            'id is already set correctly, so simply return found variable
            EXIT FUNCTION
        END IF
        IF try = 2 THEN findanotherid = 1: try = findid(n2$) ELSE try = 0
    LOOP

    '2. that failed, so apply the _define'd extension and pass
    'note! valid variable names start with

    IF debug THEN PRINT #9, "func findvariable:try add ext:" + n$


    a = ASC(UCASE$(n$)): IF a = 95 THEN a = 91
    a = a - 64 'so A=1, Z=27 and _=28
    n2$ = n$ + defineextaz(a)
    try = findid(n2$)
    DO WHILE try
        IF id.t THEN 'check it is a variable and not something else
            'id is already set correctly, so simply return found variable
            EXIT FUNCTION
        END IF
        IF try = 2 THEN findanotherid = 1: try = findid(n2$) ELSE try = 0
    LOOP
    GOTO createunknownvariable
END IF
createunknownvariable:

typ$ = removesymbol$(n2$)
retval = dim2(n2$, typ$, 1, "")

'create variable n2$
IF debug THEN PRINT #9, "CREATING VARIABLE:" + n2$
'ignore = createquickvariable(n2$)

END FUNCTION

FUNCTION fixoperationorder$ (savea$)
a$ = savea$
IF debug THEN PRINT #9, "fixoperationorder:in:" + a$

fooindwel = fooindwel + 1

n = numelements(a$) 'n is maintained throughout function

IF fooindwel = 1 THEN 'actions to take on initial call only

    '----------------A. 'Quick' mismatched brackets check----------------
    b = 0
    a2$ = sp + a$ + sp
    b1$ = sp + "(" + sp
    b2$ = sp + ")" + sp
    i = 1
    findmmb:
    i1 = INSTR(i, a2$, b1$)
    i2 = INSTR(i, a2$, b2$)
    i3 = i1
    IF i2 THEN
        IF i1 = 0 THEN
            i3 = i2
        ELSE
            IF i2 < i1 THEN i3 = i2
        END IF
    END IF
    IF i3 THEN
        IF i3 = i1 THEN b = b + 1
        IF i3 = i2 THEN b = b - 1
        i = i3 + 2
        IF b < 0 THEN qb64error "Missing ("
        GOTO findmmb
    END IF
    IF b > 0 THEN qb64error "Missing )"

    '----------------B. 'Quick' correction of over-use of +,- ----------------
    'note: the results of this change are beneficial to foolayout
    a2$ = sp + a$ + sp

    'rule 1: change ++ to +
    rule1:
    i = INSTR(a2$, sp + "+" + sp + "+" + sp)
    IF i THEN
        a2$ = LEFT$(a2$, i + 2) + RIGHT$(a2$, LEN(a2$) - i - 4)
        a$ = MID$(a2$, 2, LEN(a2$) - 2)
        n = n - 1
        IF debug THEN PRINT #9, "fixoperationorder:+/-:" + a$
        GOTO rule1
    END IF

    'rule 2: change -+ to -
    rule2:
    i = INSTR(a2$, sp + "-" + sp + "+" + sp)
    IF i THEN
        a2$ = LEFT$(a2$, i + 2) + RIGHT$(a2$, LEN(a2$) - i - 4)
        a$ = MID$(a2$, 2, LEN(a2$) - 2)
        n = n - 1
        IF debug THEN PRINT #9, "fixoperationorder:+/-:" + a$
        GOTO rule2
    END IF

    'rule 3: change anyoperator-- to anyoperator
    rule3:
    IF INSTR(a2$, sp + "-" + sp + "-" + sp) THEN
        FOR i = 1 TO n - 2
            IF isoperator(getelement(a$, i)) THEN
                IF getelement(a$, i + 1) = "-" THEN
                    IF getelement(a$, i + 2) = "-" THEN
                        removeelements a$, i + 1, i + 2, 0
                        a2$ = sp + a$ + sp
                        n = n - 2
                        IF debug THEN PRINT #9, "fixoperationorder:+/-:" + a$
                        GOTO rule3
                    END IF
                END IF
            END IF
        NEXT
    END IF 'rule 3



    '----------------C. 'Quick' location of negation----------------
    'note: the results of this change are beneficial to foolayout

    'for numbers...
    'before: anyoperator,-,number
    'after:  anyoperator,-number

    'for variables...
    'before: anyoperator,-,variable
    'after:  anyoperator,ñ,variable

    'exception for numbers followed by ^... (they will be bracketed up along with the ^ later)
    'before: anyoperator,-,number,^
    'after:  anyoperator,ñ,number,^

    FOR i = 1 TO n - 1
        IF i > n - 1 THEN EXIT FOR 'n changes, so manually exit if required

        IF ASC(getelement(a$, i)) = 45 THEN '-

            neg = 0
            IF i = 1 THEN
                neg = 1
            ELSE
                a2$ = getelement(a$, i - 1)
                c = ASC(a2$)
                IF c = 40 OR c = 44 THEN '(,
                    neg = 1
                ELSE
                    IF isoperator(a2$) THEN neg = 1
                END IF '()
            END IF 'i=1
            IF neg = 1 THEN

                a2$ = getelement(a$, i + 1)
                c = ASC(a2$)
                IF c >= 48 AND c <= 57 THEN
                    c2 = 0: IF i < n - 1 THEN c2 = ASC(getelement(a$, i + 2))
                    IF c2 <> 94 THEN 'not ^
                        'number...
                        i2 = INSTR(a2$, ",")
                        IF i2 AND ASC(a2$, i2 + 1) <> 38 THEN '&H/&O/&B values don't need the assumed negation
                            a2$ = "-" + LEFT$(a2$, i2) + "-" + RIGHT$(a2$, LEN(a2$) - i2)
                        ELSE
                            a2$ = "-" + a2$
                        END IF
                        removeelements a$, i, i + 1, 0
                        insertelements a$, i - 1, a2$
                        n = n - 1
                        IF debug THEN PRINT #9, "fixoperationorder:negation:" + a$

                        GOTO negdone
                    END IF
                END IF


                'not a number (or for exceptions)...
                removeelements a$, i, i, 0
                insertelements a$, i - 1, "ñ"
                IF debug THEN PRINT #9, "fixoperationorder:negation:" + a$

            END IF 'isoperator
        END IF '-
        negdone:
    NEXT



END IF 'fooindwel=1



'----------------D. 'Quick' Add 'power of' with negation {}bracketing to bottom bracket level----------------
pownegused = 0
powneg:
IF INSTR(a$, "^" + sp + "ñ") THEN 'quick check
    b = 0
    b1 = 0
    FOR i = 1 TO n
        a2$ = getelement(a$, i)
        c = ASC(a2$)
        IF c = 40 THEN b = b + 1
        IF c = 41 THEN b = b - 1
        IF b = 0 THEN
            IF b1 THEN
                IF isoperator(a2$) THEN
                    IF a2$ <> "^" AND a2$ <> "ñ" THEN
                        insertelements a$, i - 1, "}"
                        insertelements a$, b1, "{"
                        n = n + 2
                        IF debug THEN PRINT #9, "fixoperationorder:^-:" + a$
                        GOTO powneg
                        pownegused = 1
                    END IF
                END IF
            END IF
            IF c = 94 THEN '^
                IF getelement$(a$, i + 1) = "ñ" THEN b1 = i: i = i + 1
            END IF
        END IF 'b=0
    NEXT i
    IF b1 THEN
        insertelements a$, b1, "{"
        a$ = a$ + sp + "}"
        n = n + 2
        IF debug THEN PRINT #9, "fixoperationorder:^-:" + a$
        pownegused = 1
        GOTO powneg
    END IF

END IF 'quick check



'----------------E. Find lowest & highest operator level in bottom bracket level----------------
lco = 255
hco = 0
b = 0
FOR i = 1 TO n
    a2$ = getelement(a$, i)
    c = ASC(a2$)
    IF c = 40 OR c = 123 THEN b = b + 1
    IF c = 41 OR c = 125 THEN b = b - 1
    IF b = 0 THEN
        op = isoperator(a2$)
        IF op THEN
            IF op < lco THEN lco = op
            IF op > hco THEN hco = op
        END IF
    END IF
NEXT

'----------------F. Add operator {}bracketting----------------
'apply bracketting only if required
IF hco <> 0 THEN 'operators were used
    IF lco <> hco THEN
        'brackets needed
        n2 = n
        b = 0
        a3$ = "{"
        n = 1
        FOR i = 1 TO n2
            a2$ = getelement(a$, i)
            c = ASC(a2$)
            IF c = 40 OR c = 123 THEN b = b + 1
            IF c = 41 OR c = 125 THEN b = b - 1
            IF b = 0 THEN
                op = isoperator(a2$)
                IF op = lco THEN
                    IF i = 1 THEN
                        a3$ = a2$ + sp + "{"
                        n = 2
                    ELSE
                        a3$ = a3$ + sp + "}" + sp + a2$ + sp + "{"
                        n = n + 3
                    END IF
                    GOTO fixop0
                END IF

            END IF 'b=0
            a3$ = a3$ + sp + a2$
            n = n + 1
            fixop0:
        NEXT
        a3$ = a3$ + sp + "}"
        n = n + 1
        a$ = a3$
        IF debug THEN PRINT #9, "fixoperationorder:lco bracketing["; lco; ","; hco; "]:" + a$



        '--------(F)G. Remove indwelling {}bracketting from power-negation--------
        IF pownegused THEN
            b = 0
            i = 0
            DO WHILE i <= n
                i = i + 1
                c = ASC(getelement(a$, i))
                IF c = 41 OR c = 125 THEN b = b - 1
                IF (c = 123 OR c = 125) AND b <> 0 THEN
                    removeelements a$, i, i, 0
                    n = n - 1
                    i = i - 1
                    IF debug THEN PRINT #9, "fixoperationorder:^- {} removed:" + a$
                END IF
                IF c = 40 OR c = 123 THEN b = b + 1
            LOOP
        END IF 'pownegused

    END IF 'lco <> hco
END IF 'hco <> 0

'----------------H. Identification/conversion of elements within bottom bracket level----------------
'actions performed:
'   ->builds f$(tlayout)
'   ->adds symbols to all numbers
'   ->evaluates constants to numbers

f$ = ""
b = 0
c = 0
FOR i = 1 TO n
    f2$ = getelement(a$, i)
    lastc = c
    c = ASC(f2$)

    IF c = 40 OR c = 123 THEN
        IF c <> 40 OR b <> 0 THEN f2$ = "" 'skip temporary & indwelling  brackets
        b = b + 1
        GOTO classdone
    END IF
    IF c = 41 OR c = 125 THEN
        b = b - 1
        IF c <> 41 OR b <> 0 THEN f2$ = "" 'skip temporary & indwelling  brackets
        GOTO classdone
    END IF

    IF b = 0 THEN

        'classifications/conversions:
        '1. quoted string ("....)
        '2. number
        '3. operator
        '4. constant
        '5. variable/array/udt/function (note: nothing can share the same name as a function except a label)


        'quoted string?
        IF c = 34 THEN '"
            'convert \\ to \
            'convert \??? to CHR$(&O???)
            x2 = 1
            x = INSTR(x2, f2$, "\")
            DO WHILE x
                c2 = ASC(f2$, x + 1)
                IF c2 = 92 THEN '\\
                    f2$ = LEFT$(f2$, x) + RIGHT$(f2$, LEN(f2$) - x - 1) 'remove second \
                    x2 = x + 1
                ELSE
                    'octal triplet value
                    c3 = (ASC(f2$, x + 3) - 48) + (ASC(f2$, x + 2) - 48) * 8 + (ASC(f2$, x + 1) - 48) * 64
                    f2$ = LEFT$(f2$, x - 1) + CHR$(c3) + RIGHT$(f2$, LEN(f2$) - x - 3)
                    x2 = x + 1
                END IF
                x = INSTR(x2, f2$, "\")
            LOOP
            'remove ',len' (if it exists)
            x = INSTR(2, f2$, CHR$(34) + ","): IF x THEN f2$ = LEFT$(f2$, x)
            GOTO classdone
        END IF

        'number?
        IF (c >= 48 AND c <= 57) OR c = 45 THEN

            x = INSTR(f2$, ",")
            IF x THEN
                removeelements a$, i, i, 0: insertelements a$, i - 1, LEFT$(f2$, x - 1)
                f2$ = RIGHT$(f2$, LEN(f2$) - x)
            END IF

            IF x = 0 THEN
                c2 = ASC(f2$, LEN(f2$))
                IF c2 < 48 OR c2 > 57 THEN
                    x = 1 'extension given
                ELSE
                    x = INSTR(f2$, "`")
                END IF
            END IF

            'add appropriate integer symbol if none present
            IF x = 0 THEN
                f3$ = f2$
                s$ = ""
                IF c = 45 THEN
                    s$ = "&&"
                    IF f3$ <= "-2147483648" OR LEN(f3$) < 11 THEN s$ = "&"
                    IF f3$ <= "-32768" OR LEN(f3$) < 6 THEN s$ = "%"
                ELSE
                    s$ = "~&&"
                    IF f3$ <= "9223372036854775807" OR LEN(f3$) < 19 THEN s$ = "&&"
                    IF f3$ <= "2147483647" OR LEN(f3$) < 10 THEN s$ = "&"
                    IF f3$ <= "32767" OR LEN(f3$) < 5 THEN s$ = "%"
                END IF
                f3$ = f3$ + s$
                removeelements a$, i, i, 0: insertelements a$, i - 1, f3$
            END IF 'x=0

            GOTO classdone
        END IF

        'operator?
        IF isoperator(f2$) THEN
            IF LEN(f2$) > 1 THEN
                IF f2$ <> UCASE$(f2$) THEN
                    f2$ = UCASE$(f2$)
                    removeelements a$, i, i, 0
                    insertelements a$, i - 1, f2$
                END IF
            END IF
            'append negation
            IF f2$ = "ñ" THEN f$ = f$ + sp + "-": GOTO classdone_special
            GOTO classdone
        END IF


        IF alphanumeric(c) THEN
            IF i < n THEN nextc = ASC(getelement(a$, i + 1)) ELSE nextc = 0

            IF nextc <> 40 THEN '<>"(" (not an array)
                IF lastc <> 46 THEN '<>"." (not an element of a UDT)

                    e$ = UCASE$(f2$)
                    es$ = removesymbol$(e$)
                    FOR i2 = constlast TO 0 STEP -1
                        IF e$ = constname(i2) THEN

                            'is a STATIC variable overriding this constant?
                            staticvariable = 0
                            try = findid(e$ + es$)
                            DO WHILE try
                                IF id.arraytype = 0 THEN staticvariable = 1: EXIT DO 'if it's not an array, it's probably a static variable
                                IF try = 2 THEN findanotherid = 1: try = findid(e$ + es$) ELSE try = 0
                            LOOP
                            IF staticvariable = 0 THEN

                                t = consttype(i2)
                                IF t AND ISSTRING THEN
                                    IF LEN(es$) > 0 AND es$ <> "$" THEN qb64error "Type mismatch"
                                    e$ = conststring(i2)
                                ELSE 'not a string
                                    IF LEN(es$) THEN et = typname2typ(es$) ELSE et = 0
                                    IF et AND ISSTRING THEN qb64error "Type mismatch"
                                    'convert value to general formats
                                    IF t AND ISFLOAT THEN
                                        v## = constfloat(i2)
                                        v&& = v##
                                        v~&& = v&&
                                    ELSE
                                        IF t AND ISUNSIGNED THEN
                                            v~&& = constuinteger(i2)
                                            v&& = v~&&
                                            v## = v&&
                                        ELSE
                                            v&& = constinteger(i2)
                                            v## = v&&
                                            v~&& = v&&
                                        END IF
                                    END IF
                                    'apply type conversion if necessary
                                    IF et THEN t = et
                                    '(todo: range checking)
                                    'convert value into string for returning
                                    IF t AND ISFLOAT THEN
                                        e$ = LTRIM$(RTRIM$(STR$(v##)))
                                    ELSE
                                        IF t AND ISUNSIGNED THEN
                                            e$ = LTRIM$(RTRIM$(STR$(v~&&)))
                                        ELSE
                                            e$ = LTRIM$(RTRIM$(STR$(v&&)))
                                        END IF
                                    END IF

                                    'floats returned by str$ must be converted to qb64 standard format
                                    IF t AND ISFLOAT THEN
                                        t2 = t AND 511
                                        'find E,D or F
                                        s$ = ""
                                        IF INSTR(e$, "E") THEN s$ = "E"
                                        IF INSTR(e$, "D") THEN s$ = "D"
                                        IF INSTR(e$, "F") THEN s$ = "F"
                                        IF LEN(s$) THEN
                                            'E,D,F found
                                            x = INSTR(e$, s$)
                                            'as incorrect type letter may have been returned by STR$, override it
                                            IF t2 = 32 THEN s$ = "E"
                                            IF t2 = 64 THEN s$ = "D"
                                            IF t2 = 256 THEN s$ = "F"
                                            MID$(e$, x, 1) = s$
                                            IF INSTR(e$, ".") = 0 THEN e$ = LEFT$(e$, x - 1) + ".0" + RIGHT$(e$, LEN(e$) - x + 1): x = x + 2
                                            IF LEFT$(e$, 1) = "." THEN e$ = "0" + e$
                                            IF LEFT$(e$, 2) = "-." THEN e$ = "-0" + RIGHT$(e$, LEN(e$) - 1)
                                            IF INSTR(e$, "+") = 0 AND INSTR(e$, "-") = 0 THEN
                                                e$ = LEFT$(e$, x) + "+" + RIGHT$(e$, LEN(e$) - x)
                                            END IF
                                        ELSE
                                            'E,D,F not found
                                            IF INSTR(e$, ".") = 0 THEN e$ = e$ + ".0"
                                            IF LEFT$(e$, 1) = "." THEN e$ = "0" + e$
                                            IF LEFT$(e$, 2) = "-." THEN e$ = "-0" + RIGHT$(e$, LEN(e$) - 1)
                                            IF t2 = 32 THEN e$ = e$ + "E+0"
                                            IF t2 = 64 THEN e$ = e$ + "D+0"
                                            IF t2 = 256 THEN e$ = e$ + "F+0"
                                        END IF
                                    ELSE
                                        s$ = typevalue2symbol$(t)
                                        e$ = e$ + s$ 'simply append symbol to integer
                                    END IF

                                END IF 'not a string

                                removeelements a$, i, i, 0
                                insertelements a$, i - 1, e$
                                'alter f2$ here to original casing
                                f2$ = constcname(i2)+es$
                                GOTO classdone

                            END IF 'not static
                        END IF 'same name
                    NEXT
                END IF 'not udt element
            END IF 'not array
            'REFERENCE:
            'dim shared constmax as long
            'constmax=10000
            'dim shared constlast as long
            'constlast=-1
            'dim shared constname(constmax) as STRING
            'dim shared constnamesymbol (constmax) as STRING 'optional name symbol
            '' `1 and `no-number must be handled correctly
            'dim shared constlastshared as LONG 'so any defined inside a sub/function after this index can be "forgotten" when sub/function exits
            'constlastshared=-1
            'dim shared consttype(constmax) as LONG 'variable type number
            ''consttype determines storage
            'dim shared constinteger(constmax) as _INTEGER64
            'dim shared constuinteger(constmax) as _UNSIGNED _INTEGER64
            'dim shared constfloat(constmax) as _FLOAT
            'dim shared conststring(constmax) as STRING


            'variable/array/udt?
            u$ = f2$
            try = findid(f2$)
            DO WHILE try
                IF debug THEN PRINT #9, "found id matching " + f2$

                IF nextc = 40 THEN '(

                    'function or array?
                    IF id.arraytype <> 0 OR id.subfunc = 1 THEN
                        'note: even if it's an array of UDTs, the bracketted index will follow immediately

                        'correct name
                        f3$ = f2$
                        s$ = removesymbol$(f3$)
                        f2$ = RTRIM$(id.cn) + s$
                        removeelements a$, i, i, 0
                        insertelements a$, i - 1, UCASE$(f2$)
                        f$ = f$ + f2$ + sp + "(" + sp

                        'skip (but record with nothing inside them) brackets
                        b2 = 1 'already in first bracket
                        FOR i2 = i + 2 TO n
                            c2 = ASC(getelement(a$, i2))
                            IF c2 = 40 THEN b2 = b2 + 1
                            IF c2 = 41 THEN b2 = b2 - 1
                            IF b2 = 0 THEN EXIT FOR 'note: mismatched brackets check ensures this always succeeds
                            f$ = f$ + sp
                        NEXT

                        'adjust i accordingly
                        i = i2

                        f$ = f$ + ")"

                        'jump to UDT section if array is of UDT type (and elements are referenced)
                        IF id.arraytype AND ISUDT THEN
                            IF i < n THEN nextc = ASC(getelement(a$, i + 1)) ELSE nextc = 0
                            IF nextc = 46 THEN t = id.arraytype: GOTO fooudt
                        END IF

                        f$ = f$ + sp
                        GOTO classdone_special
                    END IF 'id.arraytype
                END IF 'nextc "("

                IF nextc <> 40 THEN 'not "(" (this avoids confusing simple variables with arrays)
                    IF id.t <> 0 OR id.subfunc = 1 THEN 'simple variable or function (without parameters)

                        IF id.t AND ISUDT THEN
                            'note: it may or may not be followed by a period (eg. if whole udt is being referred to)
                            'check if next item is a period

                            'correct name
                            f2$ = RTRIM$(id.cn) + removesymbol$(f2$)
                            removeelements a$, i, i, 0
                            insertelements a$, i - 1, UCASE$(f2$)
                            f$ = f$ + f2$



                            IF nextc <> 46 THEN f$ = f$ + sp: GOTO classdone_special 'no sub-elements referenced
                            t = id.t

                            fooudt:

                            f$ = f$ + sp + "." + sp
                            e = udtxnext(t AND 511) 'next element to check
                            i = i + 2

                            'loop

                            '"." encountered, i must be an element
                            IF i > n THEN qb64error "Expected .element"
                            f2$ = getelement(a$, i)
                            s$ = removesymbol$(f2$)
                            u$ = UCASE$(f2$) + SPACE$(256 - LEN(f2$)) 'fast scanning

                            'is f$ the same as element e?
                            fooudtnexte:
                            IF udtename(e) = u$ THEN
                                'match found
                                'todo: check symbol(s$) matches element's type

                                'correct name
                                f2$ = RTRIM$(udtecname(e)) + s$
                                removeelements a$, i, i, 0
                                insertelements a$, i - 1, UCASE$(f2$)
                                f$ = f$ + f2$

                                IF i = n THEN f$ = f$ + sp: GOTO classdone_special
                                nextc = ASC(getelement(a$, i + 1))
                                IF nextc <> 46 THEN f$ = f$ + sp: GOTO classdone_special 'no sub-elements referenced
                                'sub-element exists
                                t = udtetype(e)
                                IF (t AND ISUDT) = 0 THEN qb64error "Invalid . after element"
                                GOTO fooudt

                            END IF 'match found

                            'no, so check next element
                            e = udtenext(e)
                            IF e = 0 THEN qb64error "Element not defined"
                            GOTO fooudtnexte

                        END IF 'udt

                        'non array/udt based variable
                        f3$ = f2$
                        s$ = removesymbol$(f3$)
                        f2$ = RTRIM$(id.cn) + s$
                        'change was is returned to uppercase
                        removeelements a$, i, i, 0
                        insertelements a$, i - 1, UCASE$(f2$)
                        EXIT DO
                    END IF 'id.t

                END IF 'nextc not "("

                IF try = 2 THEN findanotherid = 1: try = findid(f2$) ELSE try = 0
            LOOP

            'alphanumeric, but item name is unknown... is it an internal type? if so, use capitals
            f3$ = UCASE$(f2$)
            internaltype = 0
            IF f3$ = "_UNSIGNED" THEN internaltype = 1
            IF f3$ = "_BIT" THEN internaltype = 1
            IF f3$ = "_BYTE" THEN internaltype = 1
            IF f3$ = "INTEGER" THEN internaltype = 1
            IF f3$ = "LONG" THEN internaltype = 1
            IF f3$ = "_INTEGER64" THEN internaltype = 1
            IF f3$ = "SINGLE" THEN internaltype = 1
            IF f3$ = "DOUBLE" THEN internaltype = 1
            IF f3$ = "_FLOAT" THEN internaltype = 1
            IF internaltype = 1 THEN
                f2$ = f3$
                removeelements a$, i, i, 0
                insertelements a$, i - 1, f3$
                GOTO classdone
            END IF

            GOTO classdone
        END IF 'alphanumeric

        classdone:
        f$ = f$ + f2$
    END IF 'b=0
    f$ = f$ + sp
    classdone_special:
NEXT
IF LEN(f$) THEN f$ = LEFT$(f$, LEN(f$) - 1) 'remove trailing 'sp'

IF debug THEN PRINT #9, "fixoperationorder:identification:" + a$, n
IF debug THEN PRINT #9, "fixoperationorder:identification(layout):" + f$, n


'----------------I. Pass (){}bracketed items (if any) to fixoperationorder & build return----------------
'note: items seperated by commas are done seperately

ff$ = ""
b = 0
b2 = 0
p1 = 0 'where level 1 began
aa$ = ""
n = numelements(a$)
FOR i = 1 TO n

    openbracket = 0

    a2$ = getelement(a$, i)

    c = ASC(a2$)



    IF c = 40 OR c = 123 THEN '({
        b = b + 1

        IF b = 1 THEN




            p1 = i + 1
            aa$ = aa$ + "(" + sp

        END IF

        openbracket = 1

        GOTO foopass

    END IF '({

    IF c = 44 THEN ',
        IF b = 1 THEN
            GOTO foopassit
        END IF
    END IF

    IF c = 41 OR c = 125 THEN ')}
        b = b - 1

        IF b = 0 THEN
            foopassit:
            IF p1 <> i THEN
                foo$ = fixoperationorder(getelements(a$, p1, i - 1))
                IF LEN(foo$) THEN
                    aa$ = aa$ + foo$ + sp
                    IF c = 125 THEN ff$ = ff$ + tlayout$ + sp ELSE ff$ = ff$ + tlayout$ + sp2 'spacing between ) } , varies
                END IF
            END IF
            IF c = 44 THEN aa$ = aa$ + "," + sp: ff$ = ff$ + "," + sp ELSE aa$ = aa$ + ")" + sp
            p1 = i + 1
        END IF

        GOTO foopass
    END IF ')}




    IF b = 0 THEN aa$ = aa$ + a2$ + sp


    foopass:

    f2$ = getelementspecial(f$, i)
    IF LEN(f2$) THEN

        'use sp2 to join items connected by a period
        IF c = 46 THEN '"."
            IF i > 1 AND i < n THEN 'stupidity check
                IF LEN(ff$) THEN MID$(ff$, LEN(ff$), 1) = sp2 'convert last spacer to a sp2
                ff$ = ff$ + "." + sp2
                GOTO fooloopnxt
            END IF
        END IF

        'spacing just before (
        IF openbracket THEN

            'convert last spacer?
            IF i <> 1 THEN
                IF isoperator(getelement$(a$, i - 1)) = 0 THEN
                    MID$(ff$, LEN(ff$), 1) = sp2
                END IF
            END IF
            ff$ = ff$ + f2$ + sp2
        ELSE 'not openbracket
            ff$ = ff$ + f2$ + sp
        END IF

    END IF 'len(f2$)

    fooloopnxt:

NEXT

IF LEN(aa$) THEN aa$ = LEFT$(aa$, LEN(aa$) - 1)
IF LEN(ff$) THEN ff$ = LEFT$(ff$, LEN(ff$) - 1)

IF debug THEN PRINT #9, "fixoperationorder:return:" + aa$
IF debug THEN PRINT #9, "fixoperationorder:layout:" + ff$
tlayout$ = ff$
fixoperationorder$ = aa$

fooindwel = fooindwel - 1
END FUNCTION




FUNCTION getelementspecial$ (savea$, elenum)
a$ = savea$
IF a$ = "" THEN EXIT FUNCTION 'no elements!

n = 1
p = 1
getelementspecialnext:
i = INSTR(p, a$, sp)

'avoid sp inside "..."
i2 = INSTR(p, a$, CHR$(34))
IF i2 < i AND i2 <> 0 THEN
    i3 = INSTR(i2 + 1, a$, CHR$(34)): IF i3 = 0 THEN qb64error "Expected " + CHR$(34)
    i = INSTR(i3, a$, sp)
END IF

IF elenum = n THEN
    IF i THEN
        getelementspecial$ = MID$(a$, p, i - p)
    ELSE
        getelementspecial$ = RIGHT$(a$, LEN(a$) - p + 1)
    END IF
    EXIT FUNCTION
END IF

IF i = 0 THEN EXIT FUNCTION 'no more elements!
n = n + 1
p = i + 1
GOTO getelementspecialnext
END FUNCTION



FUNCTION getelement$ (a$, elenum)
IF a$ = "" THEN EXIT FUNCTION 'no elements!

n = 1
p = 1
getelementnext:
i = INSTR(p, a$, sp)

IF elenum = n THEN
    IF i THEN
        getelement$ = MID$(a$, p, i - p)
    ELSE
        getelement$ = RIGHT$(a$, LEN(a$) - p + 1)
    END IF
    EXIT FUNCTION
END IF

IF i = 0 THEN EXIT FUNCTION 'no more elements!
n = n + 1
p = i + 1
GOTO getelementnext
END FUNCTION

FUNCTION getelements$ (a$, i1, i2)
IF i2 < i1 THEN getelements$ = "": EXIT FUNCTION
n = 1
p = 1
getelementsnext:
i = INSTR(p, a$, sp)
IF n = i1 THEN
    i1pos = p
END IF
IF n = i2 THEN
    IF i THEN
        getelements$ = MID$(a$, i1pos, i - i1pos)
    ELSE
        getelements$ = RIGHT$(a$, LEN(a$) - i1pos + 1)
    END IF
    EXIT FUNCTION
END IF
n = n + 1
p = i + 1
GOTO getelementsnext
END FUNCTION

SUB getid (i AS LONG)
IF i = -1 THEN nerror (82)

id = ids(i)

currentid = i
END SUB

SUB insertelements (a$, i, elements$)
IF i = 0 THEN
    IF a$ = "" THEN
        a$ = elements$
        EXIT SUB
    END IF
    a$ = elements$ + sp + a$
    EXIT SUB
END IF

a2$ = ""
n = numelements(a$)




FOR i2 = 1 TO n
    IF i2 > 1 THEN a2$ = a2$ + sp
    a2$ = a2$ + getelement$(a$, i2)
    IF i = i2 THEN a2$ = a2$ + sp + elements$
NEXT

a$ = a2$

END SUB

FUNCTION isnumber (a$)
IF LEN(a$) = 0 THEN EXIT FUNCTION
FOR i = 1 TO LEN(a$)
    a = ASC(MID$(a$, i, 1))
    IF a = 45 THEN
        IF i <> 1 THEN EXIT FUNCTION
        GOTO isnumok
    END IF
    IF a = 46 THEN
        IF dp = 1 THEN EXIT FUNCTION
        dp = 1
        GOTO isnumok
    END IF
    IF a >= 48 AND a <= 57 THEN v = 1: GOTO isnumok
    EXIT FUNCTION
    isnumok:
NEXT
isnumber = 1
END FUNCTION

FUNCTION isoperator (a2$)
a$ = UCASE$(a2$)
l = 0
l = l + 1: IF a$ = "IMP" THEN GOTO opfound
l = l + 1: IF a$ = "EQV" THEN GOTO opfound
l = l + 1: IF a$ = "XOR" THEN GOTO opfound
l = l + 1: IF a$ = "OR" THEN GOTO opfound
l = l + 1: IF a$ = "AND" THEN GOTO opfound
l = l + 1: IF a$ = "NOT" THEN GOTO opfound
l = l + 1
IF a$ = "=" THEN GOTO opfound
IF a$ = ">" THEN GOTO opfound
IF a$ = "<" THEN GOTO opfound
IF a$ = "<>" THEN GOTO opfound
IF a$ = "<=" THEN GOTO opfound
IF a$ = ">=" THEN GOTO opfound
l = l + 1
IF a$ = "+" THEN GOTO opfound
IF a$ = "-" THEN GOTO opfound '!CAREFUL! could be negation
l = l + 1: IF a$ = "MOD" THEN GOTO opfound
l = l + 1: IF a$ = "\" THEN GOTO opfound
l = l + 1
IF a$ = "*" THEN GOTO opfound
IF a$ = "/" THEN GOTO opfound
'NEGATION LEVEL (MUST BE SET AFTER CALLING ISOPERATOR BY CONTEXT)
l = l + 1: IF a$ = "ñ" THEN GOTO opfound
l = l + 1: IF a$ = "^" THEN GOTO opfound
EXIT FUNCTION
opfound:
isoperator = l
END FUNCTION

FUNCTION isuinteger (i$)
IF LEN(i$) = 0 THEN EXIT FUNCTION
FOR c = 1 TO LEN(i$)
    v = ASC(MID$(i$, c, 1))
    IF v < 48 THEN EXIT FUNCTION
    IF v > 57 THEN EXIT FUNCTION
NEXT
isuinteger = 1
END FUNCTION

FUNCTION isvalidvariable (a$)
FOR i = 1 TO LEN(a$)
    c = ASC(a$, i)
    t = 0
    IF c >= 48 AND c <= 57 THEN t = 1 'numeric
    IF c >= 65 AND c <= 90 THEN t = 2 'uppercase
    IF c >= 97 AND c <= 122 THEN t = 2 'lowercase
    IF c = 95 THEN t = 2 '_ underscore
    IF t = 2 OR (t = 1 AND i > 1) THEN
        'valid (continue)
    ELSE
        IF i = 1 THEN isvalidvariable = 0: EXIT FUNCTION
        EXIT FOR
    END IF
NEXT

isvalidvariable = 1
IF i > n THEN EXIT FUNCTION
e$ = RIGHT$(a$, LEN(a$) - i - 1)
IF e$ = "%%" OR e$ = "~%%" THEN EXIT FUNCTION
IF e$ = "%" OR e$ = "~%" THEN EXIT FUNCTION
IF e$ = "&" OR e$ = "~&" THEN EXIT FUNCTION
IF e$ = "&&" OR e$ = "~&&" THEN EXIT FUNCTION
IF e$ = "!" OR e$ = "#" OR e$ = "##" THEN EXIT FUNCTION
IF e$ = "$" THEN EXIT FUNCTION
IF e$ = "`" THEN EXIT FUNCTION
IF LEFT$(e$, 1) <> "$" AND LEFT$(e$, 1) <> "`" THEN isvalidvariable = 0: EXIT FUNCTION
e$ = RIGHT$(e$, LEN(e$) - 1)
IF isuinteger(e$) THEN isvalidvariable = 1: EXIT FUNCTION
isvalidvariable = 0
END FUNCTION




FUNCTION lineformat$ (a$)
a2$ = ""
linecontinuation = 0

continueline:

a$ = a$ + "  " 'add 2 extra spaces to make reading next char easier

ca$ = a$
a$ = UCASE$(a$)

n = LEN(a$)
i = 1
lineformatnext:
IF i >= n THEN GOTO lineformatdone

c = ASC(a$, i)
c$ = CHR$(c) '***remove later***

'----------------quoted string----------------
IF c = 34 THEN '"
    a2$ = a2$ + sp + CHR$(34)
    p1 = i + 1
    FOR i2 = i + 1 TO n - 2
        c2 = ASC(a$, i2)

        IF c2 = 34 THEN
            a2$ = a2$ + MID$(ca$, p1, i2 - p1 + 1) + "," + str2$(i2 - (i + 1))
            i = i2 + 1
            EXIT FOR
        END IF

        IF c2 = 92 THEN '\
            a2$ = a2$ + MID$(ca$, p1, i2 - p1) + "\\"
            p1 = i2 + 1
        END IF

        IF c2 < 32 OR c2 > 126 THEN
            o$ = OCT$(c2)
            IF LEN(o$) < 3 THEN
                o$ = "0" + o$
                IF LEN(o$) < 3 THEN o$ = "0" + o$
            END IF
            a2$ = a2$ + MID$(ca$, p1, i2 - p1) + "\" + o$
            p1 = i2 + 1
        END IF

    NEXT

    IF i2 = n - 1 THEN 'no closing "
        a2$ = a2$ + MID$(ca$, p1, (n - 2) - p1 + 1) + CHR$(34) + "," + str2$((n - 2) - (i + 1) + 1)
        i = n - 1
    END IF

    GOTO lineformatnext

END IF

'----------------number----------------
firsti = i
IF c = 46 THEN
    c2$ = MID$(a$, i + 1, 1): c2 = ASC(c2$)
    IF (c2 >= 48 AND c2 <= 57) THEN GOTO lfnumber
END IF
IF (c >= 48 AND c <= 57) THEN '0-9
    lfnumber:

    'handle 'IF a=1 THEN a=2 ELSE 100' by assuming numeric after ELSE to be a
    IF RIGHT$(a2$, 5) = sp + "ELSE" THEN
        a2$ = a2$ + sp + "GOTO"
    END IF

    'Number will be converted to the following format:
    ' 999999  .        99999  E        +         999
    '[whole$][dp(0/1)][frac$][ed(1/2)][pm(1/-1)][ex$]
    ' 0                1               2         3    <-mode

    mode = 0
    whole$ = ""
    dp = 0
    frac$ = ""
    ed = 0 'E=1, D=2, F=3
    pm = 1
    ex$ = ""




    lfreadnumber:
    valid = 0

    IF c = 46 THEN
        IF mode = 0 THEN valid = 1: dp = 1: mode = 1
    END IF

    IF c >= 48 AND c <= 57 THEN '0-9
        valid = 1
        IF mode = 0 THEN whole$ = whole$ + c$
        IF mode = 1 THEN frac$ = frac$ + c$
        IF mode = 2 THEN mode = 3
        IF mode = 3 THEN ex$ = ex$ + c$
    END IF

    IF c = 69 OR c = 68 OR c = 70 THEN 'E,D,F
        IF mode < 2 THEN
            valid = 1
            IF c = 69 THEN ed = 1
            IF c = 68 THEN ed = 2
            IF c = 70 THEN ed = 3
            mode = 2
        END IF
    END IF

    IF c = 43 OR c = 45 THEN '+,-
        IF mode = 2 THEN
            valid = 1
            IF c = 45 THEN pm = -1
            mode = 3
        END IF
    END IF

    IF valid THEN
        IF i <= n THEN i = i + 1: c$ = MID$(a$, i, 1): c = ASC(c$): GOTO lfreadnumber
    END IF



    'cull leading 0s off whole$
    DO WHILE LEFT$(whole$, 1) = "0": whole$ = RIGHT$(whole$, LEN(whole$) - 1): LOOP
    'cull trailing 0s off frac$
    DO WHILE RIGHT$(frac$, 1) = "0": frac$ = LEFT$(frac$, LEN(frac$) - 1): LOOP
    'cull leading 0s off ex$
    DO WHILE LEFT$(ex$, 1) = "0": ex$ = RIGHT$(ex$, LEN(ex$) - 1): LOOP

    IF dp <> 0 OR ed <> 0 THEN float = 1 ELSE float = 0

    extused = 1

    IF ed THEN e$ = "": GOTO lffoundext 'no extensions valid after E/D/F specified

    '3-character extensions
    IF i <= n - 2 THEN
        e$ = MID$(a$, i, 3)
        IF e$ = "~%%" AND float = 0 THEN i = i + 3: GOTO lffoundext
        IF e$ = "~&&" AND float = 0 THEN i = i + 3: GOTO lffoundext
    END IF
    '2-character extensions
    IF i <= n - 1 THEN
        e$ = MID$(a$, i, 2)
        IF e$ = "%%" AND float = 0 THEN i = i + 2: GOTO lffoundext
        IF e$ = "~%" AND float = 0 THEN i = i + 2: GOTO lffoundext
        IF e$ = "&&" AND float = 0 THEN i = i + 2: GOTO lffoundext
        IF e$ = "~&" AND float = 0 THEN i = i + 2: GOTO lffoundext
        IF e$ = "##" THEN
            i = i + 2
            ed = 3
            e$ = ""
            GOTO lffoundext
        END IF
        IF e$ = "~`" THEN
            i = i + 2
            GOTO lffoundbitext
        END IF
    END IF
    '1-character extensions
    IF i <= n THEN
        e$ = MID$(a$, i, 1)
        IF e$ = "%" AND float = 0 THEN i = i + 1: GOTO lffoundext
        IF e$ = "&" AND float = 0 THEN i = i + 1: GOTO lffoundext
        IF e$ = "!" THEN
            i = i + 1
            ed = 1
            e$ = ""
            GOTO lffoundext
        END IF
        IF e$ = "#" THEN
            i = i + 1
            ed = 2
            e$ = ""
            GOTO lffoundext
        END IF
        IF e$ = "`" THEN
            i = i + 1
            lffoundbitext:
            bitn$ = ""
            DO WHILE i <= n
                c2 = ASC(MID$(a$, i, 1))
                IF c2 >= 48 AND c2 <= 57 THEN
                    bitn$ = bitn$ + CHR$(c2)
                    i = i + 1
                ELSE
                    EXIT DO
                END IF
            LOOP
            IF bitn$ = "" THEN bitn$ = "1"
            'cull leading 0s off bitn$
            DO WHILE LEFT$(bitn$, 1) = "0": bitn$ = RIGHT$(bitn$, LEN(bitn$) - 1): LOOP
            e$ = e$ + bitn$
            GOTO lffoundext
        END IF
    END IF

    IF float THEN 'floating point types CAN be assumed
        'calculate first significant digit offset & number of significant digits
        IF whole$ <> "" THEN
            offset = LEN(whole$) - 1
            sigdigits = LEN(whole$) + LEN(frac$)
        ELSE
            IF frac$ <> "" THEN
                offset = -1
                sigdigits = LEN(frac$)
                FOR i2 = 1 TO LEN(frac$)
                    IF MID$(frac$, i2, 1) <> "0" THEN EXIT FOR
                    offset = offset - 1
                    sigdigits = sigdigits - 1
                NEXT
            ELSE
                'number is 0
                offset = 0
                sigdigits = 0
            END IF
        END IF
        sigdig$ = RIGHT$(whole$ + frac$, sigdigits)
        'SINGLE?
        IF sigdigits <= 7 THEN 'QBASIC interprets anything with more than 7 sig. digits as a DOUBLE
            IF offset <= 38 AND offset >= -38 THEN 'anything outside this range cannot be represented as a SINGLE
                IF offset = 38 THEN
                    IF sigdig$ > "3402823" THEN GOTO lfxsingle
                END IF
                IF offset = -38 THEN
                    IF sigdig$ < "1175494" THEN GOTO lfxsingle
                END IF
                ed = 1
                e$ = ""
                GOTO lffoundext
            END IF
        END IF
        lfxsingle:
        'DOUBLE?
        IF sigdigits <= 16 THEN 'QB64 handles DOUBLES with 16-digit precision
            IF offset <= 308 AND offset >= -308 THEN 'anything outside this range cannot be represented as a DOUBLE
                IF offset = 308 THEN
                    IF sigdig$ > "1797693134862315" THEN GOTO lfxdouble
                END IF
                IF offset = -308 THEN
                    IF sigdig$ < "2225073858507201" THEN GOTO lfxdouble
                END IF
                ed = 2
                e$ = ""
                GOTO lffoundext
            END IF
        END IF
        lfxdouble:
        'assume _FLOAT
        ed = 3
        e$ = "": GOTO lffoundext
    END IF

    extused = 0
    e$ = ""
    lffoundext:

    'make sure a leading numberic character exists
    IF whole$ = "" THEN whole$ = "0"
    'if a float, ensure frac$<>"" and dp=1
    IF float THEN
        dp = 1
        IF frac$ = "" THEN frac$ = "0"
    END IF
    'if ed is specified, make sure ex$ exists
    IF ed <> 0 AND ex$ = "" THEN ex$ = "0"

    a2$ = a2$ + sp
    a2$ = a2$ + whole$
    IF dp THEN a2$ = a2$ + "." + frac$
    IF ed THEN
        IF ed = 1 THEN a2$ = a2$ + "E"
        IF ed = 2 THEN a2$ = a2$ + "D"
        IF ed = 3 THEN a2$ = a2$ + "F"
        IF pm = -1 AND ex$ <> "0" THEN a2$ = a2$ + "-" ELSE a2$ = a2$ + "+"
        a2$ = a2$ + ex$
    END IF
    a2$ = a2$ + e$

    IF extused THEN a2$ = a2$ + "," + MID$(a$, firsti, i - firsti)

    GOTO lineformatnext
END IF

'----------------(number)&H...----------------
'note: the final value, not the number of hex characters, sets the default type
IF c = 38 THEN '&
    IF MID$(a$, i + 1, 1) = "H" THEN
        i = i + 2
        hx$ = ""
        lfreadhex:
        IF i <= n THEN
            c$ = MID$(a$, i, 1): c = ASC(c$)
            IF (c >= 48 AND c <= 57) OR (c >= 65 AND c <= 70) THEN hx$ = hx$ + c$: i = i + 1: GOTO lfreadhex
        END IF
        fullhx$ = "&H" + hx$

        'cull leading 0s off hx$
        DO WHILE LEFT$(hx$, 1) = "0": hx$ = RIGHT$(hx$, LEN(hx$) - 1): LOOP
        IF hx$ = "" THEN hx$ = "0"

        bitn$ = ""
        '3-character extensions
        IF i <= n - 2 THEN
            e$ = MID$(a$, i, 3)
            IF e$ = "~%%" THEN i = i + 3: GOTO lfhxext
            IF e$ = "~&&" THEN i = i + 3: GOTO lfhxext
        END IF
        '2-character extensions
        IF i <= n - 1 THEN
            e$ = MID$(a$, i, 2)
            IF e$ = "%%" THEN i = i + 2: GOTO lfhxext
            IF e$ = "~%" THEN i = i + 2: GOTO lfhxext
            IF e$ = "&&" THEN i = i + 2: GOTO lfhxext
            IF e$ = "~&" THEN i = i + 2: GOTO lfhxext
            IF e$ = "~`" THEN
                i = i + 2
                GOTO lfhxbitext
            END IF
        END IF
        '1-character extensions
        IF i <= n THEN
            e$ = MID$(a$, i, 1)
            IF e$ = "%" THEN i = i + 1: GOTO lfhxext
            IF e$ = "&" THEN i = i + 1: GOTO lfhxext
            IF e$ = "`" THEN
                i = i + 1
                lfhxbitext:
                DO WHILE i <= n
                    c2 = ASC(MID$(a$, i, 1))
                    IF c2 >= 48 AND c2 <= 57 THEN
                        bitn$ = bitn$ + CHR$(c2)
                        i = i + 1
                    ELSE
                        EXIT DO
                    END IF
                LOOP
                IF bitn$ = "" THEN bitn$ = "1"
                'cull leading 0s off bitn$
                DO WHILE LEFT$(bitn$, 1) = "0": bitn$ = RIGHT$(bitn$, LEN(bitn$) - 1): LOOP
                GOTO lfhxext
            END IF
        END IF
        'if no valid extension context was given, assume one
        'note: leading 0s have been culled, so LEN(hx$) reflects its values size
        e$ = "&&"
        IF LEN(hx$) <= 8 THEN e$ = "&" 'as in QBASIC, signed values must be used
        IF LEN(hx$) <= 4 THEN e$ = "%" 'as in QBASIC, signed values must be used
        GOTO lfhxext2
        lfhxext:
        fullhx$ = fullhx$ + e$ + bitn$
        lfhxext2:

        'build 8-byte unsigned integer rep. of hx$
        IF LEN(hx$) > 16 THEN qb64error "Overflow"
        v~&& = 0
        FOR i2 = 1 TO LEN(hx$)
            v2 = ASC(MID$(hx$, i2, 1))
            IF v2 <= 57 THEN v2 = v2 - 48 ELSE v2 = v2 - 65 + 10
            v~&& = v~&& * 16 + v2
        NEXT

        finishhexoctbin:
        num$ = str2u64$(v~&&) 'correct for unsigned values (overflow of unsigned can be checked later)
        IF LEFT$(e$, 1) <> "~" THEN 'note: range checking will be performed later in fixop.order
            'signed

            IF e$ = "%%" THEN
                IF v~&& > 127 THEN
                    IF v~&& > 255 THEN qb64error "Overflow"
                    v~&& = ((NOT v~&&) AND 255) + 1
                    num$ = "-" + sp + str2$(v~&&)
                END IF
            END IF

            IF e$ = "%" THEN
                IF v~&& > 32767 THEN
                    IF v~&& > 65535 THEN qb64error "Overflow"
                    v~&& = ((NOT v~&&) AND 65535) + 1
                    num$ = "-" + sp + str2$(v~&&)
                END IF
            END IF

            IF e$ = "&" THEN
                IF v~&& > 2147483647 THEN
                    IF v~&& > 4294967295 THEN qb64error "Overflow"
                    v~&& = ((NOT v~&&) AND 4294967295) + 1
                    num$ = "-" + sp + str2$(v~&&)
                END IF
            END IF

            IF e$ = "&&" THEN
                IF v~&& > 9223372036854775807 THEN
                    'note: no error checking necessary
                    v~&& = (NOT v~&&) + 1
                    num$ = "-" + sp + str2$(v~&&)
                END IF
            END IF

            IF e$ = "`" THEN
                vbitn = VAL(bitn$)
                h~&& = 1: FOR i2 = 1 TO vbitn - 1: h~&& = h~&& * 2: NEXT: h~&& = h~&& - 1 'build h~&&
                IF v~&& > h~&& THEN
                    h~&& = 1: FOR i2 = 1 TO vbitn: h~&& = h~&& * 2: NEXT: h~&& = h~&& - 1 'build h~&&
                    IF v~&& > h~&& THEN qb64error "Overflow"
                    v~&& = ((NOT v~&&) AND h~&&) + 1
                    num$ = "-" + sp + str2$(v~&&)
                END IF
            END IF

        END IF '<>"~"

        a2$ = a2$ + sp + num$ + e$ + bitn$ + "," + fullhx$

        GOTO lineformatnext
    END IF
END IF

'----------------(number)&O...----------------
'note: the final value, not the number of oct characters, sets the default type
IF c = 38 THEN '&
    IF MID$(a$, i + 1, 1) = "O" THEN
        i = i + 2
        'note: to avoid mistakes, hx$ is used instead of 'ot$'
        hx$ = ""
        lfreadoct:
        IF i <= n THEN
            c$ = MID$(a$, i, 1): c = ASC(c$)
            IF c >= 48 AND c <= 55 THEN hx$ = hx$ + c$: i = i + 1: GOTO lfreadoct
        END IF
        fullhx$ = "&O" + hx$

        'cull leading 0s off hx$
        DO WHILE LEFT$(hx$, 1) = "0": hx$ = RIGHT$(hx$, LEN(hx$) - 1): LOOP
        IF hx$ = "" THEN hx$ = "0"

        bitn$ = ""
        '3-character extensions
        IF i <= n - 2 THEN
            e$ = MID$(a$, i, 3)
            IF e$ = "~%%" THEN i = i + 3: GOTO lfotext
            IF e$ = "~&&" THEN i = i + 3: GOTO lfotext
        END IF
        '2-character extensions
        IF i <= n - 1 THEN
            e$ = MID$(a$, i, 2)
            IF e$ = "%%" THEN i = i + 2: GOTO lfotext
            IF e$ = "~%" THEN i = i + 2: GOTO lfotext
            IF e$ = "&&" THEN i = i + 2: GOTO lfotext
            IF e$ = "~&" THEN i = i + 2: GOTO lfotext
            IF e$ = "~`" THEN
                i = i + 2
                GOTO lfotbitext
            END IF
        END IF
        '1-character extensions
        IF i <= n THEN
            e$ = MID$(a$, i, 1)
            IF e$ = "%" THEN i = i + 1: GOTO lfotext
            IF e$ = "&" THEN i = i + 1: GOTO lfotext
            IF e$ = "`" THEN
                i = i + 1
                lfotbitext:
                bitn$ = ""
                DO WHILE i <= n
                    c2 = ASC(MID$(a$, i, 1))
                    IF c2 >= 48 AND c2 <= 57 THEN
                        bitn$ = bitn$ + CHR$(c2)
                        i = i + 1
                    ELSE
                        EXIT DO
                    END IF
                LOOP
                IF bitn$ = "" THEN bitn$ = "1"
                'cull leading 0s off bitn$
                DO WHILE LEFT$(bitn$, 1) = "0": bitn$ = RIGHT$(bitn$, LEN(bitn$) - 1): LOOP
                GOTO lfotext
            END IF
        END IF
        'if no valid extension context was given, assume one
        'note: leading 0s have been culled, so LEN(hx$) reflects its values size
        e$ = "&&"
        '37777777777
        IF LEN(hx$) <= 11 THEN
            IF LEN(hx$) < 11 OR ASC(LEFT$(hx$, 1)) <= 51 THEN e$ = "&"
        END IF
        '177777
        IF LEN(hx$) <= 6 THEN
            IF LEN(hx$) < 6 OR LEFT$(hx$, 1) = "1" THEN e$ = "%"
        END IF

        GOTO lfotext2
        lfotext:
        fullhx$ = fullhx$ + e$ + bitn$
        lfotext2:

        'build 8-byte unsigned integer rep. of hx$
        '1777777777777777777777 (22 digits)
        IF LEN(hx$) > 22 THEN qb64error "Overflow"
        IF LEN(hx$) = 22 THEN
            IF LEFT$(hx$, 1) <> "1" THEN qb64error "Overflow"
        END IF
        '********change v& to v~&&********
        v~&& = 0
        FOR i2 = 1 TO LEN(hx$)
            v2 = ASC(MID$(hx$, i2, 1))
            v2 = v2 - 48
            v~&& = v~&& * 8 + v2
        NEXT

        GOTO finishhexoctbin
    END IF
END IF

'----------------(number)&B...----------------
'note: the final value, not the number of bin characters, sets the default type
IF c = 38 THEN '&
    IF MID$(a$, i + 1, 1) = "B" THEN
        i = i + 2
        'note: to avoid mistakes, hx$ is used instead of 'bi$'
        hx$ = ""
        lfreadbin:
        IF i <= n THEN
            c$ = MID$(a$, i, 1): c = ASC(c$)
            IF c >= 48 AND c <= 49 THEN hx$ = hx$ + c$: i = i + 1: GOTO lfreadbin
        END IF
        fullhx$ = "&B" + hx$

        'cull leading 0s off hx$
        DO WHILE LEFT$(hx$, 1) = "0": hx$ = RIGHT$(hx$, LEN(hx$) - 1): LOOP
        IF hx$ = "" THEN hx$ = "0"

        bitn$ = ""
        '3-character extensions
        IF i <= n - 2 THEN
            e$ = MID$(a$, i, 3)
            IF e$ = "~%%" THEN i = i + 3: GOTO lfbiext
            IF e$ = "~&&" THEN i = i + 3: GOTO lfbiext
        END IF
        '2-character extensions
        IF i <= n - 1 THEN
            e$ = MID$(a$, i, 2)
            IF e$ = "%%" THEN i = i + 2: GOTO lfbiext
            IF e$ = "~%" THEN i = i + 2: GOTO lfbiext
            IF e$ = "&&" THEN i = i + 2: GOTO lfbiext
            IF e$ = "~&" THEN i = i + 2: GOTO lfbiext
            IF e$ = "~`" THEN
                i = i + 2
                GOTO lfbibitext
            END IF
        END IF
        '1-character extensions
        IF i <= n THEN
            e$ = MID$(a$, i, 1)
            IF e$ = "%" THEN i = i + 1: GOTO lfbiext
            IF e$ = "&" THEN i = i + 1: GOTO lfbiext
            IF e$ = "`" THEN
                i = i + 1
                lfbibitext:
                bitn$ = ""
                DO WHILE i <= n
                    c2 = ASC(MID$(a$, i, 1))
                    IF c2 >= 48 AND c2 <= 57 THEN
                        bitn$ = bitn$ + CHR$(c2)
                        i = i + 1
                    ELSE
                        EXIT DO
                    END IF
                LOOP
                IF bitn$ = "" THEN bitn$ = "1"
                'cull leading 0s off bitn$
                DO WHILE LEFT$(bitn$, 1) = "0": bitn$ = RIGHT$(bitn$, LEN(bitn$) - 1): LOOP
                GOTO lfbiext
            END IF
        END IF
        'if no valid extension context was given, assume one
        'note: leading 0s have been culled, so LEN(hx$) reflects its values size
        e$ = "&&"
        IF LEN(hx$) <= 32 THEN e$ = "&"
        IF LEN(hx$) <= 16 THEN e$ = "%"

        GOTO lfbiext2
        lfbiext:
        fullhx$ = fullhx$ + e$ + bitn$
        lfbiext2:

        'build 8-byte unsigned integer rep. of hx$
        IF LEN(hx$) > 64 THEN qb64error "Overflow"

        v~&& = 0
        FOR i2 = 1 TO LEN(hx$)
            v2 = ASC(MID$(hx$, i2, 1))
            v2 = v2 - 48
            v~&& = v~&& * 2 + v2
        NEXT

        GOTO finishhexoctbin
    END IF
END IF


'----------------(number)&H??? error----------------
IF c = 38 THEN qb64error "Expected &H... or &O..."

'----------------variable/name----------------
'*trailing _ is treated as a seperate line extension*
IF (c >= 65 AND c <= 90) OR c = 95 THEN 'A-Z(a-z) or _
    IF c = 95 THEN p2 = 0 ELSE p2 = i
    FOR i2 = i + 1 TO n
        c2 = ASC(a$, i2)
        IF NOT alphanumeric(c2) THEN EXIT FOR
        IF c2 <> 95 THEN p2 = i2
    NEXT
    IF p2 THEN 'not just underscores!
        'char is from i to p2
        n2 = p2 - i + 1
        a3$ = MID$(a$, i, n2)

        '----(variable/name)rem----
        IF n2 = 3 THEN
            IF a3$ = "REM" THEN
                i = i + n2
                'note: In QBASIC 'IF cond THEN REM comment' counts as a single line IF statement, however use of ' instead of REM does not
                IF UCASE$(RIGHT$(a2$, 5)) = sp + "THEN" THEN a2$ = a2$ + sp + "'" 'add nop
                layoutcomment = "REM"
                GOTO comment
            END IF
        END IF

        '----(variable/name)data----
        IF n2 = 4 THEN
            IF a3$ = "DATA" THEN
		x$=""
                i = i + n2
                scan = 0
                speechmarks = 0
                commanext = 0
                finaldata = 0
                e$ = ""
                p1 = 0
                p2 = 0
                nextdatachr:
                IF i < n THEN
                    c = ASC(a$, i)

                    IF c = 9 OR c = 32 THEN
                        IF scan = 0 THEN GOTO skipwhitespace
                    END IF

                    IF c = 58 THEN '":"
                        IF speechmarks = 0 THEN finaldata = 1: GOTO adddata
                    END IF

                    IF c = 44 THEN '","
                        IF speechmarks = 0 THEN
                            adddata:                      
			if prepass=0 then
                            IF p1 THEN
                                'FOR i2 = p1 TO p2
                                '    DATA_add ASC(ca$, i2)
                                'NEXT
				x$=x$+mid$(ca$,p1,p2-p1+1)
                            END IF
                            'assume closing "
                            IF speechmarks THEN
                                'DATA_add 34
				x$=x$+chr$(34)
                            END IF
                            'append comma
                            'DATA_add 44
			    x$=x$+chr$(44)
			end if
                            IF finaldata = 1 THEN GOTO finisheddata
                            e$ = ""
                            p1 = 0
                            p2 = 0
                            speechmarks = 0
                            scan = 0
                            commanext = 0
                            i = i + 1
                            GOTO nextdatachr
                        END IF
                    END IF '","

                    IF commanext = 1 THEN
                        IF c <> 32 AND c <> 9 THEN nerror (99)
                    END IF

                    IF c = 34 THEN
                        IF speechmarks = 1 THEN
                            commanext = 1
                            speechmarks = 0
                        END IF
                        IF scan = 0 THEN speechmarks = 1
                    END IF

                    scan = 1

                    IF p1 = 0 THEN p1 = i: p2 = i
                    IF c <> 9 AND c <> 32 THEN p2 = i

                    skipwhitespace:
                    i = i + 1: GOTO nextdatachr
                END IF 'i<n
                finaldata = 1: GOTO adddata
                finisheddata:
                e$=""
		if prepass=0 then
                put #16,,x$
		dataoffset=dataoffset+len(x$)

                e$=space$((len(x$)-1)*2)
                for ec=1 to len(x$)-1
                '2 chr hex encode each character
                v1=asc(x$,ec)
                v2=v1\16: if v2<=9 then v2=v2+48 else v2=v2+55
                v1=v1 and 15: if v1<=9 then v1=v1+48 else v1=v1+55
                asc(e$,ec*2-1)=v1
                asc(e$,ec*2)=v2
                next

		end if

                a2$ = a2$ + sp + "DATA": if len(e$) then a2$=a2$+sp+"_"+e$
                GOTO lineformatnext
            END IF
        END IF

        a2$ = a2$ + sp + MID$(ca$, i, n2)
        i = i + n2

        '----(variable/name)extensions----
        extcheck:
        IF n2 > 40 THEN qb64error "Identifier longer than 40 character limit"
        c3 = ASC(a$, i)
        m = 0
        IF c3 = 126 THEN '"~"
            e2$ = MID$(a$, i + 1, 2)
            IF e2$ = "&&" THEN e2$ = "~&&": GOTO lfgetve
            IF e2$ = "%%" THEN e2$ = "~%%": GOTO lfgetve
            e2$ = CHR$(ASC(e2$))
            IF e2$ = "&" THEN e2$ = "~&": GOTO lfgetve
            IF e2$ = "%" THEN e2$ = "~%": GOTO lfgetve
            IF e2$ = "`" THEN m = 1: e2$ = "~`": GOTO lfgetve
        END IF
        IF c3 = 37 THEN
            c4 = ASC(a$, i + 1)
            IF c4 = 37 THEN e2$ = "%%": GOTO lfgetve
            e2$ = "%": GOTO lfgetve
        END IF
        IF c3 = 38 THEN
            c4 = ASC(a$, i + 1)
            IF c4 = 38 THEN e2$ = "&&": GOTO lfgetve
            e2$ = "&": GOTO lfgetve
        END IF
        IF c3 = 33 THEN e2$ = "!": GOTO lfgetve
        IF c3 = 35 THEN
            c4 = ASC(a$, i + 1)
            IF c4 = 35 THEN e2$ = "##": GOTO lfgetve
            e2$ = "#": GOTO lfgetve
        END IF
        IF c3 = 36 THEN m = 1: e2$ = "$": GOTO lfgetve
        IF c3 = 96 THEN m = 1: e2$ = "`": GOTO lfgetve
        '(no symbol)

        'cater for unusual names/labels (eg a.0b%)
        IF ASC(a$, i) = 46 THEN '"."
            c2 = ASC(a$, i + 1)
            IF c2 >= 48 AND c2 <= 57 THEN
                'scan until no further alphanumerics
                p2 = i + 1
                FOR i2 = i + 2 TO n
                    c = ASC(a$, i2)
                    IF NOT alphanumeric(c) THEN EXIT FOR
                    IF c <> 95 THEN p2 = i2 'don't including trailing _
                NEXT
                a2$ = a2$ + sp + "." + sp + MID$(ca$, i + 1, p2 - (i + 1) + 1) 'case sensitive
                n2 = n2 + 1 + (p2 - (i + 1) + 1)
                i = p2 + 1
                GOTO extcheck 'it may have an extension or be continued with another "."
            END IF
        END IF

        GOTO lineformatnext

        lfgetve:
        i = i + LEN(e2$)
        a2$ = a2$ + e2$
        IF m THEN 'allow digits after symbol
            lfgetvd:
            IF i < n THEN
                c = ASC(a$, i)
                IF c >= 48 AND c <= 57 THEN a2$ = a2$ + CHR$(c): i = i + 1: GOTO lfgetvd
            END IF
        END IF 'm

        GOTO lineformatnext

    END IF 'p2
END IF 'variable/name
'----------------variable/name end----------------

'----------------spacing----------------
IF c = 32 OR c = 9 THEN i = i + 1: GOTO lineformatnext

'----------------symbols----------------
'--------single characters--------
IF lfsinglechar(c) THEN

    IF c = 60 THEN '<
        c2 = ASC(a$, i + 1)
        IF c2 = 61 THEN a2$ = a2$ + sp + "<=": i = i + 2: GOTO lineformatnext
        IF c2 = 62 THEN a2$ = a2$ + sp + "<>": i = i + 2: GOTO lineformatnext
    END IF
    IF c = 62 THEN '>
        c2 = ASC(a$, i + 1)
        IF c2 = 61 THEN a2$ = a2$ + sp + ">=": i = i + 2: GOTO lineformatnext
        IF c2 = 60 THEN a2$ = a2$ + sp + "<>": i = i + 2: GOTO lineformatnext '>< to <>
    END IF
    IF c = 61 THEN '=
        c2 = ASC(a$, i + 1)
        IF c2 = 62 THEN a2$ = a2$ + sp + ">=": i = i + 2: GOTO lineformatnext '=> to >=
        IF c2 = 60 THEN a2$ = a2$ + sp + "<=": i = i + 2: GOTO lineformatnext '=< to <=
    END IF

    IF c = 36 AND LEN(a2$) THEN GOTO badusage '$

    a2$ = a2$ + sp + CHR$(c)
    i = i + 1
    GOTO lineformatnext
END IF
badusage:

IF c <> 39 THEN nerror (100) 'invalid symbol encountered

'----------------comment(')----------------
layoutcomment = "'"
i = i + 1
comment:
IF i >= n THEN GOTO lineformatdone2
c$ = RIGHT$(a$, LEN(a$) - i + 1)
cc$ = RIGHT$(ca$, LEN(ca$) - i + 1)
IF LEN(c$) = 0 THEN GOTO lineformatdone2
layoutcomment$ = layoutcomment$ + cc$

c$ = LTRIM$(c$)
IF LEN(c$) = 0 THEN GOTO lineformatdone2
ac = ASC(c$)
IF ac <> 36 THEN GOTO lineformatdone2
nocasec$ = LTRIM$(RIGHT$(ca$, LEN(ca$) - i + 1))
memmode = 0
FOR x = 1 TO LEN(c$)
    mcnext:
    IF MID$(c$, x, 1) = "$" THEN



        'note: $STATICksdcdweh$DYNAMIC is valid!

        IF MID$(c$, x, 7) = "$STATIC" THEN
            memmode = 1
            xx = INSTR(x + 1, c$, "$")
            if xx=0 then exit for else
            x = xx: GOTO mcnext
        END IF

        IF MID$(c$, x, 8) = "$DYNAMIC" THEN
            memmode = 2
            xx = INSTR(x + 1, c$, "$")
            IF xx = 0 THEN EXIT FOR
            x = xx: GOTO mcnext
        END IF

        IF MID$(c$, x, 8) = "$INCLUDE" THEN
            'note: INCLUDE adds the file AFTER the line it is on has been processed
            'note: No other metacommands can follow the INCLUDE metacommand!
            'skip spaces until :
            FOR xx = x + 8 TO LEN(c$)
                ac = ASC(MID$(c$, xx, 1))
                IF ac = 58 THEN EXIT FOR ':
                IF ac <> 32 AND ac <> 9 THEN qb64error "Expected $INCLUDE:'filename'"
            NEXT
            x = xx
            'skip spaces until '
            FOR xx = x + 1 TO LEN(c$)
                ac = ASC(MID$(c$, xx, 1))
                IF ac = 39 THEN EXIT FOR 'character:'
                IF ac <> 32 AND ac <> 9 THEN qb64error "Expected $INCLUDE:'filename'"
            NEXT
            x = xx
            xx = INSTR(x + 1, c$, "'")
            IF xx = 0 THEN qb64error "Expected $INCLUDE:'filename'"
            addmetainclude$ = MID$(nocasec$, x + 1, xx - x - 1)
            IF addmetainclude$ = "" THEN qb64error "Expected $INCLUDE:'filename'"
            GOTO mcfinal
        END IF

        'add more metacommands here

    END IF '$
NEXT
mcfinal:

IF memmode = 1 THEN addmetastatic = 1
IF memmode = 2 THEN addmetadynamic = 1

GOTO lineformatdone2



lineformatdone:

'line continuation?
'note: line continuation in idemode is illegal
IF LEN(a2$) THEN
    IF RIGHT$(a2$, 1) = "_" THEN

        linecontinuation = 1 'avoids auto-format glitches
        layout$ = ""

        'remove _ from the end of the building string
        IF LEN(a2$) >= 2 THEN
            IF RIGHT$(a2$, 2) = sp + "_" THEN a2$ = LEFT$(a2$, LEN(a2$) - 1)
        END IF
        a2$ = LEFT$(a2$, LEN(a2$) - 1)

        IF inclevel THEN
            fh = 99 + inclevel
            IF EOF(fh) THEN GOTO lineformatdone2
            LINE INPUT #fh, a$
            inclinenumber(inclevel) = inclinenumber(inclevel) + 1
            GOTO includecont 'note: should not increase linenumber
        END IF

        IF idemode THEN
            idecommand$ = CHR$(100)
            ignore = ide(0)
            ideerror = 0
            a$ = idereturn$
            IF a$ = "" THEN GOTO lineformatdone2
        ELSE
            a$ = lineinput3$
            IF a$ = CHR$(13) THEN GOTO lineformatdone2
        END IF

        linenumber = linenumber + 1

        includecont:

        contline = 1
        GOTO continueline
    END IF
END IF

lineformatdone2:
IF LEFT$(a2$, 1) = sp THEN a2$ = RIGHT$(a2$, LEN(a2$) - 1)

'fix for trailing : error
IF RIGHT$(a2$, 1) = ":" THEN a2$ = a2$ + sp + "'" 'add nop

IF debug THEN PRINT #9, "lineformat():return:" + a2$
lineformat$ = a2$

END FUNCTION


SUB makeidrefer (ref$, typ AS LONG)
ref$ = str2$(currentid)
typ = id.t + ISREFERENCE
END SUB

SUB nerror (n AS LONG)
layout$ = "": layoutok = 0 'invalidate layout

IF os$ = "WIN" THEN OPEN ".\internal\qb64\errormes.txt" FOR INPUT AS #50
IF os$ = "LNX" THEN OPEN "./internal/qb64/errormes.txt" FOR INPUT AS #50

FOR i = 1 TO n
    LINE INPUT #50, a$
NEXT
a$ = RIGHT$(a$, LEN(a$) - INSTR(a$, ","))
qb64error a$
END SUB

FUNCTION numelements (a$)
IF a$ = "" THEN EXIT FUNCTION
n = 1
p = 1
numelementsnext:
i = INSTR(p, a$, sp)
IF i = 0 THEN numelements = n: EXIT FUNCTION
n = n + 1
p = i + 1
GOTO numelementsnext
END FUNCTION

FUNCTION operatorusage (operator$, typ AS LONG, info$, lhs AS LONG, rhs AS LONG, result AS LONG)
lhs = 7: rhs = 7: result = 0
'return values
'1 = use info$ as the operator without any other changes
'2 = use the function returned in info$ to apply this operator
'    upon left and right side of equation
'3=  bracket left and right side with negation and change operator to info$
'4=  BINARY NOT l.h.s, then apply operator in info$
'5=  UNARY, bracket up rhs, apply operator info$ to left, rebracket again

'lhs & rhs bit-field values
'1=integeral
'2=floating point
'4=string
'8=bool

'string operator
IF (typ AND ISSTRING) THEN
    lhs = 4: rhs = 4
    result = 4
    IF operator$ = "+" THEN info$ = "qbs_add": operatorusage = 2: EXIT FUNCTION
    result = 8
    IF operator$ = "=" THEN info$ = "qbs_equal": operatorusage = 2: EXIT FUNCTION
    IF operator$ = "<>" THEN info$ = "qbs_notequal": operatorusage = 2: EXIT FUNCTION
    IF operator$ = ">" THEN info$ = "qbs_greaterthan": operatorusage = 2: EXIT FUNCTION
    IF operator$ = "<" THEN info$ = "qbs_lessthan": operatorusage = 2: EXIT FUNCTION
    IF operator$ = ">=" THEN info$ = "qbs_greaterorequal": operatorusage = 2: EXIT FUNCTION
    IF operator$ = "<=" THEN info$ = "qbs_lessorequal": operatorusage = 2: EXIT FUNCTION
    IF debug THEN PRINT #9, "INVALID STRING OPERATOR!": END
END IF

'assume numeric operator
lhs = 1 + 2: rhs = 1 + 2
IF operator$ = "^" THEN result = 2: info$ = "pow2": operatorusage = 2: EXIT FUNCTION
IF operator$ = "ñ" THEN info$ = "-": operatorusage = 5: EXIT FUNCTION
IF operator$ = "/" THEN
    info$ = "/ ": operatorusage = 1
    'for / division, either the lhs or the rhs must be a float to make
    'c++ return a result in floating point form
    IF (typ AND ISFLOAT) THEN
        'lhs is a float
        lhs = 2
        rhs = 1 + 2
    ELSE
        'lhs isn't a float!
        lhs = 1 + 2
        rhs = 2
    END IF
    result = 2
    EXIT FUNCTION
END IF
IF operator$ = "*" THEN info$ = "*": operatorusage = 1: EXIT FUNCTION
IF operator$ = "+" THEN info$ = "+": operatorusage = 1: EXIT FUNCTION
IF operator$ = "-" THEN info$ = "-": operatorusage = 1: EXIT FUNCTION

result = 8
IF operator$ = "=" THEN info$ = "==": operatorusage = 3: EXIT FUNCTION
IF operator$ = ">" THEN info$ = ">": operatorusage = 3: EXIT FUNCTION
IF operator$ = "<" THEN info$ = "<": operatorusage = 3: EXIT FUNCTION
IF operator$ = "<>" THEN info$ = "!=": operatorusage = 3: EXIT FUNCTION
IF operator$ = "<=" THEN info$ = "<=": operatorusage = 3: EXIT FUNCTION
IF operator$ = ">=" THEN info$ = ">=": operatorusage = 3: EXIT FUNCTION

lhs = 1: rhs = 1: result = 1
IF operator$ = "MOD" THEN info$ = "%": operatorusage = 1: EXIT FUNCTION
IF operator$ = "\" THEN info$ = "/ ": operatorusage = 1: EXIT FUNCTION
IF operator$ = "IMP" THEN info$ = "|": operatorusage = 4: EXIT FUNCTION
IF operator$ = "EQV" THEN info$ = "^": operatorusage = 4: EXIT FUNCTION
IF operator$ = "XOR" THEN info$ = "^": operatorusage = 1: EXIT FUNCTION
IF operator$ = "OR" THEN info$ = "|": operatorusage = 1: EXIT FUNCTION
IF operator$ = "AND" THEN info$ = "&": operatorusage = 1: EXIT FUNCTION

lhs = 7
IF operator$ = "NOT" THEN info$ = "~": operatorusage = 5: EXIT FUNCTION

IF debug THEN PRINT #9, "INVALID NUMBERIC OPERATOR!": END

END FUNCTION

SUB qb64error (info$)
layout$ = "": layoutok = 0 'invalidate layout

IF inclevel > 0 THEN info$ = info$ + incerror$

IF idemode THEN
    ideerrorline = linenumber
    idemessage$ = info$
    ERROR 2 'simulate an error to take advantage of qb64's error jumping
END IF

PRINT
PRINT info$
FOR i = 1 TO LEN(linefragment)
    IF MID$(linefragment, i, 1) = sp$ THEN MID$(linefragment, i, 1) = " "
NEXT
FOR i = 1 TO LEN(wholeline)
    IF MID$(wholeline, i, 1) = sp$ THEN MID$(wholeline, i, 1) = " "
NEXT
PRINT "Caused by (or after):" + linefragment
PRINT "LINE " + str2(linenumber) + ":" + wholeline
END
END SUB

FUNCTION refer$ (a2$, typ AS LONG, method AS LONG)
typbak = typ
'method: 0 return an equation which calculates the value of the "variable"
'        1 return the C name of the variable, typ will be left unchanged

a$ = a2$

'retrieve ID
i = INSTR(a$, "³")
IF i THEN
    idnumber = VAL(LEFT$(a$, i - 1)): a$ = RIGHT$(a$, LEN(a$) - i)
ELSE
    idnumber = VAL(a$)
END IF
getid idnumber

'UDT?
IF typ AND ISUDT THEN
    IF method = 1 THEN
        n$ = "UDT_" + RTRIM$(id.n)
        IF id.t = 0 THEN n$ = "ARRAY_" + n$
        n$ = scope$ + n$
        refer$ = n$
        EXIT FUNCTION
    END IF

    'print "UDTSUBSTRING[idX|u|e|o]:"+a$

    u = VAL(a$)
    i = INSTR(a$, "³"): a$ = RIGHT$(a$, LEN(a$) - i): e = VAL(a$)
    i = INSTR(a$, "³"): o$ = RIGHT$(a$, LEN(a$) - i)
    n$ = "UDT_" + RTRIM$(id.n): IF id.t = 0 THEN n$ = "ARRAY_" + n$ + "[0]"
    IF e = 0 THEN qb64error "User defined types in expressions are invalid"
    IF typ AND ISOFFSETINBITS THEN qb64error "Cannot resolve bit-length variables inside user defined types yet"

    IF typ AND ISSTRING THEN
        o2$ = "(((uint8*)" + scope$ + n$ + ")+(" + o$ + "))"
        r$ = "qbs_new_fixed(" + o2$ + "," + str2(udtetypesize(e)) + ",1)"
        typ = STRINGTYPE + ISFIXEDLENGTH 'ISPOINTER retained, it is still a pointer!
    ELSE
        typ = typ - ISUDT - ISREFERENCE - ISPOINTER
        IF typ AND ISARRAY THEN typ = typ - ISARRAY
        t$ = typ2ctyp$(typ, "")
        o2$ = "(((char*)" + scope$ + n$ + ")+(" + o$ + "))"
        r$ = "*" + "(" + t$ + "*)" + o2$
    END IF

    'print "REFER:"+r$+","+str2$(typ)
    refer$ = r$
    EXIT FUNCTION
END IF


'array?
IF id.arraytype THEN

    n$ = RTRIM$(id.callname)
    IF method = 1 THEN
        refer$ = n$
        typ = typbak
        EXIT FUNCTION
    END IF
    typ = typ - ISPOINTER - ISREFERENCE 'typ now looks like a regular value

    IF (typ AND ISSTRING) THEN
        IF (typ AND ISFIXEDLENGTH) THEN
            offset$ = "&((uint8*)(" + n$ + "[0]))[(" + a$ + ")*" + str2(id.tsize) + "]"
            r$ = "qbs_new_fixed(" + offset$ + "," + str2(id.tsize) + ",1)"
        ELSE
            r$ = "((qbs*)(((uint64*)(" + n$ + "[0]))[" + a$ + "]))"
        END IF
        stringprocessinghappened = 1
        refer$ = r$
        EXIT FUNCTION
    END IF

    IF (typ AND ISOFFSETINBITS) THEN
        'IF (typ AND ISUNSIGNED) THEN r$ = "getubits_" ELSE r$ = "getbits_"
        'r$ = r$ + str2(typ AND 511) + "("
        IF (typ AND ISUNSIGNED) THEN r$ = "getubits" ELSE r$ = "getbits"
        r$ = r$ + "(" + str2(typ AND 511) + ","
        r$ = r$ + "(uint8*)(" + n$ + "[0])" + ","
        r$ = r$ + a$ + ")"
        refer$ = r$
        EXIT FUNCTION
    ELSE
        t$ = ""
        IF (typ AND ISFLOAT) THEN
            IF (typ AND 511) = 32 THEN t$ = "float"
            IF (typ AND 511) = 64 THEN t$ = "double"
            IF (typ AND 511) = 256 THEN t$ = "long double"
        ELSE
            IF (typ AND ISUNSIGNED) THEN
                IF (typ AND 511) = 8 THEN t$ = "uint8"
                IF (typ AND 511) = 16 THEN t$ = "uint16"
                IF (typ AND 511) = 32 THEN t$ = "uint32"
                IF (typ AND 511) = 64 THEN t$ = "uint64"
            ELSE
                IF (typ AND 511) = 8 THEN t$ = "int8"
                IF (typ AND 511) = 16 THEN t$ = "int16"
                IF (typ AND 511) = 32 THEN t$ = "int32"
                IF (typ AND 511) = 64 THEN t$ = "int64"
            END IF
        END IF
    END IF
    IF t$ = "" THEN nerror (83)
    r$ = "((" + t$ + "*)(" + n$ + "[0]))[" + a$ + "]"
    refer$ = r$
    EXIT FUNCTION
END IF 'array

'variable?
IF id.t THEN
    r$ = RTRIM$(id.n)
    t = id.t
    'remove irrelavant flags
    IF (t AND ISINCONVENTIONALMEMORY) THEN t = t - ISINCONVENTIONALMEMORY
    'string?
    IF (t AND ISSTRING) THEN
        IF (t AND ISFIXEDLENGTH) THEN
            r$ = scope$ + "STRING" + str2(id.tsize) + "_" + r$: GOTO ref
        END IF
        r$ = scope$ + "STRING_" + r$: GOTO ref
    END IF
    'bit-length single variable?
    IF (t AND ISOFFSETINBITS) THEN
        IF (t AND ISUNSIGNED) THEN
            r$ = "*" + scope$ + "UBIT" + str2(t AND 511) + "_" + r$
        ELSE
            r$ = "*" + scope$ + "BIT" + str2(t AND 511) + "_" + r$
        END IF
        GOTO ref
    END IF
    IF t = BYTETYPE THEN r$ = "*" + scope$ + "BYTE_" + r$: GOTO ref
    IF t = UBYTETYPE THEN r$ = "*" + scope$ + "UBYTE_" + r$: GOTO ref
    IF t = INTEGERTYPE THEN r$ = "*" + scope$ + "INTEGER_" + r$: GOTO ref
    IF t = UINTEGERTYPE THEN r$ = "*" + scope$ + "UINTEGER_" + r$: GOTO ref
    IF t = LONGTYPE THEN r$ = "*" + scope$ + "LONG_" + r$: GOTO ref
    IF t = ULONGTYPE THEN r$ = "*" + scope$ + "ULONG_" + r$: GOTO ref
    IF t = INTEGER64TYPE THEN r$ = "*" + scope$ + "INTEGER64_" + r$: GOTO ref
    IF t = UINTEGER64TYPE THEN r$ = "*" + scope$ + "UINTEGER64_" + r$: GOTO ref
    IF t = SINGLETYPE THEN r$ = "*" + scope$ + "SINGLE_" + r$: GOTO ref
    IF t = DOUBLETYPE THEN r$ = "*" + scope$ + "DOUBLE_" + r$: GOTO ref
    IF t = FLOATTYPE THEN r$ = "*" + scope$ + "FLOAT_" + r$: GOTO ref
    ref:
    IF (t AND ISSTRING) THEN stringprocessinghappened = 1
    IF (t AND ISPOINTER) THEN t = t - ISPOINTER
    typ = t
    IF method = 1 THEN
        IF LEFT$(r$, 1) = "*" THEN r$ = RIGHT$(r$, LEN(r$) - 1)
        typ = typbak
    END IF
    refer$ = r$
    EXIT FUNCTION
END IF 'variable



END FUNCTION

SUB regid
idn = idn + 1

IF idn > ids_max THEN
    ids_max = ids_max * 2
    REDIM _PRESERVE ids(1 TO ids_max) AS idstruct
    REDIM _PRESERVE cmemlist(1 TO ids_max + 1) AS INTEGER
    REDIM _PRESERVE sfcmemargs(1 TO ids_max + 1) AS STRING * 100
    REDIM _PRESERVE arrayelementslist(1 TO ids_max + 1) AS INTEGER
END IF


'register case sensitive name if none given
IF ASC(id.cn) = 32 THEN
    a$ = RTRIM$(id.n)
    id.n = UCASE$(a$)
    id.cn = a$
END IF


id.insubfunc = subfunc

'note: cannot be STATIC and SHARED at the same time
IF dimshared THEN
    id.share = dimshared
ELSE
    IF dimstatic THEN id.staticscope = 1
END IF

ids(idn) = id

currentid = idn

'add it to the hash table
HashAdd RTRIM$(id.n), 1, currentid

END SUB

SUB reginternal

'special codes:

'-1 Any numeric variable (will be made explicit by a C cast)
'   Typically, these are used when multiple C functions exist

'-2 Offset+Size(in bytes)
'   Size is the largest safe memory block available from the offset
'   used for: CALL INTERRUPT[X]

'-3 Offset+Size(in bytes)
'   Size is the largest safe memory block available from the offset
'   *Like -2, but restrictions apply
'   used for: GET/PUT(graphics)

'-4 Offset+Size(in bytes)
'   Size is the size of the element referenced
'   used for: GET/PUT(file)

'special return codes:
'none

clearid
id.n = "_MAPUNICODE"
id.subfunc = 2
id.callname = "sub__mapunicode"
id.args = 2
id.arg = MKL$(LONGTYPE - ISPOINTER)+MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "?{TO}?"
regid

clearid
id.n = "_MAPUNICODE"
id.subfunc = 1
id.callname = "func__mapunicode"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "_KEYDOWN"
id.subfunc = 1
id.callname = "func__keydown"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "_KEYHIT"
id.subfunc = 1
id.callname = "func__keyhit"
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "FILES"
id.subfunc = 2
id.callname = "sub_files"
id.args = 1
id.arg = MKL$(STRINGTYPE - ISPOINTER)
id.specialformat = "[?]"
regid

clearid
id.n = "_PRINTIMAGE"
id.subfunc = 2
id.callname = "sub__printimage"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
''proposed version:
''id.specialformat = "[_SQUAREPIXELS][?][,(?,?)-(?,?)]"
regid

'remote desktop

clearid
id.n = "_SCREENCLICK"
id.subfunc = 2
id.callname = "sub__screenclick"
id.args = 2
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
regid

clearid
id.n = "_SCREENPRINT"
id.subfunc = 2
id.callname = "sub__screenprint"
id.args = 1
id.arg = MKL$(STRINGTYPE - ISPOINTER)
regid

clearid
id.n = "_SCREENIMAGE"
id.subfunc = 1
id.callname = "func__screenimage"
id.ret = LONGTYPE - ISPOINTER
regid





clearid
id.n = "LOCK"
id.subfunc = 2
id.callname = "sub_lock"
id.args = 3
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(INTEGER64TYPE - ISPOINTER) + MKL$(INTEGER64TYPE - ISPOINTER)
id.specialformat = "[#]?[,[?][{TO}?]]"
regid

clearid
id.n = "UNLOCK"
id.subfunc = 2
id.callname = "sub_unlock"
id.args = 3
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(INTEGER64TYPE - ISPOINTER) + MKL$(INTEGER64TYPE - ISPOINTER)
id.specialformat = "[#]?[,[?][{TO}?]]"
regid

clearid
id.n = "_FREETIMER"
id.subfunc = 1
id.callname = "func__freetimer"
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "TIMER"
id.subfunc = 2
id.callname = "sub_timer"
id.args = 2
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "[(?)]{ON|OFF|STOP|FREE}"
regid

clearid
id.n = "_FULLSCREEN"
id.subfunc = 2
id.callname = "sub__fullscreen"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "[{_OFF|_STRETCH|_SQUAREPIXELS}]"
regid

clearid
id.n = "_FULLSCREEN"
id.subfunc = 1
id.callname = "func__fullscreen"
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "_CLIPBOARD"
id.musthave = "$"
id.subfunc = 2
id.callname = "sub__clipboard"
id.args = 1
id.arg = MKL$(STRINGTYPE - ISPOINTER)
id.specialformat = "=?"
regid

clearid
id.n = "_CLIPBOARD"
id.musthave = "$"
id.subfunc = 1
id.callname = "func__clipboard"
id.ret = STRINGTYPE - ISPOINTER
regid

clearid
id.n = "_EXIT"
id.subfunc = 1
id.callname = "func__exit"
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "_OPENHOST"
id.subfunc = 1
id.callname = "func__openhost"
id.args = 1
id.arg = MKL$(STRINGTYPE - ISPOINTER)
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "_CONNECTED"
id.subfunc = 1
id.callname = "func__connected"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "_CONNECTIONADDRESS"
id.subfunc = 1
id.callname = "func__connectionaddress"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.ret = STRINGTYPE - ISPOINTER
regid

clearid
id.n = "_OPENCONNECTION"
id.subfunc = 1
id.callname = "func__openconnection"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "_OPENCLIENT"
id.subfunc = 1
id.callname = "func__openclient"
id.args = 1
id.arg = MKL$(STRINGTYPE - ISPOINTER)
id.ret = LONGTYPE - ISPOINTER
regid


clearid
id.n = "ENVIRON"
id.musthave = "$"
id.subfunc = 1
id.callname = "func_environ"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.ret = STRINGTYPE - ISPOINTER
regid

clearid
id.n = "ENVIRON"
id.subfunc = 2
id.callname = "sub_environ"
id.args = 1
id.arg = MKL$(STRINGTYPE - ISPOINTER)
regid

clearid
id.n = "_ERRORLINE"
id.subfunc = 1
id.callname = "func__errorline"
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "_DISPLAY"
id.subfunc = 2
id.callname = "sub__display"
regid

clearid
id.n = "_AUTODISPLAY"
id.subfunc = 2
id.callname = "sub__autodisplay"
regid


clearid
id.n = "_LIMIT"
id.subfunc = 2
id.callname = "sub__limit"
id.args = 1
id.arg = MKL$(DOUBLETYPE - ISPOINTER)
regid

clearid
id.n = "_DELAY"
id.subfunc = 2
id.callname = "sub__delay"
id.args = 1
id.arg = MKL$(DOUBLETYPE - ISPOINTER)
regid

clearid
id.n = "_ICON"
id.subfunc = 2
id.callname = "sub__icon"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
regid

clearid
id.n = "_TITLE"
id.subfunc = 2
id.callname = "sub__title"
id.args = 1
id.arg = MKL$(STRINGTYPE - ISPOINTER)
regid

clearid
id.n = "CLEAR"
id.subfunc = 2
id.callname = "sub_clear"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "[,,?]"
regid

'2D PROTOTYPE 1.0

'IMAGE CREATION/FREEING

clearid
id.n = "_NEWIMAGE"
id.subfunc = 1
id.callname = "func__newimage"
id.args = 3
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "?,?[,?]"
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "_LOADIMAGE"
id.subfunc = 1
id.callname = "func__loadimage"
id.args = 2
id.arg = MKL$(STRINGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "?[,?]"
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "_FREEIMAGE"
id.subfunc = 2
id.callname = "sub__freeimage"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "[?]"
regid

clearid
id.n = "_COPYIMAGE"
id.subfunc = 1
id.callname = "func__copyimage"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "[?]"
id.ret = LONGTYPE - ISPOINTER
regid

'IMAGE SELECTION

clearid
id.n = "_SOURCE"
id.subfunc = 2
id.callname = "sub__source"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "?"
regid

clearid
id.n = "_DEST"
id.subfunc = 2
id.callname = "sub__dest"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "?"
regid

clearid
id.n = "_SOURCE"
id.subfunc = 1
id.callname = "func__source"
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "_DEST"
id.subfunc = 1
id.callname = "func__dest"
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "_DISPLAY"
id.subfunc = 1
id.callname = "func__display"
id.ret = LONGTYPE - ISPOINTER
regid

'IMAGE SETTINGS

clearid
id.n = "_BLEND"
id.subfunc = 2
id.callname = "sub__blend"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "[?]"
regid

clearid
id.n = "_DONTBLEND"
id.subfunc = 2
id.callname = "sub__dontblend"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "[?]"
regid

clearid
id.n = "_CLEARCOLOR"
id.subfunc = 2
id.callname = "sub__clearcolor"
id.args = 3
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(ULONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "[{_NONE}][?][,?]"
regid

'USING/CHANGING A SURFACE

clearid
id.n = "_PUTIMAGE"
id.subfunc = 2
id.callname = "sub__putimage"
id.args = 14
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(DOUBLETYPE - ISPOINTER) + MKL$(DOUBLETYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(DOUBLETYPE - ISPOINTER) + MKL$(DOUBLETYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(DOUBLETYPE - ISPOINTER) + MKL$(DOUBLETYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(DOUBLETYPE - ISPOINTER) + MKL$(DOUBLETYPE - ISPOINTER)
id.specialformat = "[[{STEP}](?,?)[-[{STEP}](?,?)]][,[?][,[?][,[[{STEP}](?,?)[-[{STEP}](?,?)]]]]]"
regid

clearid
id.n = "_SETALPHA"
id.subfunc = 2
id.callname = "sub__setalpha"
id.args = 4
id.arg = MKL$(ULONGTYPE - ISPOINTER) + MKL$(ULONGTYPE - ISPOINTER) + MKL$(ULONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "?[,[?[{TO}?]][,?]]"
regid

'IMAGE INFO

clearid
id.n = "_WIDTH"
id.subfunc = 1
id.callname = "func__width"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "[?]"
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "_HEIGHT"
id.subfunc = 1
id.callname = "func__height"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "[?]"
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "_PIXELSIZE"
id.subfunc = 1
id.callname = "func__pixelsize"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "[?]"
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "_CLEARCOLOR"
id.subfunc = 1
id.callname = "func__clearcolor"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "[?]"
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "_BLEND"
id.subfunc = 1
id.callname = "func__blend"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "[?]"
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "_DEFAULTCOLOR"
id.subfunc = 1
id.callname = "func__defaultcolor"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "[?]"
id.ret = ULONGTYPE - ISPOINTER
regid

clearid
id.n = "_BACKGROUNDCOLOR"
id.subfunc = 1
id.callname = "func__backgroundcolor"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "[?]"
id.ret = ULONGTYPE - ISPOINTER
regid

'256 COLOR PALETTES

clearid
id.n = "_PALETTECOLOR"
id.subfunc = 1
id.callname = "func__palettecolor"
id.args = 2
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "?[,?]"
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "_PALETTECOLOR"
id.subfunc = 2
id.callname = "sub__palettecolor"
id.args = 3
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(ULONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "?,?[,?]"
regid

clearid
id.n = "_COPYPALETTE"
id.subfunc = 2
id.callname = "sub__copypalette"
id.args = 2
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "[?][,?]"
regid

'FONT SUPPORT

clearid
id.n = "_LOADFONT"
id.subfunc = 1
id.callname = "func__loadfont"
id.args = 3
id.arg = MKL$(STRINGTYPE - ISPOINTER) + MKL$(DOUBLETYPE - ISPOINTER) + MKL$(STRINGTYPE - ISPOINTER)
id.specialformat = "?,?[,?]"
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "_FONT"
id.subfunc = 2
id.callname = "sub__font"
id.args = 2
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "?[,?]"
regid

clearid
id.n = "_FONTWIDTH"
id.subfunc = 1
id.callname = "func__fontwidth"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "[?]"
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "_FONTHEIGHT"
id.subfunc = 1
id.callname = "func__fontheight"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "[?]"
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "_FONT"
id.subfunc = 1
id.callname = "func__font"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "[?]"
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "_PRINTSTRING"
id.subfunc = 2
id.callname = "sub__printstring"
id.args = 5
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(DOUBLETYPE - ISPOINTER) + MKL$(DOUBLETYPE - ISPOINTER) + MKL$(STRINGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "[{STEP}](?,?),?[,?]"
regid

clearid
id.n = "_PRINTWIDTH"
id.subfunc = 1
id.callname = "func__printwidth"
id.args = 2
id.arg = MKL$(STRINGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "?[,?]"
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "_FREEFONT"
id.subfunc = 2
id.callname = "sub__freefont"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "?"
regid

clearid
id.n = "_PRINTMODE"
id.subfunc = 2
id.callname = "sub__printmode"
id.args = 2
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "{_FILLBACKGROUND|_KEEPBACKGROUND|_ONLYBACKGROUND}[,?]"
regid

clearid
id.n = "_PRINTMODE"
id.subfunc = 1
id.callname = "func__printmode"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "[?]"
id.ret = LONGTYPE - ISPOINTER
regid

'WORKING WITH COLORS

clearid
id.n = "_RGBA"
id.subfunc = 1
id.callname = "func__rgba"
id.args = 5
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "?,?,?,?[,?]"
id.ret = ULONGTYPE - ISPOINTER
regid

clearid
id.n = "_RGB"
id.subfunc = 1
id.callname = "func__rgb"
id.args = 4
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "?,?,?[,?]"
id.ret = ULONGTYPE - ISPOINTER
regid

clearid
id.n = "_RED"
id.subfunc = 1
id.callname = "func__red"
id.args = 2
id.arg = MKL$(ULONGTYPE - ISPOINTER) + MKL$(ULONGTYPE - ISPOINTER)
id.specialformat = "?[,?]"
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "_GREEN"
id.subfunc = 1
id.callname = "func__green"
id.args = 2
id.arg = MKL$(ULONGTYPE - ISPOINTER) + MKL$(ULONGTYPE - ISPOINTER)
id.specialformat = "?[,?]"
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "_BLUE"
id.subfunc = 1
id.callname = "func__blue"
id.args = 2
id.arg = MKL$(ULONGTYPE - ISPOINTER) + MKL$(ULONGTYPE - ISPOINTER)
id.specialformat = "?[,?]"
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "_ALPHA"
id.subfunc = 1
id.callname = "func__alpha"
id.args = 2
id.arg = MKL$(ULONGTYPE - ISPOINTER) + MKL$(ULONGTYPE - ISPOINTER)
id.specialformat = "?[,?]"
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "_RGBA32"
id.subfunc = 1
id.callname = "func__rgba32"
id.args = 4
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
id.ret = ULONGTYPE - ISPOINTER
regid

clearid
id.n = "_RGB32"
id.subfunc = 1
id.callname = "func__rgb32"
id.args = 3
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
id.ret = ULONGTYPE - ISPOINTER
regid

clearid
id.n = "_RED32"
id.subfunc = 1
id.callname = "func__red32"
id.args = 1
id.arg = MKL$(ULONGTYPE - ISPOINTER)
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "_GREEN32"
id.subfunc = 1
id.callname = "func__green32"
id.args = 1
id.arg = MKL$(ULONGTYPE - ISPOINTER)
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "_BLUE32"
id.subfunc = 1
id.callname = "func__blue32"
id.args = 1
id.arg = MKL$(ULONGTYPE - ISPOINTER)
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "_ALPHA32"
id.subfunc = 1
id.callname = "func__alpha32"
id.args = 1
id.arg = MKL$(ULONGTYPE - ISPOINTER)
id.ret = LONGTYPE - ISPOINTER
regid


clearid
id.n = "DRAW"
id.subfunc = 2
id.callname = "sub_draw"
id.args = 1
id.arg = MKL$(STRINGTYPE - ISPOINTER)
regid

clearid
id.n = "PLAY"
id.subfunc = 2
id.callname = "sub_play"
id.args = 1
id.arg = MKL$(STRINGTYPE - ISPOINTER)
regid

'QB64 MOUSE
clearid
id.n = "_MOUSESHOW"
id.subfunc = 2
id.callname = "sub__mouseshow"
regid

clearid
id.n = "_MOUSEHIDE"
id.subfunc = 2
id.callname = "sub__mousehide"
regid

clearid
id.n = "_MOUSEINPUT"
id.subfunc = 1
id.callname = "func__mouseinput"
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "_MOUSEX"
id.subfunc = 1
id.callname = "func__mousex"
id.ret = SINGLETYPE - ISPOINTER
regid

clearid
id.n = "_MOUSEY"
id.subfunc = 1
id.callname = "func__mousey"
id.ret = SINGLETYPE - ISPOINTER
regid

clearid
id.n = "_MOUSEMOVEMENTX"
id.subfunc = 1
id.callname = "func__mousemovementx"
id.ret = SINGLETYPE - ISPOINTER
regid

clearid
id.n = "_MOUSEMOVEMENTY"
id.subfunc = 1
id.callname = "func__mousemovementy"
id.ret = SINGLETYPE - ISPOINTER
regid

clearid
id.n = "_MOUSEBUTTON"
id.subfunc = 1
id.callname = "func__mousebutton"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "_MOUSEWHEEL"
id.subfunc = 1
id.callname = "func__mousewheel"
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "FREEFILE"
id.subfunc = 1
id.callname = "func_freefile"
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "NAME"
id.subfunc = 2
id.callname = "sub_name"
id.args = 2
id.arg = MKL$(STRINGTYPE - ISPOINTER) + MKL$(STRINGTYPE - ISPOINTER)
id.specialformat = "?{AS}?"
regid

clearid
id.n = "KILL"
id.subfunc = 2
id.callname = "sub_kill"
id.args = 1
id.arg = MKL$(STRINGTYPE - ISPOINTER)
regid

clearid
id.n = "CHDIR"
id.subfunc = 2
id.callname = "sub_chdir"
id.args = 1
id.arg = MKL$(STRINGTYPE - ISPOINTER)
regid

clearid
id.n = "MKDIR"
id.subfunc = 2
id.callname = "sub_mkdir"
id.args = 1
id.arg = MKL$(STRINGTYPE - ISPOINTER)
regid

clearid
id.n = "RMDIR"
id.subfunc = 2
id.callname = "sub_rmdir"
id.args = 1
id.arg = MKL$(STRINGTYPE - ISPOINTER)
regid

clearid
id.n = "CHAIN"
id.subfunc = 2
id.callname = "sub_chain"
id.args = 1
id.arg = MKL$(STRINGTYPE - ISPOINTER)
regid

clearid
id.n = "SHELL"
id.subfunc = 2
id.callname = "sub_shell"
id.args = 1
id.arg = MKL$(STRINGTYPE - ISPOINTER)
id.specialformat = "[?]"
'id.secondargcantbe = "_HIDE"
regid

clearid
id.n = "SHELL"
id.subfunc = 2
id.callname = "sub_shell2"
id.args = 1
id.arg = MKL$(STRINGTYPE - ISPOINTER)
id.specialformat = "{_HIDE}?"
id.secondargmustbe = "_HIDE"
regid

clearid
id.n = "SHELL"
id.subfunc = 2
id.callname = "sub_shell3"
id.args = 1
id.arg = MKL$(STRINGTYPE - ISPOINTER)
id.specialformat = "{_DONTWAIT}?"
id.secondargmustbe = "_DONTWAIT"
regid

clearid
id.n = "COMMAND"
id.musthave = "$"
id.subfunc = 1
id.callname = "func_command"
id.args = 0
id.ret = STRINGTYPE - ISPOINTER
regid

'QB64 AUDIO
clearid
id.n = "_SNDLEN"
id.subfunc = 1
id.callname = "func__sndlen"
id.args = 1
id.arg = MKL$(ULONGTYPE - ISPOINTER)
id.ret = SINGLETYPE - ISPOINTER
regid

clearid
id.n = "_SNDPAUSED"
id.subfunc = 1
id.callname = "func__sndpaused"
id.args = 1
id.arg = MKL$(ULONGTYPE - ISPOINTER)
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "_SNDPLAYFILE"
id.subfunc = 2
id.callname = "sub__sndplayfile"
id.args = 3
id.arg = MKL$(STRINGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(FLOATTYPE - ISPOINTER)
id.specialformat = "?[,[?][,?]]"
regid

clearid
id.n = "_SNDPLAYCOPY"
id.subfunc = 2
id.callname = "sub__sndplaycopy"
id.args = 2
id.arg = MKL$(ULONGTYPE - ISPOINTER) + MKL$(FLOATTYPE - ISPOINTER)
id.specialformat = "?[,?]"
regid

clearid
id.n = "_SNDSTOP"
id.subfunc = 2
id.callname = "sub__sndstop"
id.args = 1
id.arg = MKL$(ULONGTYPE - ISPOINTER)
regid

clearid
id.n = "_SNDLOOP"
id.subfunc = 2
id.callname = "sub__sndloop"
id.args = 1
id.arg = MKL$(ULONGTYPE - ISPOINTER)
regid

clearid
id.n = "_SNDLIMIT"
id.subfunc = 2
id.callname = "sub__sndlimit"
id.args = 2
id.arg = MKL$(ULONGTYPE - ISPOINTER) + MKL$(FLOATTYPE - ISPOINTER)
regid

clearid
id.n = "_SNDOPEN"
id.subfunc = 1
id.callname = "func__sndopen"
id.args = 2
id.arg = MKL$(STRINGTYPE - ISPOINTER) + MKL$(STRINGTYPE - ISPOINTER)
id.specialformat = "?[,?]"
id.ret = ULONGTYPE - ISPOINTER
regid

clearid
id.n = "_SNDSETPOS"
id.subfunc = 2
id.callname = "sub__sndsetpos"
id.args = 2
id.arg = MKL$(ULONGTYPE - ISPOINTER) + MKL$(DOUBLETYPE - ISPOINTER)
regid

clearid
id.n = "_SNDGETPOS"
id.subfunc = 1
id.callname = "func__sndgetpos"
id.args = 1
id.arg = MKL$(ULONGTYPE - ISPOINTER)
id.ret = SINGLETYPE - ISPOINTER
regid

clearid
id.n = "_SNDPLAYING"
id.subfunc = 1
id.callname = "func__sndplaying"
id.args = 1
id.arg = MKL$(ULONGTYPE - ISPOINTER)
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "_SNDPAUSE"
id.subfunc = 2
id.callname = "sub__sndpause"
id.args = 1
id.arg = MKL$(ULONGTYPE - ISPOINTER)
regid

clearid
id.n = "_SNDBAL"
id.subfunc = 2
id.callname = "sub__sndbal"
id.args = 4
id.arg = MKL$(ULONGTYPE - ISPOINTER) + MKL$(FLOATTYPE - ISPOINTER) + MKL$(FLOATTYPE - ISPOINTER) + MKL$(FLOATTYPE - ISPOINTER)
id.specialformat = "?,[?][,[?][,[?]]]"
regid


clearid
id.n = "_SNDVOL"
id.subfunc = 2
id.callname = "sub__sndvol"
id.args = 2
id.arg = MKL$(ULONGTYPE - ISPOINTER) + MKL$(FLOATTYPE - ISPOINTER)
regid

clearid
id.n = "_SNDPLAY"
id.subfunc = 2
id.callname = "sub__sndplay"
id.args = 1
id.arg = MKL$(ULONGTYPE - ISPOINTER)
regid

clearid
id.n = "_SNDCOPY"
id.subfunc = 1
id.callname = "func__sndcopy"
id.args = 1
id.arg = MKL$(ULONGTYPE - ISPOINTER)
id.ret = ULONGTYPE - ISPOINTER
regid

clearid
id.n = "_SNDCLOSE"
id.subfunc = 2
id.callname = "sub__sndclose"
id.args = 1
id.arg = MKL$(ULONGTYPE - ISPOINTER)
regid



clearid
id.n = "WRITE" 'stub
id.subfunc = 2
regid

clearid
id.n = "INPUT"
id.musthave = "$"
id.subfunc = 1
id.callname = "func_input"
id.args = 2
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "?[,?]"
id.ret = STRINGTYPE - ISPOINTER
regid

clearid
id.n = "SEEK"
id.subfunc = 2
id.callname = "sub_seek"
id.args = 2
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "[#]?,?"
regid

clearid
id.n = "SEEK"
id.subfunc = 1
id.callname = "func_seek"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "LOC"
id.subfunc = 1
id.callname = "func_loc"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "EOF"
id.subfunc = 1
id.callname = "func_eof"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "LOF"
id.subfunc = 1
id.callname = "func_lof"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.ret = LONGTYPE - ISPOINTER
regid


clearid
id.n = "SCREEN"
id.subfunc = 1
id.callname = "func_screen"
id.args = 3
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "?,?[,?]"
id.ret = ULONGTYPE - ISPOINTER
regid

clearid
id.n = "PMAP"
id.subfunc = 1
id.callname = "func_pmap"
id.args = 2
id.arg = MKL$(SINGLETYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
id.ret = SINGLETYPE - ISPOINTER
regid


clearid
id.n = "POINT"
id.subfunc = 1
id.callname = "func_point"
id.args = 2
id.arg = MKL$(SINGLETYPE - ISPOINTER) + MKL$(SINGLETYPE - ISPOINTER)
id.specialformat = "?[,?]"
id.ret = DOUBLETYPE - ISPOINTER
regid


clearid
id.n = "TAB"
id.subfunc = 1
id.callname = "func_tab"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.ret = STRINGTYPE - ISPOINTER
regid

clearid
id.n = "SPC"
id.subfunc = 1
id.callname = "func_spc"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.ret = STRINGTYPE - ISPOINTER
regid


clearid
id.n = "WAIT"
id.subfunc = 2
id.callname = "sub_wait"
id.args = 3
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "?,?[,?]"
regid

clearid
id.n = "INP"
id.subfunc = 1
id.callname = "func_inp"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "POS"
id.subfunc = 1
id.callname = "func_pos"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "SGN"
id.subfunc = 1
id.callname = "func_sgn"
id.args = 1
id.arg = MKL$(-1)
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "LBOUND"
id.subfunc = 1
id.args = 2
id.arg = MKL$(-1) + MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "?,[?]"
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "UBOUND"
id.subfunc = 1
id.args = 2
id.arg = MKL$(-1) + MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "?,[?]"
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "OCT"
id.musthave = "$"
id.subfunc = 1
id.args = 1
id.arg = MKL$(-1)
id.ret = STRINGTYPE - ISPOINTER
regid

clearid
id.n = "HEX"
id.musthave = "$"
id.subfunc = 1
id.args = 1
id.arg = MKL$(-1)
id.ret = STRINGTYPE - ISPOINTER
regid

clearid
id.n = "SLEEP"
id.subfunc = 2
id.callname = "sub_sleep"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "[?]"
regid

clearid
id.n = "EXP"
id.subfunc = 1
id.args = 1
id.arg = MKL$(-1)
id.ret = -1
regid

clearid
id.n = "FIX"
id.subfunc = 1
id.args = 1
id.arg = MKL$(-1)
id.ret = -1
regid

clearid
id.n = "INT"
id.subfunc = 1
id.args = 1
id.arg = MKL$(-1)
id.ret = -1
regid

clearid
id.n = "CDBL"
id.subfunc = 1
id.args = 1
id.arg = MKL$(-1)
id.ret = DOUBLETYPE - ISPOINTER
regid

clearid
id.n = "CSNG"
id.subfunc = 1
id.args = 1
id.arg = MKL$(-1)
id.ret = SINGLETYPE - ISPOINTER
regid

clearid
id.n = "_ROUND"
id.subfunc = 1
id.args = 1
id.arg = MKL$(-1)
id.ret = INTEGER64TYPE - ISPOINTER
regid

clearid
id.n = "CINT"
id.subfunc = 1
id.args = 1
id.arg = MKL$(-1)
id.ret = INTEGERTYPE - ISPOINTER
regid

clearid
id.n = "CLNG"
id.subfunc = 1
id.args = 1
id.arg = MKL$(-1)
id.ret = INTEGERTYPE - ISPOINTER
regid



clearid
id.n = "TIME"
id.musthave = "$"
id.subfunc = 2
id.callname = "sub_time"
id.args = 1
id.arg = MKL$(STRINGTYPE - ISPOINTER)
id.specialformat = "=?"
regid

clearid
id.n = "TIME"
id.musthave = "$"
id.subfunc = 1
id.callname = "func_time"
id.ret = STRINGTYPE - ISPOINTER
regid



clearid
id.n = "DATE"
id.musthave = "$"
id.subfunc = 2
id.callname = "sub_date"
id.args = 1
id.arg = MKL$(STRINGTYPE - ISPOINTER)
id.specialformat = "=?"
regid

clearid
id.n = "DATE"
id.musthave = "$"
id.subfunc = 1
id.callname = "func_date"
id.ret = STRINGTYPE - ISPOINTER
regid

clearid
id.n = "CSRLIN"
id.subfunc = 1
id.callname = "func_csrlin"
id.ret = LONGTYPE - ISPOINTER
regid


clearid
id.n = "PAINT"
id.subfunc = 2
id.callname = "sub_paint"
id.args = 6
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(FLOATTYPE - ISPOINTER) + MKL$(FLOATTYPE - ISPOINTER) + MKL$(ULONGTYPE - ISPOINTER) + MKL$(ULONGTYPE - ISPOINTER) + MKL$(STRINGTYPE - ISPOINTER)
id.specialformat = "[{STEP}](?,?)[,[?][,[?][,?]]]"
'PAINT [STEP] (x!,y!)[,[paint] [,[bordercolor&] [,background$]]]
regid

clearid
id.n = "CIRCLE"
id.subfunc = 2
id.callname = "sub_circle"
id.args = 8
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(FLOATTYPE - ISPOINTER) + MKL$(FLOATTYPE - ISPOINTER) + MKL$(FLOATTYPE - ISPOINTER) + MKL$(ULONGTYPE - ISPOINTER) + MKL$(FLOATTYPE - ISPOINTER) + MKL$(FLOATTYPE - ISPOINTER) + MKL$(FLOATTYPE - ISPOINTER)
id.specialformat = "[{STEP}](?,?),?[,[?][,[?][,[?][,?]]]]"
'CIRCLE [STEP] (x!,y!),radius![,[color&] [,[start!] [,[end!] [,aspect!]]]]
regid

clearid
id.n = "READ" 'stub
id.subfunc = 2
regid


clearid
id.n = "BLOAD"
id.subfunc = 2
id.callname = "sub_bload"
id.args = 2
id.arg = MKL$(STRINGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "?[,?]"
regid

clearid
id.n = "BSAVE"
id.subfunc = 2
id.callname = "sub_bsave"
id.args = 3
id.arg = MKL$(STRINGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
regid


clearid
id.n = "CLOSE" 'stub
id.subfunc = 2
regid

clearid
id.n = "RESET" 'stub
id.subfunc = 2
regid

clearid
id.n = "GET"
id.subfunc = 2
id.callname = "sub_get"
id.args = 3
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(-4)
'id.specialformat = "[#]?,[?],?" 'non field complient definition
id.specialformat = "[#]?[,[?][,?]]" 'field complient definition
regid

clearid
id.n = "PUT"
id.subfunc = 2
id.callname = "sub_put"
id.args = 3
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(-4)
'id.specialformat = "[#]?,[?],?" 'non field complient definition
id.specialformat = "[#]?[,[?][,?]]" 'field complient definition
regid

'double definition
clearid
id.n = "GET"
id.subfunc = 2
id.callname = "sub_graphics_get"
id.args = 8
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(FLOATTYPE - ISPOINTER) + MKL$(FLOATTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(FLOATTYPE - ISPOINTER) + MKL$(FLOATTYPE - ISPOINTER) + MKL$(-3) + MKL$(ULONGTYPE - ISPOINTER)
id.specialformat = "[{STEP}](?,?)-[{STEP}](?,?),?[,?]"
'GET [STEP](x1!,y1!)-[STEP](x2!,y2!),arrayname[(indexes%)]
id.secondargmustbe = "STEP"
regid
clearid
id.n = "GET"
id.subfunc = 2
id.callname = "sub_graphics_get"
id.args = 8
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(FLOATTYPE - ISPOINTER) + MKL$(FLOATTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(FLOATTYPE - ISPOINTER) + MKL$(FLOATTYPE - ISPOINTER) + MKL$(-3) + MKL$(ULONGTYPE - ISPOINTER)
id.specialformat = "[{STEP}](?,?)-[{STEP}](?,?),?[,?]"
'GET [STEP](x1!,y1!)-[STEP](x2!,y2!),arrayname[(indexes%)]
id.secondargmustbe = "("
regid

'double definition
clearid
id.n = "PUT"
id.subfunc = 2
id.callname = "sub_graphics_put"
id.args = 7
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(FLOATTYPE - ISPOINTER) + MKL$(FLOATTYPE - ISPOINTER) + MKL$(-3) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(ULONGTYPE - ISPOINTER)
id.specialformat = "[{STEP}](?,?),?[,[{_CLIP}][{PSET|PRESET|AND|OR|XOR}][,?]]"
'PUT [STEP] (x!,y!),arrayname# [(indexes%)] [,actionverb]
'PUT (10, 10), myimage, _CLIP, 0
id.secondargmustbe = "STEP"
regid
clearid
id.n = "PUT"
id.subfunc = 2
id.callname = "sub_graphics_put"
id.args = 7
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(FLOATTYPE - ISPOINTER) + MKL$(FLOATTYPE - ISPOINTER) + MKL$(-3) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(ULONGTYPE - ISPOINTER)
id.specialformat = "[{STEP}](?,?),?[,[{_CLIP}][{PSET|PRESET|AND|OR|XOR}][,?]]"
'PUT [STEP] (x!,y!),arrayname# [(indexes%)] [,actionverb]
'PUT (10, 10), myimage, _CLIP, 0
id.secondargmustbe = "("
regid

clearid
id.n = "OPEN"
id.subfunc = 2
id.callname = "sub_open_gwbasic"
id.args = 4
id.arg = MKL$(STRINGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(STRINGTYPE - ISPOINTER) +MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "?,[#]?,?[,?]"
regid
clearid
id.n = "OPEN"
id.subfunc = 2
id.callname = "sub_open"
id.args = 6
id.arg = MKL$(STRINGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "?[{FOR RANDOM|FOR BINARY|FOR INPUT|FOR OUTPUT|FOR APPEND}][{ACCESS READ WRITE|ACCESS READ|ACCESS WRITE}][{SHARED|LOCK READ WRITE|LOCK READ|LOCK WRITE}]{AS}[#]?[{LEN =}?]"
regid

clearid
id.n = "VAL"
id.subfunc = 1
id.callname = "func_val"
id.args = 1
id.arg = MKL$(STRINGTYPE - ISPOINTER)
id.ret = FLOATTYPE - ISPOINTER
regid

clearid
id.n = "MKSMBF"
id.musthave = "$"
id.subfunc = 1
id.callname = "func_mksmbf"
id.args = 1
id.arg = MKL$(SINGLETYPE - ISPOINTER)
id.ret = STRINGTYPE - ISPOINTER
regid
clearid
id.n = "MKDMBF"
id.musthave = "$"
id.subfunc = 1
id.callname = "func_mkdmbf"
id.args = 1
id.arg = MKL$(DOUBLETYPE - ISPOINTER)
id.ret = STRINGTYPE - ISPOINTER
regid

clearid
id.n = "MKI"
id.musthave = "$"
id.subfunc = 1
id.callname = ""
id.args = 1
id.arg = MKL$(INTEGERTYPE - ISPOINTER)
id.ret = STRINGTYPE - ISPOINTER
regid
clearid
id.n = "MKL"
id.musthave = "$"
id.subfunc = 1
id.callname = ""
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.ret = STRINGTYPE - ISPOINTER
regid
clearid
id.n = "MKS"
id.musthave = "$"
id.subfunc = 1
id.callname = ""
id.args = 1
id.arg = MKL$(SINGLETYPE - ISPOINTER)
id.ret = STRINGTYPE - ISPOINTER
regid
clearid
id.n = "MKD"
id.musthave = "$"
id.subfunc = 1
id.callname = ""
id.args = 1
id.arg = MKL$(DOUBLETYPE - ISPOINTER)
id.ret = STRINGTYPE - ISPOINTER
regid
clearid
id.n = "_MK"
id.musthave = "$"
id.subfunc = 1
id.callname = ""
id.args = 2
id.arg = MKL$(-1) + MKL$(-1)
id.ret = STRINGTYPE - ISPOINTER
regid

clearid
id.n = "CVSMBF"
id.subfunc = 1
id.callname = "func_cvsmbf"
id.args = 1
id.arg = MKL$(STRINGTYPE - ISPOINTER)
id.ret = SINGLETYPE - ISPOINTER
regid
clearid
id.n = "CVDMBF"
id.subfunc = 1
id.callname = "func_cvdmbf"
id.args = 1
id.arg = MKL$(STRINGTYPE - ISPOINTER)
id.ret = DOUBLETYPE - ISPOINTER
regid

clearid
id.n = "CVI"
id.subfunc = 1
id.callname = ""
id.args = 1
id.arg = MKL$(STRINGTYPE - ISPOINTER)
id.ret = INTEGERTYPE - ISPOINTER
regid
clearid
id.n = "CVL"
id.subfunc = 1
id.callname = ""
id.args = 1
id.arg = MKL$(STRINGTYPE - ISPOINTER)
id.ret = LONGTYPE - ISPOINTER
regid
clearid
id.n = "CVS"
id.subfunc = 1
id.callname = ""
id.args = 1
id.arg = MKL$(STRINGTYPE - ISPOINTER)
id.ret = SINGLETYPE - ISPOINTER
regid
clearid
id.n = "CVD"
id.subfunc = 1
id.callname = ""
id.args = 1
id.arg = MKL$(STRINGTYPE - ISPOINTER)
id.ret = DOUBLETYPE - ISPOINTER
regid
clearid
id.n = "_CV"
id.subfunc = 1
id.callname = ""
id.args = 2
id.arg = MKL$(-1) + MKL$(STRINGTYPE - ISPOINTER)
id.ret = -1
regid

clearid
id.n = "STRING"
id.musthave = "$"
id.subfunc = 1
id.callname = "func_string"
id.args = 2
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
id.ret = STRINGTYPE - ISPOINTER
regid

clearid
id.n = "SPACE"
id.musthave = "$"
id.subfunc = 1
id.callname = "func_space"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.ret = STRINGTYPE - ISPOINTER
regid

clearid
id.n = "INSTR"
id.subfunc = 1
id.callname = "func_instr"
id.args = 3
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(STRINGTYPE - ISPOINTER) + MKL$(STRINGTYPE - ISPOINTER)
id.ret = LONGTYPE - ISPOINTER
id.specialformat = "[?],?,?" 'checked!
regid

clearid
id.n = "MID"
id.musthave = "$"
id.subfunc = 1
id.callname = "func_mid"
id.args = 3
id.arg = MKL$(STRINGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
id.ret = STRINGTYPE - ISPOINTER
id.specialformat = "?,?,[?]" 'checked!
regid

clearid
id.n = "SADD"
id.subfunc = 1
id.callname = ""
id.args = 1
id.arg = MKL$(-1) '!this value is ignored, the qb64 compiler handles this function
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "CLS"
id.subfunc = 2
id.callname = "sub_cls"
id.args = 2
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(ULONGTYPE - ISPOINTER)
id.specialformat = "[?][,?]"
regid

clearid
id.n = "SQR"
id.subfunc = 1
id.callname = "func_sqr"
id.args = 1
id.arg = MKL$(FLOATTYPE - ISPOINTER)
id.ret = FLOATTYPE - ISPOINTER
regid

clearid
id.n = "CHR"
id.musthave = "$"
id.subfunc = 1
id.callname = "func_chr"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.ret = STRINGTYPE - ISPOINTER
regid

clearid
id.n = "VARPTR"
id.subfunc = 1
id.callname = ""
id.args = 1
id.arg = MKL$(-1) '!this value is ignored, the qb64 compiler handles this function
id.ret = STRINGTYPE - ISPOINTER
id.musthave = "$"
regid


clearid
id.n = "VARPTR"
id.subfunc = 1
id.callname = ""
id.args = 1
id.arg = MKL$(-1) '!this value is ignored, the qb64 compiler handles this function
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "VARSEG"
id.subfunc = 1
id.callname = ""
id.args = 1
id.arg = MKL$(-1) '!this value is ignored, the qb64 compiler handles this function
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "POKE"
id.subfunc = 2
id.callname = "sub_poke"
id.args = 2
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
regid

clearid
id.n = "PEEK"
id.subfunc = 1
id.callname = "func_peek"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "DEF"
id.subfunc = 2
id.callname = "sub_defseg"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "{SEG}[=?]" 'checked!
id.secondargmustbe = "SEG"
regid

clearid
id.n = "SIN"
id.subfunc = 1
id.callname = "sin"
id.args = 1
id.arg = MKL$(FLOATTYPE - ISPOINTER)
id.ret = FLOATTYPE - ISPOINTER
regid

clearid
id.n = "COS"
id.subfunc = 1
id.callname = "cos"
id.args = 1
id.arg = MKL$(FLOATTYPE - ISPOINTER)
id.ret = FLOATTYPE - ISPOINTER
regid

clearid
id.n = "TAN"
id.subfunc = 1
id.callname = "tan"
id.args = 1
id.arg = MKL$(FLOATTYPE - ISPOINTER)
id.ret = FLOATTYPE - ISPOINTER
regid

clearid
id.n = "ATN"
id.subfunc = 1
id.callname = "atan"
id.args = 1
id.arg = MKL$(FLOATTYPE - ISPOINTER)
id.ret = FLOATTYPE - ISPOINTER
regid

clearid
id.n = "LOG"
id.subfunc = 1
id.callname = "func_log"
id.args = 1
id.arg = MKL$(FLOATTYPE - ISPOINTER)
id.ret = FLOATTYPE - ISPOINTER
regid

clearid
id.n = "ABS"
id.subfunc = 1
id.callname = "func_abs"
id.args = 1
id.arg = MKL$(-1) 'takes anything numerical
id.ret = FLOATTYPE - ISPOINTER '***overridden by function evaluatefunc***
regid

clearid
id.n = "ERL"
id.subfunc = 1
id.callname = "get_error_erl"
id.args = 0
id.ret = DOUBLETYPE - ISPOINTER
regid

clearid
id.n = "ERR"
id.subfunc = 1
id.callname = "get_error_err"
id.args = 0
id.ret = ULONGTYPE - ISPOINTER
regid

clearid
id.n = "ERROR"
id.subfunc = 2
id.callname = "error"
id.args = 1
id.arg = MKL$(ULONGTYPE - ISPOINTER)
regid

clearid
id.n = "LINE"
id.subfunc = 2
id.callname = "sub_line"
id.args = 9
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(FLOATTYPE - ISPOINTER) + MKL$(FLOATTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(FLOATTYPE - ISPOINTER) + MKL$(FLOATTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$ _
(LONGTYPE - ISPOINTER)
id.specialformat = "[[{STEP}](?,?)]-[{STEP}](?,?)[,[?][,[{B|BF}][,?]]]"
regid

clearid
id.n = "SOUND"
id.subfunc = 2
id.callname = "sub_sound"
id.args = 2
id.arg = MKL$(DOUBLETYPE - ISPOINTER) + MKL$(DOUBLETYPE - ISPOINTER)
regid

clearid
id.n = "BEEP"
id.subfunc = 2
id.callname = "sub_beep"
id.args = 0
regid

clearid
id.n = "TIMER"
id.subfunc = 1
id.callname = "func_timer"
id.args = 1
id.arg = MKL$(DOUBLETYPE - ISPOINTER)
id.ret = SINGLETYPE - ISPOINTER
id.specialformat = "[?]"
regid

clearid
id.n = "RND"
id.subfunc = 1
id.callname = "func_rnd"
id.args = 1
id.arg = MKL$(FLOATTYPE - ISPOINTER)
id.ret = SINGLETYPE - ISPOINTER
id.specialformat = "[?]" 'checked!
regid

clearid
id.n = "RANDOMIZE"
id.subfunc = 2
id.callname = "sub_randomize"
id.args = 1
id.arg = MKL$(DOUBLETYPE - ISPOINTER)
id.specialformat = "[?]" 'checked!
regid

clearid
id.n = "OUT"
id.subfunc = 2
id.callname = "sub_out"
id.args = 2
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
regid

clearid
id.n = "PCOPY"
id.subfunc = 2
id.callname = "sub_pcopy"
id.args = 2
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
regid

clearid
id.n = "VIEW"
id.subfunc = 2
id.callname = "qbg_sub_view"
id.args = 7
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "[[{SCREEN}](?,?)-(?,?)[,[?][,?]]]" 'new!
id.secondargcantbe = "PRINT"
regid

clearid
id.n = "VIEW"
id.subfunc = 2
id.callname = "qbg_sub_view_print"
id.args = 2
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "{PRINT}[?{TO}?]" 'new!
id.secondargmustbe = "PRINT"
regid

clearid
id.n = "INPUT"
id.subfunc = 2
'stub
regid

clearid
id.n = "WINDOW"
id.subfunc = 2
id.callname = "qbg_sub_window"
id.args = 5
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(FLOATTYPE - ISPOINTER) + MKL$(FLOATTYPE - ISPOINTER) + MKL$(FLOATTYPE - ISPOINTER) + MKL$(FLOATTYPE - ISPOINTER)
id.specialformat = "[[{SCREEN}](?,?)-(?,?)]"
regid

clearid
id.n = "LOCATE"
id.subfunc = 2
id.callname = "qbg_sub_locate"
id.args = 5
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "[?][,[?][,[?][,?,?]]]"
regid

clearid
id.n = "COLOR"
id.subfunc = 2
id.callname = "qbg_sub_color"
id.args = 3
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "[?][,[?][,?]]"
regid

clearid
id.n = "PALETTE"
id.subfunc = 2
id.callname = "qbg_palette"
id.args = 2
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "[?,?]"
regid

clearid
id.n = "WIDTH"
id.subfunc = 2
id.callname = "qbsub_width"
id.args = 3
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "[{#|LPRINT}][?][,?]" 'new!
regid

clearid
id.n = "SCREEN"
id.subfunc = 2
id.callname = "qbg_screen"
id.args = 5
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
'id.specialformat = "[?][,[?][,[?][,?]]]" 'new!
'id.specialformat = "[?][,[?][,[?][,[?][,{_MANUALDISPLAY}]]]]" 'breaks compilation!
id.specialformat = "[?][,[?][,[?][,[?][,[{_MANUALDISPLAY}]]]]]"
regid

clearid
id.n = "PSET"
id.subfunc = 2
id.callname = "qbg_pset"
id.args = 4
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(FLOATTYPE - ISPOINTER) + MKL$(FLOATTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "[{STEP}](?,?)[,?]" 'new!
regid

clearid
id.n = "PRESET"
id.subfunc = 2
id.callname = "sub_preset"
id.args = 4
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(FLOATTYPE - ISPOINTER) + MKL$(FLOATTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
id.specialformat = "[{STEP}](?,?)[,?]"
regid

clearid
id.n = "ASC"
id.subfunc = 1
id.callname = "qbs_asc"
id.args = 1
id.arg = MKL$(STRINGTYPE - ISPOINTER)
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "LEN"
id.subfunc = 1
id.callname = "" 'callname is not used
id.args = 1
id.arg = MKL$(STRINGTYPE - ISPOINTER) 'note: LEN is a special case, any input is actually accepted
id.ret = LONGTYPE - ISPOINTER
regid

clearid
id.n = "INKEY"
id.musthave = "$"
id.subfunc = 1
id.callname = "qbs_inkey"
id.ret = STRINGTYPE - ISPOINTER
regid

clearid
id.n = "STR"
id.musthave = "$"
id.subfunc = 1
id.callname = "qbs_str"
id.args = 1
id.arg = MKL$(-1)
id.ret = STRINGTYPE - ISPOINTER
regid

clearid
id.n = "UCASE"
id.musthave = "$"
id.subfunc = 1
id.callname = "qbs_ucase"
id.args = 1
id.arg = MKL$(STRINGTYPE - ISPOINTER)
id.ret = STRINGTYPE - ISPOINTER
regid

clearid
id.n = "LCASE"
id.musthave = "$"
id.subfunc = 1
id.callname = "qbs_lcase"
id.args = 1
id.arg = MKL$(STRINGTYPE - ISPOINTER)
id.ret = STRINGTYPE - ISPOINTER
regid

clearid
id.n = "LEFT"
id.musthave = "$"
id.subfunc = 1
id.callname = "qbs_left"
id.args = 2
id.arg = MKL$(STRINGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
id.ret = STRINGTYPE - ISPOINTER
regid

clearid
id.n = "RIGHT"
id.musthave = "$"
id.subfunc = 1
id.callname = "qbs_right"
id.args = 2
id.arg = MKL$(STRINGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
id.ret = STRINGTYPE - ISPOINTER
regid

clearid
id.n = "LTRIM"
id.musthave = "$"
id.subfunc = 1
id.callname = "qbs_ltrim"
id.args = 1
id.arg = MKL$(STRINGTYPE - ISPOINTER)
id.ret = STRINGTYPE - ISPOINTER
regid

clearid
id.n = "RTRIM"
id.musthave = "$"
id.subfunc = 1
id.callname = "qbs_rtrim"
id.args = 1
id.arg = MKL$(STRINGTYPE - ISPOINTER)
id.ret = STRINGTYPE - ISPOINTER
regid

clearid
id.n = "PRINT"
id.subfunc = 2
id.callname = "qbs_print" 'not called directly
id.args = 1
id.arg = MKL$(STRINGTYPE - ISPOINTER)
regid

clearid
id.n = "LPRINT"
id.subfunc = 2
id.callname = "qbs_lprint" 'not called directly
id.args = 1
id.arg = MKL$(STRINGTYPE - ISPOINTER)
regid

clearid
id.n = "LPRINT"
id.subfunc = 2
id.callname = "qbs_lprint" 'not called directly
id.args = 1
id.arg = MKL$(STRINGTYPE - ISPOINTER)
regid

clearid
id.n = "LPOS"
id.subfunc = 1
id.callname = "func_lpos"
id.args = 1
id.arg = MKL$(LONGTYPE - ISPOINTER)
id.ret = LONGTYPE - ISPOINTER
regid

END SUB

'this sub is faulty atm!
'sub replacelement (a$, i, newe$)
''note: performs no action for out of range values of i
'e=1
's=1
'do
'x=instr(s,a$,sp)
'if x then
'if e=i then
'a1$=left$(a$,s-1): a2$=right$(a$,len(a$)-x+1)
'a$=a1$+sp+newe$+a2$ 'note: a2 includes spacer
'exit sub
'end if
's=x+1
'e=e+1
'end if
'loop until x=0
'if e=i then
'a$=left$(a$,s-1)+sp+newe$
'end if
'end sub


SUB removeelements (a$, first, last, keepindexing)
a2$ = ""
'note: first and last MUST be valid
'      keepindexing means the number of elements will stay the same
'       but some elements will be equal to ""

n = numelements(a$)
FOR i = 1 TO n
    IF i < first OR i > last THEN
        a2$ = a2$ + sp + getelement(a$, i)
    ELSE
        IF keepindexing THEN a2$ = a2$ + sp
    END IF
NEXT
IF LEFT$(a2$, 1) = sp THEN a2$ = RIGHT$(a2$, LEN(a2$) - 1)

a$ = a2$

END SUB

FUNCTION removesymbol$ (varname$)
i = INSTR(varname$, "~"): IF i THEN GOTO foundsymbol
i = INSTR(varname$, "`"): IF i THEN GOTO foundsymbol
i = INSTR(varname$, "%"): IF i THEN GOTO foundsymbol
i = INSTR(varname$, "&"): IF i THEN GOTO foundsymbol
i = INSTR(varname$, "!"): IF i THEN GOTO foundsymbol
i = INSTR(varname$, "#"): IF i THEN GOTO foundsymbol
i = INSTR(varname$, "$"): IF i THEN GOTO foundsymbol
EXIT FUNCTION
foundsymbol:
IF i = 1 THEN nerror (84)
removesymbol$ = RIGHT$(varname$, LEN(varname$) - i + 1)
varname$ = LEFT$(varname$, i - 1)
END FUNCTION

FUNCTION scope$
IF id.share THEN scope$ = module$ + "__": EXIT FUNCTION
scope$ = module$ + "_" + subfunc$ + "_"
END FUNCTION

FUNCTION seperateargs (a$, ca$, pass&)
pass& = 0

FOR i = 1 TO 60: separgs(i) = "": NEXT
FOR i = 1 TO 61: separgslayout(i) = "": NEXT

DIM id2 AS idstruct

id2 = id

IF id2.args = 0 THEN EXIT FUNCTION 'no arguments!

s$ = id2.specialformat
s$ = RTRIM$(s$)
IF s$ = "" THEN
    FOR i = 1 TO id2.args
        IF i <> 1 THEN s$ = s$ + ",?" ELSE s$ = "?"
    NEXT
END IF

'these options are independent of separgs, because they refer to the
'format of the sub/function HOWEVER, the first value should be larger
'than the value used in separgs
'the second value is the number of options in a block such as
'{A|BAT|CAT}
DIM opt(1 TO 100, 1 TO 100) AS STRING
DIM optwords(1 TO 100, 1 TO 100) AS INTEGER
DIM lev(1 TO 100) AS INTEGER
DIM entrylev(1 TO 100) AS INTEGER
DIM t(1 TO 100) AS INTEGER
DIM dontpass(1 TO 100) AS INTEGER
DIM passflag(1 TO 100) AS INTEGER 'used to avoid passing duplicate "passed" flags
DIM levelentered(100) 'up to 64 levels supported

nextentrylevel = 0
nextentrylevelset = 1
level = 0
lastt = 0

FOR i = 1 TO LEN(s$)
    s2$ = MID$(s$, i, 1)

    IF s2$ = "[" THEN
        level = level + 1
        levelentered(level) = 0
        GOTO nextsymbol
    END IF

    IF s2$ = "]" THEN
        level = level - 1
        GOTO nextsymbol
    END IF

    IF s2$ = "{" THEN
        lastt = lastt + 1: lev(lastt) = level

        i = i + 1
        i2 = INSTR(i, s$, "}")
        numopts = 0
        nextopt:
        numopts = numopts + 1
        i3 = INSTR(i + 1, s$, "|")
        IF i3 <> 0 AND i3 < i2 THEN
            opt(lastt, numopts) = MID$(s$, i, i3 - i)
            i = i3 + 1: GOTO nextopt
        END IF
        opt(lastt, numopts) = MID$(s$, i, i2 - i)
        t(lastt) = numopts
        'calculate words in each option
        FOR x = 1 TO t(lastt)
            w = 1
            x2 = 1
            newword:
            IF INSTR(x2, opt(lastt, x), " ") THEN w = w + 1: x2 = INSTR(x2, opt(lastt, x), " ") + 1: GOTO newword
            optwords(lastt, x) = w
        NEXT
        i = i2

        'set entry level routine
        entrylev(lastt) = level 'default level when continuing a previously entered level
        IF levelentered(level) = 0 THEN
            entrylev(lastt) = 0
            FOR i2 = 1 TO level - 1
                IF levelentered(i2) = 1 THEN entrylev(lastt) = i2
            NEXT
        END IF
        levelentered(level) = 1

        GOTO nextsymbol
    END IF

    IF s2$ = "?" THEN
        lastt = lastt + 1: lev(lastt) = level
        t(lastt) = 0

        'set entry level routine
        entrylev(lastt) = level 'default level when continuing a previously entered level
        IF levelentered(level) = 0 THEN
            entrylev(lastt) = 0
            FOR i2 = 1 TO level - 1
                IF levelentered(i2) = 1 THEN entrylev(lastt) = i2
            NEXT
        END IF
        levelentered(level) = 1

        GOTO nextsymbol
    END IF

    'assume "special" character (like ( ) , . - etc.)
    lastt = lastt + 1: lev(lastt) = level
    t(lastt) = 1: opt(lastt, 1) = s2$: optwords(lastt, 1) = 1: dontpass(lastt) = 1

    'set entry level routine
    entrylev(lastt) = level 'default level when continuing a previously entered level
    IF levelentered(level) = 0 THEN
        entrylev(lastt) = 0
        FOR i2 = 1 TO level - 1
            IF levelentered(i2) = 1 THEN entrylev(lastt) = i2
        NEXT
    END IF
    levelentered(level) = 1

    GOTO nextsymbol

    nextsymbol:
NEXT

DIM nopasslist(1 TO 100) AS INTEGER
FOR x = 1 TO lastt
    IF lev(x) = 0 THEN
        IF t(x) = 1 THEN dontpass(x) = 1
    END IF
NEXT

x1 = 0
optional = 0
nopasslistn = 0
FOR l = 1 TO 32767
    scannextlevel = 0

    FOR x = 1 TO lastt
        IF lev(x) > l THEN scannextlevel = 1

        IF x1 THEN
            IF entrylev(x) < l THEN
                IF optional THEN
                    FOR x2 = 1 TO nopasslistn: dontpass(nopasslist(x2)) = 1: NEXT
                ELSE
                    FOR x2 = 2 TO nopasslistn: dontpass(nopasslist(x2)) = 1: NEXT
                END IF
                x1 = 0
            END IF
        END IF

        IF lev(x) = l THEN
            IF entrylev(x) < l THEN x1 = x: optional = 0: nopasslistn = 0
        END IF

        IF x1 THEN
            IF lev(x) > l THEN optional = 1
            IF lev(x) = l THEN
                IF t(x) <> 1 THEN optional = 1
                IF t(x) = 1 THEN nopasslistn = nopasslistn + 1: nopasslist(nopasslistn) = x
            END IF
        END IF

    NEXT
    'scan last run
    IF x1 THEN
        IF optional THEN
            FOR x2 = 1 TO nopasslistn: dontpass(nopasslist(x2)) = 1: NEXT
        ELSE
            FOR x2 = 2 TO nopasslistn: dontpass(nopasslist(x2)) = 1: NEXT
        END IF
    END IF
    IF scannextlevel = 0 THEN EXIT FOR
NEXT

'should consider changes from previous pass
x1 = 0
optional = 0
nopasslistn = 0
FOR l = 1 TO 32767
    scannextlevel = 0

    FOR x = 1 TO lastt
        IF lev(x) > l THEN scannextlevel = 1

        IF x1 THEN
            IF entrylev(x) < l THEN
                IF nopasslistn THEN passflag(nopasslist(1)) = 1
                x1 = 0
            END IF
        END IF

        IF lev(x) = l THEN
            IF entrylev(x) < l THEN x1 = x: nopasslistn = 0
            IF x1 = 0 THEN
                IF lev(x - 1) > l THEN x1 = x: nopasslistn = 0
            END IF
        END IF

        IF x1 THEN
            IF lev(x) > l THEN optional = 1
            IF lev(x) = l THEN
                IF dontpass(x) = 0 AND t(x) = 0 THEN nopasslistn = nopasslistn + 1: nopasslist(nopasslistn) = x
            END IF
        END IF

    NEXT
    'scan last run
    IF x1 THEN
        IF entrylev(x) < l THEN
            IF nopasslistn THEN passflag(nopasslist(1)) = 1
            x1 = 0
        END IF
    END IF
    IF scannextlevel = 0 THEN EXIT FOR
NEXT

FOR i = 1 TO lastt: separgs(i) = "null": NEXT

'visualize opts
GOTO skipvisopts

COLOR 15
LOCATE 1, 1
PRINT "FORMAT:"
PRINT s$
x = 1
FOR i = 1 TO lastt
    COLOR 7
    LOCATE 20 - lev(i), x: PRINT str2(lev(i) + 0) '"*" 'str2(t(i) + 0)
    COLOR 8
    extra = 0
    IF t(i) = 0 THEN
        LOCATE 20 - lev(i) - 1, x: PRINT "?"
        extra = 1
    ELSE
        FOR i2 = 1 TO t(i)
            LOCATE 20 - lev(i) - 1 - t(i) + i2, x: PRINT opt(i, i2)
            IF extra < LEN(opt(i, i2)) THEN extra = LEN(opt(i, i2))
        NEXT
    END IF
    COLOR 1
    LOCATE 21, x: IF entrylev(i) <> -1 THEN PRINT str2(entrylev(i) + 0) ELSE PRINT "-"
    LOCATE 22, x: IF dontpass(i) THEN COLOR 4: PRINT "X" ELSE COLOR 2: PRINT "P"
    LOCATE 23, x: IF passflag(i) THEN COLOR 10: PRINT "û"
    x = x + 1 + extra
NEXT
COLOR 7
SLEEP
LOCATE 24, 1
skipvisopts:

DIM readahead(1 TO 8) AS STRING

n = numelements(a$)
s = 1 'next item to check (assume at least 1 item exists!)
i = 1
level = 0
currentexpression = -1
l$ = ""
sepnextarg:

e$ = ""
b = 0
nextexpele:
'reload read-ahead buffers
IF (i <= n) THEN e2$ = getelement$(ca$, i) ELSE e2$ = ""
readahead(1) = UCASE$(e2$)
FOR x = 1 TO 7
    IF ((i + x) <= n) THEN readahead(x + 1) = readahead(x) + " " + getelement$(a$, i + x) ELSE readahead(x + 1) = ""
NEXT

IF b = 0 THEN
    currentexpression = -1
    l = level 'temp. level
    FOR x = s TO lastt
        IF entrylev(x) < l THEN l = entrylev(x) 'lower l

        IF entrylev(x) <= l THEN 'it is possible to enter this level

            'register an expression?
            IF t(x) = 0 THEN

                IF currentexpression = -1 THEN
                    currentexpression = x: level = lev(x)
                    x = x + 1
                END IF

            END IF

            IF t(x) THEN

                x3 = x
                FOR x2 = 1 TO t(x3)
                    'PRINT readahead(optwords(x3, x2)), opt(x3, x2)
                    IF readahead(optwords(x3, x2)) = opt(x3, x2) THEN
                        IF e$ <> "" THEN
                            'IF currentexpression = -1 THEN PRINT "ILLEGAL EXPRESSION!"
                            'separgslayout(currentexpression) = "@"+l$
                            separgs(currentexpression) = e$
                            currentexpression = -1
                        END IF

                        'aha x3 is x, and x is the point in the syntax we are up to
                        'x begins at s(the start) to lastt(the last point in the syntax)

                        'unfortunately it may be near impossible to deduce which opts are choices
                        'aha, it seems unneeded args are culled after(see below)
                        'this could destroy some of these args but... that's ok they can be added to others

                        e$ = ""
                        separgslayout(x3) = CHR$(LEN(opt(x3, x2))) + opt(x3, x2)
                        separgs(x3) = CHR$(0) + str2(x2)
                        i = i + optwords(x3, x2)
                        s = x3 + 1
                        level = lev(x3)
                        GOTO sepnextarg
                    END IF
                NEXT x2

                'PRINT l, lev(x)

                IF l = lev(x) THEN 'is level we are in now the same as this options level?
                    'if so, a mandatory item has been encountered!
                    'missing mandatory option encountered! abort this scan
                    'PRINT "Aborted!"
                    GOTO abortoptscan
                END IF

            END IF 't(x)<>0

        END IF
    NEXT
    abortoptscan:

END IF

IF e2$ = "(" THEN b = b + 1
IF e2$ = ")" THEN b = b - 1
IF e$ <> "" THEN e$ = e$ + sp + e2$ ELSE e$ = e2$

IF i < n THEN
    i = i + 1
    GOTO nextexpele
END IF

IF e$ <> "" THEN
    'should this create an error?
    IF currentexpression = -1 THEN qb64error "Syntax error in expression"

    'separgslayout(currentexpression) = "#"+l$
    separgs(currentexpression) = e$
    currentexpression = -1
END IF

'PRINT "--------SEPERATE ARGUMENTS REPORT--------"
'PRINT "----FORMAT----"
'PRINT s$
'PRINT "----SEPARGS(...)----"
'FOR i = 1 TO lastt
'PRINT separgs(i)
'NEXT
'PRINT lastt

pass& = 0
x = 1
omitn = 0
omitnpassed = 0
FOR i = 1 TO lastt
    IF dontpass(i) = 0 THEN

        IF passflag(i) THEN omit = 1: omitn = omitn + 1
        IF separgs(i) <> "null" AND passflag(i) = 1 THEN pass& = pass& + (2& ^ (omitn - 1)): omitnpassed = omitnpassed + 1
        separgs(x) = separgs(i)
        separgslayout(x) = separgslayout(i)

        IF LEN(separgs(x)) THEN
            IF ASC(separgs(x)) = 0 THEN
                'switch omit layout tag from item to layout info
                separgs(x) = RIGHT$(separgs(x), LEN(separgs(x)) - 1)
                separgslayout(x) = separgslayout(x) + CHR$(0)
            END IF
        END IF

        IF separgs(x) = "null" THEN separgs(x) = "NULL"
        x = x + 1

    ELSE
        'its gonna be skipped!
        'add it to the next one to be safe
        separgslayout(i + 1) = separgslayout(i) + separgslayout(i + 1)

    END IF
NEXT
separgslayout(x) = separgslayout(i) 'set final layout



x = x - 1

'PRINT "total arguments:"; x
'PRINT "omittable arguments passed:"; omitnpassed; "/"; omitn
'PRINT "pass omit (0/1):"; omit
'PRINT "pass&="; pass&

seperateargs = omit
END FUNCTION

SUB setrefer (a2$, typ2 AS LONG, e2$, method AS LONG)
a$ = a2$: typ = typ2: e$ = e2$
IF method <> 1 THEN e$ = fixoperationorder$(e$)
tl$ = tlayout$

'method: 0 evaulatetotyp e$
'        1 skip evaluation of e$ and use as is
'*due to the complexity of setting a reference with a value/string
' this function handles the problem

'retrieve ID
i = INSTR(a$, "³")
IF i THEN
    idnumber = VAL(LEFT$(a$, i - 1)): a$ = RIGHT$(a$, LEN(a$) - i)
ELSE
    idnumber = VAL(a$)
END IF
getid idnumber


'UDT?
IF typ AND ISUDT THEN

    'print "setrefer-ing a UDT!"
    u = VAL(a$)
    i = INSTR(a$, "³"): a$ = RIGHT$(a$, LEN(a$) - i): e = VAL(a$)
    i = INSTR(a$, "³"): o$ = RIGHT$(a$, LEN(a$) - i)
    n$ = "UDT_" + RTRIM$(id.n): IF id.t = 0 THEN n$ = "ARRAY_" + n$ + "[0]"


    IF e = 0 THEN
        'use u and u's size

        IF method <> 0 THEN qb64error "Unexpected internal code reference to UDT"
        lhsscope$ = scope$
        e$ = evaluate(e$, t2)
        IF (t2 AND ISUDT) = 0 THEN qb64error "Expected = similar user defined type"
        idnumber2 = VAL(e$)
        getid idnumber2
        n2$ = "UDT_" + RTRIM$(id.n): IF id.t = 0 THEN n2$ = "ARRAY_" + n2$ + "[0]"
        i = INSTR(e$, "³"): e$ = RIGHT$(e$, LEN(e$) - i): u2 = VAL(e$)
        i = INSTR(e$, "³"): e$ = RIGHT$(e$, LEN(e$) - i): e2 = VAL(e$)
        i = INSTR(e$, "³"): o2$ = RIGHT$(e$, LEN(e$) - i)
        'WARNING: u2 may need minor modifications based on e to see if they are the same
        IF u <> u2 OR e2 <> 0 THEN qb64error "Expected = similar user defined type"

        'we have now established we have 2 pointers to similar data types!
        'ASSUME BYTE TYPE!!!

        dst$ = "(((char*)" + lhsscope$ + n$ + ")+(" + o$ + "))"
        src$ = "(((char*)" + scope$ + n2$ + ")+(" + o2$ + "))"
        siz$ = str2$(udtxsize(u) \ 8)

        PRINT #12, "memcpy(" + dst$ + "," + src$ + "," + siz$ + ");"

        'print "setFULLUDTrefer!"

        tlayout$ = tl$
        EXIT SUB

    END IF 'e=0

    IF typ AND ISOFFSETINBITS THEN qb64error "Cannot resolve bit-length variables inside user defined types yet"
    IF typ AND ISSTRING THEN
        o2$ = "(((uint8*)" + scope$ + n$ + ")+(" + o$ + "))"
        r$ = "qbs_new_fixed(" + o2$ + "," + str2(udtetypesize(e)) + ",1)"
        IF method = 0 THEN e$ = evaluatetotyp(e$, STRINGTYPE - ISPOINTER)
        PRINT #12, "qbs_set(" + r$ + "," + e$ + ");"
    ELSE
        typ = typ - ISUDT - ISREFERENCE - ISPOINTER
        IF typ AND ISARRAY THEN typ = typ - ISARRAY
        t$ = typ2ctyp$(typ, "")
        o2$ = "(((char*)" + scope$ + n$ + ")+(" + o$ + "))"
        r$ = "*" + "(" + t$ + "*)" + o2$
        IF method = 0 THEN e$ = evaluatetotyp(e$, typ)
        PRINT #12, r$ + "=" + e$ + ";"
    END IF

    'print "setUDTrefer:"+r$,e$
    tlayout$ = tl$
    EXIT SUB
END IF


'array?
IF id.arraytype THEN
    n$ = RTRIM$(id.callname)
    typ = typ - ISPOINTER - ISREFERENCE 'typ now looks like a regular value

    IF (typ AND ISSTRING) THEN
        IF (typ AND ISFIXEDLENGTH) THEN
            offset$ = "&((uint8*)(" + n$ + "[0]))[tmp_long*" + str2(id.tsize) + "]"
            r$ = "qbs_new_fixed(" + offset$ + "," + str2(id.tsize) + ",1)"
            PRINT #12, "tmp_long=" + a$ + ";"
            IF method = 0 THEN
                l$ = "if (!new_error) qbs_set(" + r$ + "," + evaluatetotyp(e$, typ) + ");"
            ELSE
                l$ = "if (!new_error) qbs_set(" + r$ + "," + e$ + ");"
            END IF
            PRINT #12, l$
        ELSE
            PRINT #12, "tmp_long=" + a$ + ";"
            IF method = 0 THEN
                l$ = "if (!new_error) qbs_set( ((qbs*)(((uint64*)(" + n$ + "[0]))[tmp_long]))," + evaluatetotyp(e$, typ) + ");"
            ELSE
                l$ = "if (!new_error) qbs_set( ((qbs*)(((uint64*)(" + n$ + "[0]))[tmp_long]))," + e$ + ");"
            END IF
            PRINT #12, l$
        END IF
        stringprocessinghappened = 1
        tlayout$ = tl$
        EXIT SUB
    END IF

    IF (typ AND ISOFFSETINBITS) THEN
        'r$ = "setbits_" + str2(typ AND 511) + "("
        r$ = "setbits(" + str2(typ AND 511) + ","
        r$ = r$ + "(uint8*)(" + n$ + "[0])" + ",tmp_long,"
        PRINT #12, "tmp_long=" + a$ + ";"
        IF method = 0 THEN
            l$ = "if (!new_error) " + r$ + evaluatetotyp(e$, typ) + ");"
        ELSE
            l$ = "if (!new_error) " + r$ + e$ + ");"
        END IF
        PRINT #12, l$
        tlayout$ = tl$
        EXIT SUB
    ELSE
        t$ = ""
        IF (typ AND ISFLOAT) THEN
            IF (typ AND 511) = 32 THEN t$ = "float"
            IF (typ AND 511) = 64 THEN t$ = "double"
            IF (typ AND 511) = 256 THEN t$ = "long double"
        ELSE
            IF (typ AND ISUNSIGNED) THEN
                IF (typ AND 511) = 8 THEN t$ = "uint8"
                IF (typ AND 511) = 16 THEN t$ = "uint16"
                IF (typ AND 511) = 32 THEN t$ = "uint32"
                IF (typ AND 511) = 64 THEN t$ = "uint64"
            ELSE
                IF (typ AND 511) = 8 THEN t$ = "int8"
                IF (typ AND 511) = 16 THEN t$ = "int16"
                IF (typ AND 511) = 32 THEN t$ = "int32"
                IF (typ AND 511) = 64 THEN t$ = "int64"
            END IF
        END IF
    END IF
    IF t$ = "" THEN nerror (101)
    PRINT #12, "tmp_long=" + a$ + ";"
    IF method = 0 THEN
        l$ = "if (!new_error) ((" + t$ + "*)(" + n$ + "[0]))[tmp_long]=" + evaluatetotyp(e$, typ) + ";"
    ELSE
        l$ = "if (!new_error) ((" + t$ + "*)(" + n$ + "[0]))[tmp_long]=" + e$ + ";"
    END IF

    PRINT #12, l$
    tlayout$ = tl$
    EXIT SUB
END IF 'array

'variable?
IF id.t THEN
    r$ = RTRIM$(id.n)
    t = id.t
    'remove irrelavant flags
    IF (t AND ISINCONVENTIONALMEMORY) THEN t = t - ISINCONVENTIONALMEMORY
    typ = t

    'string variable?
    IF (t AND ISSTRING) THEN
        IF (t AND ISFIXEDLENGTH) THEN
            r$ = scope$ + "STRING" + str2(id.tsize) + "_" + r$
        ELSE
            r$ = scope$ + "STRING_" + r$
        END IF
        IF method = 0 THEN e$ = evaluatetotyp(e$, ISSTRING)
        PRINT #12, "qbs_set(" + r$ + "," + e$ + ");"
        PRINT #12, cleanupstringprocessingcall$ + "0);"
        IF arrayprocessinghappened THEN arrayprocessinghappened = 0
        tlayout$ = tl$
        EXIT SUB
    END IF

    'bit-length variable?
    IF (t AND ISOFFSETINBITS) THEN
        b = t AND 511
        IF (t AND ISUNSIGNED) THEN
            r$ = "*" + scope$ + "UBIT" + str2(t AND 511) + "_" + r$
            IF method = 0 THEN e$ = evaluatetotyp(e$, 64& + ISUNSIGNED)
            l$ = r$ + "=(" + e$ + ")&" + str2(bitmask(b)) + ";"
            PRINT #12, l$
        ELSE
            r$ = "*" + scope$ + "BIT" + str2(t AND 511) + "_" + r$
            IF method = 0 THEN e$ = evaluatetotyp(e$, 64&)
            l$ = "if ((" + r$ + "=" + e$ + ")&" + str2(2 ^ (b - 1)) + "){"
            PRINT #12, l$
            'signed bit is set
            l$ = r$ + "|=" + str2(bitmaskinv(b)) + ";"
            PRINT #12, l$
            PRINT #12, "}else{"
            'signed bit is not set
            l$ = r$ + "&=" + str2(bitmask(b)) + ";"
            PRINT #12, l$
            PRINT #12, "}"
        END IF
        IF stringprocessinghappened THEN PRINT #12, cleanupstringprocessingcall$ + "0);": stringprocessinghappened = 0
        IF arrayprocessinghappened THEN arrayprocessinghappened = 0
        tlayout$ = tl$
        EXIT SUB
    END IF

    'standard variable?
    IF t = BYTETYPE THEN r$ = "*" + scope$ + "BYTE_" + r$: GOTO sref
    IF t = UBYTETYPE THEN r$ = "*" + scope$ + "UBYTE_" + r$: GOTO sref
    IF t = INTEGERTYPE THEN r$ = "*" + scope$ + "INTEGER_" + r$: GOTO sref
    IF t = UINTEGERTYPE THEN r$ = "*" + scope$ + "UINTEGER_" + r$: GOTO sref
    IF t = LONGTYPE THEN r$ = "*" + scope$ + "LONG_" + r$: GOTO sref
    IF t = ULONGTYPE THEN r$ = "*" + scope$ + "ULONG_" + r$: GOTO sref
    IF t = INTEGER64TYPE THEN r$ = "*" + scope$ + "INTEGER64_" + r$: GOTO sref
    IF t = UINTEGER64TYPE THEN r$ = "*" + scope$ + "UINTEGER64_" + r$: GOTO sref
    IF t = SINGLETYPE THEN r$ = "*" + scope$ + "SINGLE_" + r$: GOTO sref
    IF t = DOUBLETYPE THEN r$ = "*" + scope$ + "DOUBLE_" + r$: GOTO sref
    IF t = FLOATTYPE THEN r$ = "*" + scope$ + "FLOAT_" + r$: GOTO sref
    sref:
    t2 = t - ISPOINTER
    IF method = 0 THEN e$ = evaluatetotyp(e$, t2)
    l$ = r$ + "=" + e$ + ";"
    PRINT #12, l$
    IF stringprocessinghappened THEN PRINT #12, cleanupstringprocessingcall$ + "0);": stringprocessinghappened = 0
    IF arrayprocessinghappened THEN arrayprocessinghappened = 0
    tlayout$ = tl$
    EXIT SUB
END IF 'variable

tlayout$ = tl$
END SUB

FUNCTION str2$ (v AS LONG)
str2$ = LTRIM$(RTRIM$(STR$(v)))
END FUNCTION

FUNCTION str2u64$ (v~&&)
str2u64$ = LTRIM$(RTRIM$(STR$(v~&&)))
END FUNCTION

FUNCTION str2i64$ (v&&)
str2i64$ = LTRIM$(RTRIM$(STR$(v&&)))
END FUNCTION

FUNCTION typ2ctyp$ (t AS LONG, tstr AS STRING)
ctyp$ = ""
'typ can be passed as either: (the unused value is ignored)
'i. as a typ value in t
'ii. as a typ symbol (eg. "~%") in tstr
'iii. as a typ name (eg. _UNSIGNED INTEGER) in tstr
IF tstr$ = "" THEN
    IF (t AND ISARRAY) THEN EXIT FUNCTION 'cannot return array types
    IF (t AND ISSTRING) THEN typ2ctyp$ = "qbs": EXIT FUNCTION
    b = t AND 511
    IF (t AND ISUDT) THEN typ2ctyp$ = "void": EXIT FUNCTION
    IF (t AND ISOFFSETINBITS) THEN
        IF b <= 32 THEN ctyp$ = "int32" ELSE ctyp$ = "int64"
        IF (t AND ISUNSIGNED) THEN ctyp$ = "u" + ctyp$
        typ2ctyp$ = ctyp$: EXIT FUNCTION
    END IF
    IF (t AND ISFLOAT) THEN
        IF b = 32 THEN ctyp$ = "float"
        IF b = 64 THEN ctyp$ = "double"
        IF b = 256 THEN ctyp$ = "long double"
    ELSE
        IF b = 8 THEN ctyp$ = "int8"
        IF b = 16 THEN ctyp$ = "int16"
        IF b = 32 THEN ctyp$ = "int32"
        IF b = 64 THEN ctyp$ = "int64"
        IF (t AND ISUNSIGNED) THEN ctyp$ = "u" + ctyp$
    END IF
    typ2ctyp$ = ctyp$: EXIT FUNCTION
END IF

ts$ = tstr$
'is ts$ a symbol?
IF ts$ = "$" THEN ctyp$ = "qbs"
IF ts$ = "!" THEN ctyp$ = "float"
IF ts$ = "#" THEN ctyp$ = "double"
IF ts$ = "##" THEN ctyp$ = "long double"
IF LEFT$(ts$, 1) = "~" THEN unsgn = 1: ts$ = RIGHT$(ts$, 1)
IF LEFT$(ts$, 1) = "`" THEN
    n$ = RIGHT$(ts$, LEN(ts$) - 1)
    b = 1
    IF n$ <> "" THEN
        IF isuinteger(n$) = 0 THEN qb64error "Invalid index after _BIT type"
        b = VAL(n$)
        IF b > 57 THEN qb64error "Invalid index after _BIT type"
    END IF
    IF b <= 32 THEN ctyp$ = "int32" ELSE ctyp$ = "int64"
    IF unsgn THEN ctyp$ = "u" + ctyp$
    typ2ctyp$ = ctyp$: EXIT FUNCTION
END IF
IF ts$ = "%%" THEN ctyp$ = "int8"
IF ts$ = "%" THEN ctyp$ = "int16"
IF ts$ = "&" THEN ctyp$ = "int32"
IF ts$ = "&&" THEN ctyp$ = "int64"
IF ctyp$ <> "" THEN
    IF unsgn THEN ctyp$ = "u" + ctyp$
    typ2ctyp$ = ctyp$: EXIT FUNCTION
END IF

'is tstr$ a named type? (eg. 'LONG')
s$=type2symbol$(tstr$)
if len(s$) then
typ2ctyp$ = typ2ctyp$(0,s$)
EXIT FUNCTION
end if

qb64error "Invalid type"

END FUNCTION

FUNCTION type2symbol$ (typ$)
t$ = typ$
FOR i = 1 TO LEN(t$)
    IF MID$(t$, i, 1) = sp THEN MID$(t$, i, 1) = " "
NEXT
e$ = "Cannot convert type (" + typ$ + ") to symbol"
t2$ = "_UNSIGNED _BIT": s$ = "~`1": IF LEFT$(t$, LEN(t2$)) = t2$ THEN GOTO t2sfound
t2$ = "_UNSIGNED _BYTE": s$ = "~%%": IF LEFT$(t$, LEN(t2$)) = t2$ THEN GOTO t2sfound
t2$ = "_UNSIGNED INTEGER": s$ = "~%": IF LEFT$(t$, LEN(t2$)) = t2$ THEN GOTO t2sfound
t2$ = "_UNSIGNED LONG": s$ = "~&": IF LEFT$(t$, LEN(t2$)) = t2$ THEN GOTO t2sfound
t2$ = "_UNSIGNED _INTEGER64": s$ = "~&&": IF LEFT$(t$, LEN(t2$)) = t2$ THEN GOTO t2sfound
t2$ = "_BIT": s$ = "`1": IF LEFT$(t$, LEN(t2$)) = t2$ THEN GOTO t2sfound
t2$ = "_BYTE": s$ = "%%": IF LEFT$(t$, LEN(t2$)) = t2$ THEN GOTO t2sfound
t2$ = "INTEGER": s$ = "%": IF LEFT$(t$, LEN(t2$)) = t2$ THEN GOTO t2sfound
t2$ = "LONG": s$ = "&": IF LEFT$(t$, LEN(t2$)) = t2$ THEN GOTO t2sfound
t2$ = "_INTEGER64": s$ = "&&": IF LEFT$(t$, LEN(t2$)) = t2$ THEN GOTO t2sfound
t2$ = "SINGLE": s$ = "!": IF LEFT$(t$, LEN(t2$)) = t2$ THEN GOTO t2sfound
t2$ = "DOUBLE": s$ = "#": IF LEFT$(t$, LEN(t2$)) = t2$ THEN GOTO t2sfound
t2$ = "_FLOAT": s$ = "##": IF LEFT$(t$, LEN(t2$)) = t2$ THEN GOTO t2sfound
t2$ = "STRING": s$ = "$": IF LEFT$(t$, LEN(t2$)) = t2$ THEN GOTO t2sfound
qb64error e$
t2sfound:
type2symbol$ = s$
IF LEN(t2$) <> LEN(t$) THEN
    IF s$ <> "*" AND s$ <> "~`1" AND s$ <> "`1" THEN qb64error e$
    t$ = RIGHT$(t$, LEN(t$) - LEN(t2$))
    IF LEFT$(t$, 3) <> " * " THEN qb64error e$
    t$ = RIGHT$(t$, LEN(t$) - 3)
    IF isuinteger(t$) = 0 THEN qb64error e$
    v = VAL(t$)
    IF v = 0 THEN qb64error e$
    IF s$ <> "$" AND v > 56 THEN qb64error e$
    IF s$ = "$" THEN
        s$ = s$ + str2$(v)
    ELSE
        s$ = LEFT$(s$, LEN(s$) - 1) + str2$(v)
    END IF
    type2symbol$ = s$
END IF
END FUNCTION

'Strips away bits/indentifiers which make locating a variables source difficult
FUNCTION typecomp (typ)
typ2 = typ
IF (typ2 AND ISINCONVENTIONALMEMORY) THEN typ2 = typ2 - ISINCONVENTIONALMEMORY
typecomp = typ2
END FUNCTION

FUNCTION typname2typ& (t2$)
typname2typsize = 0 'the default

t$ = t2$

'symbol?
ts$ = t$
IF ts$ = "$" THEN typname2typ& = STRINGTYPE: EXIT FUNCTION
IF ts$ = "!" THEN typname2typ& = SINGLETYPE: EXIT FUNCTION
IF ts$ = "#" THEN typname2typ& = DOUBLETYPE: EXIT FUNCTION
IF ts$ = "##" THEN typname2typ& = FLOATTYPE: EXIT FUNCTION

'fixed length string?
IF LEFT$(ts$, 1) = "$" THEN
    n$ = RIGHT$(ts$, LEN(ts$) - 1)
    IF isuinteger(n$) = 0 THEN qb64error "Invalid index after STRING * type"
    b = VAL(n$)
    IF b = 0 THEN qb64error "Invalid index after STRING * type"
    typname2typsize = b
    typname2typ& = STRINGTYPE + ISFIXEDLENGTH
    EXIT FUNCTION
END IF

'unsigned?
IF LEFT$(ts$, 1) = "~" THEN unsgn = 1: ts$ = RIGHT$(ts$, LEN(ts$) - 1)

'bit-type?
IF LEFT$(ts$, 1) = "`" THEN
    n$ = RIGHT$(ts$, LEN(ts$) - 1)
    b = 1
    IF n$ <> "" THEN
        IF isuinteger(n$) = 0 THEN qb64error "Invalid index after _BIT type"
        b = VAL(n$)
        IF b > 56 THEN qb64error "Invalid index after _BIT type"
    END IF
    IF unsgn THEN typname2typ& = UBITTYPE + (b - 1) ELSE typname2typ& = BITTYPE + (b - 1)
    EXIT FUNCTION
END IF

t = 0
IF ts$ = "%%" THEN t = BYTETYPE
IF ts$ = "%" THEN t = INTEGERTYPE
IF ts$ = "&" THEN t = LONGTYPE
IF ts$ = "&&" THEN t = INTEGER64TYPE
IF t THEN
    IF unsgn THEN t = t + ISUNSIGNED
    typname2typ& = t: EXIT FUNCTION
END IF
'not a valid symbol

'type name?
FOR i = 1 TO LEN(t$)
    IF MID$(t$, i, 1) = sp THEN MID$(t$, i, 1) = " "
NEXT
IF t$ = "STRING" THEN typname2typ& = STRINGTYPE: EXIT FUNCTION

IF LEFT$(t$, 9) = "STRING * " THEN
    n$ = RIGHT$(t$, LEN(t$) - 9)
    IF isuinteger(n$) = 0 THEN qb64error "Invalid index after STRING * type"
    b = VAL(n$)
    IF b = 0 THEN qb64error "Invalid index after STRING * type"
    typname2typsize = b
    typname2typ& = STRINGTYPE + ISFIXEDLENGTH
    EXIT FUNCTION
END IF

IF t$ = "SINGLE" THEN typname2typ& = SINGLETYPE: EXIT FUNCTION
IF t$ = "DOUBLE" THEN typname2typ& = DOUBLETYPE: EXIT FUNCTION
IF t$ = "_FLOAT" THEN typname2typ& = FLOATTYPE: EXIT FUNCTION
IF LEFT$(t$, 10) = "_UNSIGNED " THEN u = 1: t$ = RIGHT$(t$, LEN(t$) - 10)
IF LEFT$(t$, 4) = "_BIT" THEN
    IF t$ = "_BIT" THEN
        IF u THEN typname2typ& = UBITTYPE ELSE typname2typ& = BITTYPE
        EXIT FUNCTION
    END IF
    IF LEFT$(t$, 7) <> "_BIT * " THEN qb64error "Expected _BIT * number"
    n$ = RIGHT$(t$, LEN(t$) - 7)
    IF isuinteger(n$) = 0 THEN qb64error "Invalid size after _BIT *"
    b = VAL(n$)
    IF b = 0 OR b > 56 THEN qb64error "Invalid size after _BIT *"
    t = BITTYPE - 1 + b: IF u THEN t = t + ISUNSIGNED
    typname2typ& = t
    EXIT FUNCTION
END IF

t = 0
IF t$ = "_BYTE" THEN t = BYTETYPE
IF t$ = "INTEGER" THEN t = INTEGERTYPE
IF t$ = "LONG" THEN t = LONGTYPE
IF t$ = "_INTEGER64" THEN t = INTEGER64TYPE
IF t THEN
    IF u THEN t = t + ISUNSIGNED
    typname2typ& = t
    EXIT FUNCTION
END IF
IF u THEN EXIT FUNCTION '_UNSIGNED (nothing)

'UDT?
FOR i = 1 TO lasttype
    IF t$ = RTRIM$(udtxname(i)) THEN
        typname2typ& = ISUDT + ISPOINTER + i
        EXIT FUNCTION
    END IF
NEXT

'return 0 (failed)
END FUNCTION

FUNCTION uniquenumber&
uniquenumbern = uniquenumbern + 1
uniquenumber& = uniquenumbern
END FUNCTION

FUNCTION validlabel (LABEL2$)
validlabel = 0
IF LEN(LABEL2$) = 0 THEN EXIT FUNCTION
clabel$ = LABEL2$
label$ = UCASE$(LABEL2$)

n = numelements(label$)

IF n = 1 THEN

    'any internal SUB which can be called with no parameters cannot be a label
    IF label$ = "BEEP" THEN EXIT FUNCTION
    IF label$ = "COLOR" THEN EXIT FUNCTION
    IF label$ = "CLS" THEN EXIT FUNCTION
    IF label$ = "CLEAR" THEN EXIT FUNCTION
    IF label$ = "CLOSE" THEN EXIT FUNCTION
    IF label$ = "DATA" THEN EXIT FUNCTION
    IF label$ = "DO" THEN EXIT FUNCTION
    IF label$ = "ELSE" THEN EXIT FUNCTION
    IF label$ = "ELSEIF" THEN EXIT FUNCTION
    IF label$ = "END" THEN EXIT FUNCTION
    IF label$ = "FILES" THEN EXIT FUNCTION
    IF label$ = "LOCATE" THEN EXIT FUNCTION
    IF label$ = "LOCAL" THEN EXIT FUNCTION
    IF label$ = "LOOP" THEN EXIT FUNCTION
    IF label$ = "NEXT" THEN EXIT FUNCTION
    IF label$ = "PRINT" THEN EXIT FUNCTION
    IF label$ = "PALETTE" THEN EXIT FUNCTION
    IF label$ = "RANDOMIZE" THEN EXIT FUNCTION
    IF label$ = "RESTORE" THEN EXIT FUNCTION
    IF label$ = "RESUME" THEN EXIT FUNCTION
    IF label$ = "RETURN" THEN EXIT FUNCTION
    IF label$ = "RUN" THEN EXIT FUNCTION
    IF label$ = "SCREEN" THEN EXIT FUNCTION
    IF label$ = "SHELL" THEN EXIT FUNCTION
    IF label$ = "SIGNAL" THEN EXIT FUNCTION
    IF label$ = "SLEEP" THEN EXIT FUNCTION
    IF label$ = "SYSTEM" THEN EXIT FUNCTION
    IF label$ = "TRON" THEN EXIT FUNCTION
    IF label$ = "TROFF" THEN EXIT FUNCTION
    IF label$ = "RESET" THEN EXIT FUNCTION
    IF label$ = "WEND" THEN EXIT FUNCTION
    IF label$ = "WIDTH" THEN EXIT FUNCTION
    IF label$ = "WINDOW" THEN EXIT FUNCTION

    'Numeric label?
    'quasi numbers are possible, but:
    'a) They may only have one decimal place
    'b) They must be typed with the exact same characters to match
    t$ = label$
    'numeric?
    a = ASC(t$)
    IF (a >= 48 AND a <= 57) OR a = 46 THEN
        IF a = 46 THEN dp = 1
        'remove possible E/D/F+0 added by autoformatting
        FOR x = 2 TO LEN(t$)
            a = ASC(MID$(t$, x, 1))
            IF a = 46 THEN dp = dp + 1
            IF a = 68 OR a = 69 OR a = 70 THEN 'D/E/F
                IF MID$(t$, x + 1, 2) = "+0" THEN EXIT FOR
                EXIT FUNCTION
            END IF
            IF a = 44 THEN EXIT FOR 'skip auto-layout info
            IF (a < 48 OR a > 57) AND a <> 46 THEN EXIT FUNCTION 'not numeric
        NEXT x
        IF dp > 1 THEN EXIT FUNCTION 'too many decimal places
        t$ = LEFT$(t$, x - 1)
        tlayout$ = t$
        'change dp to "p"
        i = INSTR(t$, "."): IF i THEN MID$(t$, i, 1) = "p"
        LABEL2$ = t$
        validlabel = 1
        EXIT FUNCTION
    END IF 'numeric

END IF 'n=1

'Alpha-numeric label?
'Build label

'structure check (???.???.???.???)
IF (n AND 1) = 0 THEN EXIT FUNCTION 'must be an odd number of elements
FOR nx = 2 TO n - 1 STEP 2
    a$ = getelement$(LABEL2$, nx)
    IF a$ <> "." THEN EXIT FUNCTION 'every 2nd element must be a period
NEXT

'cannot begin with numeric
c = ASC(clabel$): IF c >= 48 AND c <= 57 THEN EXIT FUNCTION

'elements check
label3$ = ""
FOR nx = 1 TO n STEP 2
    label$ = getelement$(clabel$, nx)

    'alpha-numeric?
    FOR x = 1 TO LEN(label$)
        IF alphanumeric(ASC(label$, x)) = 0 THEN EXIT FUNCTION
    NEXT

    'build label
    IF label3$ = "" THEN label3$ = UCASE$(label$): tlayout$ = label$ ELSE label3$ = label3$ + fix046$ + UCASE$(label$): tlayout$ = tlayout$ + "." + label$
NEXT nx

validlabel = 1
LABEL2$ = label3$

END FUNCTION

SUB xend

'1. locate bottomline,1
'PRINT #12, "display_page->cursor_y=print_holding_cursor=0; qbg_cursor_x=1; qbg_cursor_y=qbg_height_in_characters;"

'2. print a message in the screen's width
'PRINT #12, "if (qbg_width_in_characters==80){"
'PRINT #12, "qbs_print(qbs_new_txt(" + CHR$(34) + "Press any key to continue" + SPACE$(80 - 25) + CHR$(34) + "),0);"
'PRINT #12, "}else{"
'PRINT #12, "qbs_print(qbs_new_txt(" + CHR$(34) + "Press any key to continue" + SPACE$(40 - 25) + CHR$(34) + "),0);"
'PRINT #12, "}"

'3. wait for a key to be pressed
'PRINT #12, "do{"
'PRINT #12, "SDL_Delay(0);"
'PRINT #12, "if (stop_program) end();"
'PRINT #12, "}while(qbs_cleanup(qbs_tmp_base,qbs_equal(qbs_inkey(),
'            qbs_new_txt(" + CHR$(34) + CHR$(34) + "))));"
'4. quit
'PRINT #12, "close_program=1;"
'PRINT #12, "end();"
PRINT #12, "sub_end();"
END SUB

SUB xfileprint (a$, ca$, n)
u$ = str2$(uniquenumber)
PRINT #12, "tab_spc_cr_size=2;"
IF n = 2 THEN nerror (52)
a3$ = ""
b = 0
FOR i = 3 TO n
    a2$ = getelement$(ca$, i)
    IF a2$ = "(" THEN b = b + 1
    IF a2$ = ")" THEN b = b - 1
    IF a2$ = "," AND b = 0 THEN
        IF a3$ = "" THEN nerror (53)
        GOTO printgotfn
    END IF
    IF a3$ = "" THEN a3$ = a2$ ELSE a3$ = a3$ + sp + a2$
NEXT
nerror (54)
printgotfn:
e$ = fixoperationorder$(a3$)
l$ = "PRINT" + sp + "#" + sp2 + tlayout$ + sp2 + ","
e$ = evaluatetotyp(e$, 64&)
PRINT #12, "tab_fileno=tmp_fileno=" + e$ + ";"
PRINT #12, "if (new_error) goto skip" + u$ + ";"
i = i + 1

'PRINT USING? (file)
IF n >= i THEN
    IF getelement(a$, i) = "USING" THEN
        'get format string
        fpujump:
        l$ = l$ + sp + "USING"
        e$ = "": b = 0: puformat$ = ""
        FOR i = i + 1 TO n
            a2$ = getelement(ca$, i)
            IF a2$ = "(" THEN b = b + 1
            IF a2$ = ")" THEN b = b - 1
            IF b = 0 THEN
                IF a2$ = "," THEN qb64error "Expected PRINT USING #filenumber, formatstring ; ..."
                IF a2$ = ";" THEN
                    e$ = fixoperationorder$(e$)
                    l$ = l$ + sp + tlayout$ + sp2 + ";"
                    e$ = evaluate(e$, typ)
                    IF (typ AND ISREFERENCE) THEN e$ = refer(e$, typ, 0)
                    IF (typ AND ISSTRING) = 0 THEN qb64error "Expected PRINT USING #filenumber, formatstring ; ..."
                    puformat$ = e$
                    EXIT FOR
                END IF ';
            END IF 'b
            IF LEN(e$) THEN e$ = e$ + sp + a2$ ELSE e$ = a2$
        NEXT
        IF puformat$ = "" THEN qb64error "Expected PRINT USING #filenumber, formatstring ; ..."
        IF i = n THEN qb64error "Expected PRINT USING #filenumber, formatstring ; ..."
        'create build string
        PRINT #12, "tqbs=qbs_new(0,0);"
        'set format start/index variable
        PRINT #12, "tmp_long=0;" 'scan format from beginning
        'create string to hold format in for multiple references
        puf$ = "print_using_format" + u$
        IF subfunc = "" THEN
            PRINT #13, "static qbs *" + puf$ + ";"
        ELSE
            PRINT #13, "qbs *" + puf$ + ";"
        END IF
        PRINT #12, puf$ + "=qbs_new(0,0); qbs_set(" + puf$ + "," + puformat$ + ");"
        PRINT #12, "if (new_error) goto skip" + u$ + ";"
        'print expressions
        b = 0
        e$ = ""
        last = 0
        FOR i = i + 1 TO n
            a2$ = getelement(ca$, i)
            IF a2$ = "(" THEN b = b + 1
            IF a2$ = ")" THEN b = b - 1
            IF b = 0 THEN
                IF a2$ = ";" OR a2$ = "," THEN
                    fprintulast:
                    e$ = fixoperationorder$(e$)
                    IF last THEN l$ = l$ + sp + tlayout$ ELSE l$ = l$ + sp + tlayout$ + sp2 + a2$
                    e$ = evaluate(e$, typ)
                    IF (typ AND ISREFERENCE) THEN e$ = refer(e$, typ, 0)
                    IF typ AND ISSTRING THEN
                        PRINT #12, "tmp_long=print_using(" + puf$ + ",tmp_long,tqbs," + e$ + ");"
                    ELSE 'not a string
                        IF typ AND ISFLOAT THEN
                            IF (typ AND 511) = 32 THEN PRINT #12, "tmp_long=print_using_single(" + puf$ + "," + e$ + ",tmp_long,tqbs);"
                            IF (typ AND 511) = 64 THEN PRINT #12, "tmp_long=print_using_double(" + puf$ + "," + e$ + ",tmp_long,tqbs);"
                            IF (typ AND 511) > 64 THEN PRINT #12, "tmp_long=print_using_float(" + puf$ + "," + e$ + ",tmp_long,tqbs);"
                        ELSE
                            IF ((typ AND 511) = 64) AND (typ AND ISUNSIGNED) <> 0 THEN
                                PRINT #12, "tmp_long=print_using_uinteger64(" + puf$ + "," + e$ + ",tmp_long,tqbs);"
                            ELSE
                                PRINT #12, "tmp_long=print_using_integer64(" + puf$ + "," + e$ + ",tmp_long,tqbs);"
                            END IF
                        END IF
                    END IF 'string/not string
                    PRINT #12, "if (new_error) goto skip_pu" + u$ + ";"
                    e$ = ""
                    IF last THEN EXIT FOR
                    GOTO fprintunext
                END IF
            END IF
            IF LEN(e$) THEN e$ = e$ + sp + a2$ ELSE e$ = a2$
            fprintunext:
        NEXT
        IF e$ <> "" THEN a2$ = "": last = 1: GOTO fprintulast
        PRINT #12, "skip_pu" + u$ + ":"
        'check for errors
        PRINT #12, "if (new_error){"
        PRINT #12, "g_tmp_long=new_error; new_error=0; sub_file_print(tmp_fileno,tqbs,0,0,0); new_error=g_tmp_long;"
        PRINT #12, "}else{"
        IF a2$ = "," OR a2$ = ";" THEN nl = 0 ELSE nl = 1 'note: a2$ is set to the last element of a$
        PRINT #12, "sub_file_print(tmp_fileno,tqbs,0,0," + str2$(nl) + ");"
        PRINT #12, "}"
        PRINT #12, "qbs_free(tqbs);"
        PRINT #12, "qbs_free(" + puf$ + ");"
        PRINT #12, "skip" + u$ + ":"
        PRINT #12, cleanupstringprocessingcall$ + "0);"
        PRINT #12, "tab_spc_cr_size=1;"
        tlayout$ = l$
        EXIT SUB
    END IF
END IF
'end of print using code

IF i > n THEN
    PRINT #12, "sub_file_print(tmp_fileno,nothingstring,0,0,1);"
    GOTO printblankline
END IF
b = 0
e$ = ""
last = 0
FOR i = i TO n
    a2$ = getelement(ca$, i)
    IF a2$ = "(" THEN b = b + 1
    IF a2$ = ")" THEN b = b - 1
    IF b = 0 THEN
        IF a2$ = ";" OR a2$ = "," OR UCASE$(a2$) = "USING" THEN
            printfilelast:

            IF UCASE$(a2$) = "USING" THEN
                IF e$ <> "" THEN gotofpu = 1 ELSE GOTO fpujump
            END IF

            IF a2$ = "," THEN usetab = 1 ELSE usetab = 0
            IF last = 1 THEN newline = 1 ELSE newline = 0
            extraspace = 0

            IF LEN(e$) THEN
                ebak$ = e$
                pnrtnum = 0
                printfilenumber:
                e$ = fixoperationorder$(e$)
                IF pnrtnum = 0 THEN
                    IF last THEN l$ = l$ + sp + tlayout$ ELSE l$ = l$ + sp + tlayout$ + sp2 + a2$
                END IF
                e$ = evaluate(e$, typ)
                IF (typ AND ISSTRING) = 0 THEN
                    e$ = "STR$" + sp + "(" + sp + ebak$ + sp + ")"
                    extraspace = 1
                    pnrtnum = 1
                    GOTO printfilenumber 'force re-evaluation
                END IF
                IF (typ AND ISREFERENCE) THEN e$ = refer(e$, typ, 0)
                'format: string, (1/0) extraspace, (1/0) tab, (1/0)begin a new line
                PRINT #12, "sub_file_print(tmp_fileno," + e$ + ","; extraspace; ","; usetab; ","; newline; ");"
            ELSE 'len(e$)=0
                IF usetab THEN PRINT #12, "sub_file_print(tmp_fileno,nothingstring,0,1,0);"
            END IF 'len(e$)
            PRINT #12, "if (new_error) goto skip" + u$ + ";"

            e$ = ""
            IF gotofpu THEN GOTO fpujump
            IF last THEN EXIT FOR
            GOTO printfilenext
        END IF ', or ;
    END IF 'b=0
    IF e$ <> "" THEN e$ = e$ + sp + a2$ ELSE e$ = a2$
    printfilenext:
NEXT
IF e$ <> "" THEN a2$ = "": last = 1: GOTO printfilelast
printblankline:
PRINT #12, "skip" + u$ + ":"
PRINT #12, cleanupstringprocessingcall$ + "0);"
PRINT #12, "tab_spc_cr_size=1;"
tlayout$ = l$
END SUB

SUB xfilewrite (ca$, n)
l$ = "WRITE" + sp + "#"
u$ = str2$(uniquenumber)
PRINT #12, "tab_spc_cr_size=2;"
IF n = 2 THEN qb64error "Expected # ..."
a3$ = ""
b = 0
FOR i = 3 TO n
    a2$ = getelement$(ca$, i)
    IF a2$ = "(" THEN b = b + 1
    IF a2$ = ")" THEN b = b - 1
    IF a2$ = "," AND b = 0 THEN
        IF a3$ = "" THEN nerror (53)
        GOTO writegotfn
    END IF
    IF a3$ = "" THEN a3$ = a2$ ELSE a3$ = a3$ + sp + a2$
NEXT
nerror (54)
writegotfn:
e$ = fixoperationorder$(a3$)
l$ = l$ + sp2 + tlayout$ + sp2 + ","
e$ = evaluatetotyp(e$, 64&)
PRINT #12, "tab_fileno=tmp_fileno=" + e$ + ";"
PRINT #12, "if (new_error) goto skip" + u$ + ";"
i = i + 1
IF i > n THEN
    PRINT #12, "sub_file_print(tmp_fileno,nothingstring,0,0,1);"
    GOTO writeblankline
END IF
b = 0
e$ = ""
last = 0
FOR i = i TO n
    a2$ = getelement(ca$, i)
    IF a2$ = "(" THEN b = b + 1
    IF a2$ = ")" THEN b = b - 1
    IF b = 0 THEN
        IF a2$ = "," THEN
            writefilelast:
            IF last = 1 THEN newline = 1 ELSE newline = 0
            ebak$ = e$
            reevaled = 0
            writefilenumber:
            e$ = fixoperationorder$(e$)
            IF reevaled = 0 THEN
                l$ = l$ + sp + tlayout$
                IF last = 0 THEN l$ = l$ + sp2 + ","
            END IF
            e$ = evaluate(e$, typ)
            IF reevaled = 0 THEN
                IF (typ AND ISSTRING) = 0 THEN
                    e$ = "LTRIM$" + sp + "(" + sp + "STR$" + sp + "(" + sp + ebak$ + sp + ")" + sp + ")"
                    IF last = 0 THEN e$ = e$ + sp + "+" + sp + CHR$(34) + "," + CHR$(34) + ",1"
                    reevaled = 1
                    GOTO writefilenumber 'force re-evaluation
                ELSE
                    e$ = CHR$(34) + "\042" + CHR$(34) + ",1" + sp + "+" + sp + ebak$ + sp + "+" + sp + CHR$(34) + "\042" + CHR$(34) + ",1"
                    IF last = 0 THEN e$ = e$ + sp + "+" + sp + CHR$(34) + "," + CHR$(34) + ",1"
                    reevaled = 1
                    GOTO writefilenumber 'force re-evaluation
                END IF
            END IF
            IF (typ AND ISREFERENCE) THEN e$ = refer(e$, typ, 0)
            'format: string, (1/0) extraspace, (1/0) tab, (1/0)begin a new line
            PRINT #12, "sub_file_print(tmp_fileno," + e$ + ",0,0,"; newline; ");"
            PRINT #12, "if (new_error) goto skip" + u$ + ";"
            e$ = ""
            IF last THEN EXIT FOR
            GOTO writefilenext
        END IF ',
    END IF 'b=0
    IF e$ <> "" THEN e$ = e$ + sp + a2$ ELSE e$ = a2$
    writefilenext:
NEXT
IF e$ <> "" THEN a2$ = ",": last = 1: GOTO writefilelast
writeblankline:
'print #12, "}"'new_error
PRINT #12, "skip" + u$ + ":"
PRINT #12, cleanupstringprocessingcall$ + "0);"
PRINT #12, "tab_spc_cr_size=1;"
layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
END SUB

SUB xgosub (ca$, n&)
a2$ = getelement(ca$, 2)
IF validlabel(a2$) = 0 THEN nerror (65)

v=HashFind(a2$,HASHFLAG_LABEL,ignore,r)
x=1
labchk200: 
if v then
s=labels(r).scope
if s=subfuncn or s=-1 then 'same scope?
if s=-1 then labels(r).scope=subfuncn 'acquire scope
x=0 'already defined
tlayout$=rtrim$(labels(r).cn)
else
if v=2 then v=HashFindCont(ignore,r): goto labchk200
end if
end if
if x then
'does not exist
nLabels=nLabels+1: if nLabels>Labels_Ubound then Labels_Ubound=Labels_Ubound*2: redim _preserve Labels(1 to Labels_Ubound) as Label_Type
Labels(nLabels)=Empty_label
hashadd a2$,HASHFLAG_LABEL,nLabels
r=nLabels
Labels(r).state=0
Labels(r).cn=tlayout$
Labels(r).scope=subfuncn
Labels(r).Error_Line=linenumber
end if 'x

l$ = "GOSUB" + sp + tlayout$
layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
'note: This code fragment also used by ON ... GOTO/GOSUB
'assume label is reachable (revise)
PRINT #12, "return_point[next_return_point++]=" + str2(gosubid) + ";"
PRINT #12, "if (next_return_point>=return_points) more_return_points();"
PRINT #12, "goto LABEL_" + a2$ + ";"
'add return point jump
PRINT #15, "case " + str2(gosubid) + ":"
PRINT #15, "goto RETURN_" + str2(gosubid) + ";"
PRINT #15, "break;"
PRINT #12, "RETURN_" + str2(gosubid) + ":;"
gosubid = gosubid + 1
END SUB

SUB xongotogosub (a$, ca$, n)
IF n < 4 THEN qb64error "Expected ON expression GOTO/GOSUB label,label,..."
l$ = "ON"
b = 0
FOR i = 2 TO n
    e2$ = getelement$(a$, i)
    IF e2$ = "(" THEN b = b + 1
    IF e2$ = ")" THEN b = b - 1
    IF e2$ = "GOTO" OR e2$ = "GOSUB" THEN EXIT FOR
NEXT
IF i >= n OR i = 2 THEN qb64error "Expected ON expression GOTO/GOSUB label,label,..."
e$ = getelements$(ca$, 2, i - 1)

g = 0: IF e2$ = "GOSUB" THEN g = 1
e$ = fixoperationorder(e$)
l$ = l$ + sp + tlayout$
e$ = evaluate(e$, typ)
IF (typ AND ISREFERENCE) THEN e$ = refer(e$, typ, 0)
IF (typ AND ISSTRING) THEN qb64error "Expected numeric expression"
IF (typ AND ISFLOAT) THEN
    e$ = "qbr_float_to_long(" + e$ + ")"
END IF
l$ = l$ + sp + e2$
u$ = str2$(uniquenumber)
PRINT #13, "static int32 ongo_" + u$ + "=0;"
PRINT #12, "ongo_" + u$ + "=" + e$ + ";"
ln = 1
labelwaslast = 0
FOR i = i + 1 TO n
    e$ = getelement$(ca$, i)
    IF e$ = "," THEN
        l$ = l$ + sp2 + ","
        IF i = n THEN qb64error "Trailing , invalid"
        ln = ln + 1
        labelwaslast = 0
    ELSE
        IF labelwaslast THEN qb64error "Expected ,"
        IF validlabel(e$) = 0 THEN nerror (36)

v=HashFind(e$,HASHFLAG_LABEL,ignore,r)
x=1
labchk507: 
if v then
s=labels(r).scope
if s=subfuncn or s=-1 then 'same scope?
if s=-1 then labels(r).scope=subfuncn 'acquire scope
x=0 'already defined
tlayout$=rtrim$(labels(r).cn)
else
if v=2 then v=HashFindCont(ignore,r): goto labchk507
end if
end if
if x then
'does not exist
nLabels=nLabels+1: if nLabels>Labels_Ubound then Labels_Ubound=Labels_Ubound*2: redim _preserve Labels(1 to Labels_Ubound) as Label_Type
Labels(nLabels)=Empty_label
hashadd e$,HASHFLAG_LABEL,nLabels
r=nLabels
Labels(r).state=0
Labels(r).cn=tlayout$
Labels(r).scope=subfuncn
Labels(r).Error_Line=linenumber
end if 'x

        l$ = l$ + sp + tlayout$
        IF g THEN 'gosub
            lb$ = e$
            PRINT #12, "if (ongo_" + u$ + "==" + str2$(ln) + "){"
            'note: This code fragment also used by ON ... GOTO/GOSUB
            'assume label is reachable (revise)
            PRINT #12, "return_point[next_return_point++]=" + str2(gosubid) + ";"
            PRINT #12, "if (next_return_point>=return_points) more_return_points();"
            PRINT #12, "goto LABEL_" + lb$ + ";"
            'add return point jump
            PRINT #15, "case " + str2(gosubid) + ":"
            PRINT #15, "goto RETURN_" + str2(gosubid) + ";"
            PRINT #15, "break;"
            PRINT #12, "RETURN_" + str2(gosubid) + ":;"
            gosubid = gosubid + 1
            PRINT #12, "goto ongo_" + u$ + "_skip;"
            PRINT #12, "}"
        ELSE 'goto
            PRINT #12, "if (ongo_" + u$ + "==" + str2$(ln) + ") goto LABEL_" + e$ + ";"
        END IF
        labelwaslast = 1
    END IF
NEXT
PRINT #12, "if (ongo_" + u$ + "<0) error(5);"
IF g = 1 THEN PRINT #12, "ongo_" + u$ + "_skip:;"
layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
END SUB

SUB xprint (a$, ca$, n)
u$ = str2$(uniquenumber)

l$ = "PRINT"
if asc(a$)=76 then lp=1: lp$="l": l$ = "LPRINT" '"L"

'PRINT USING?
IF n >= 2 THEN
    IF getelement(a$, 2) = "USING" THEN
        'get format string
        i = 3
        pujump:
        l$ = l$ + sp + "USING"
        e$ = "": b = 0: puformat$ = ""
        FOR i = i TO n
            a2$ = getelement(ca$, i)
            IF a2$ = "(" THEN b = b + 1
            IF a2$ = ")" THEN b = b - 1
            IF b = 0 THEN
                IF a2$ = "," THEN qb64error "Expected PRINT USING formatstring ; ..."
                IF a2$ = ";" THEN
                    e$ = fixoperationorder$(e$)
                    l$ = l$ + sp + tlayout$ + sp2 + ";"
                    e$ = evaluate(e$, typ)
                    IF (typ AND ISREFERENCE) THEN e$ = refer(e$, typ, 0)
                    IF (typ AND ISSTRING) = 0 THEN qb64error "Expected PRINT USING formatstring ; ..."
                    puformat$ = e$
                    EXIT FOR
                END IF ';
            END IF 'b
            IF LEN(e$) THEN e$ = e$ + sp + a2$ ELSE e$ = a2$
        NEXT
        IF puformat$ = "" THEN qb64error "Expected PRINT USING formatstring ; ..."
        IF i = n THEN qb64error "Expected PRINT USING formatstring ; ..."
        'create build string
        PRINT #12, "tqbs=qbs_new(0,0);"
        'set format start/index variable
        PRINT #12, "tmp_long=0;" 'scan format from beginning
        'create string to hold format in for multiple references
        puf$ = "print_using_format" + u$
        IF subfunc = "" THEN
            PRINT #13, "static qbs *" + puf$ + ";"
        ELSE
            PRINT #13, "qbs *" + puf$ + ";"
        END IF
        PRINT #12, puf$ + "=qbs_new(0,0); qbs_set(" + puf$ + "," + puformat$ + ");"
        PRINT #12, "if (new_error) goto skip_pu" + u$ + ";"
        'print expressions
        b = 0
        e$ = ""
        last = 0
        FOR i = i + 1 TO n
            a2$ = getelement(ca$, i)
            IF a2$ = "(" THEN b = b + 1
            IF a2$ = ")" THEN b = b - 1
            IF b = 0 THEN
                IF a2$ = ";" OR a2$ = "," THEN
                    printulast:
                    e$ = fixoperationorder$(e$)
                    IF last THEN l$ = l$ + sp + tlayout$ ELSE l$ = l$ + sp + tlayout$ + sp2 + a2$
                    e$ = evaluate(e$, typ)
                    IF (typ AND ISREFERENCE) THEN e$ = refer(e$, typ, 0)
                    IF typ AND ISSTRING THEN
                        PRINT #12, "tmp_long=print_using(" + puf$ + ",tmp_long,tqbs," + e$ + ");"
                    ELSE 'not a string
                        IF typ AND ISFLOAT THEN
                            IF (typ AND 511) = 32 THEN PRINT #12, "tmp_long=print_using_single(" + puf$ + "," + e$ + ",tmp_long,tqbs);"
                            IF (typ AND 511) = 64 THEN PRINT #12, "tmp_long=print_using_double(" + puf$ + "," + e$ + ",tmp_long,tqbs);"
                            IF (typ AND 511) > 64 THEN PRINT #12, "tmp_long=print_using_float(" + puf$ + "," + e$ + ",tmp_long,tqbs);"
                        ELSE
                            IF ((typ AND 511) = 64) AND (typ AND ISUNSIGNED) <> 0 THEN
                                PRINT #12, "tmp_long=print_using_uinteger64(" + puf$ + "," + e$ + ",tmp_long,tqbs);"
                            ELSE
                                PRINT #12, "tmp_long=print_using_integer64(" + puf$ + "," + e$ + ",tmp_long,tqbs);"
                            END IF
                        END IF
                    END IF 'string/not string
                    PRINT #12, "if (new_error) goto skip_pu" + u$ + ";"
                    e$ = ""
                    IF last THEN EXIT FOR
                    GOTO printunext
                END IF
            END IF
            IF LEN(e$) THEN e$ = e$ + sp + a2$ ELSE e$ = a2$
            printunext:
        NEXT
        IF e$ <> "" THEN a2$ = "": last = 1: GOTO printulast
        PRINT #12, "skip_pu" + u$ + ":"
        'check for errors
        PRINT #12, "if (new_error){"
        PRINT #12, "g_tmp_long=new_error; new_error=0; qbs_"+lp$+"print(tqbs,0); new_error=g_tmp_long;"
        PRINT #12, "}else{"
        IF a2$ = "," OR a2$ = ";" THEN nl = 0 ELSE nl = 1 'note: a2$ is set to the last element of a$
        PRINT #12, "qbs_"+lp$+"print(tqbs," + str2$(nl) + ");"
        PRINT #12, "}"
        PRINT #12, "qbs_free(tqbs);"
        PRINT #12, "qbs_free(" + puf$ + ");"
        PRINT #12, "skip" + u$ + ":"
        PRINT #12, cleanupstringprocessingcall$ + "0);"
        tlayout$ = l$
        EXIT SUB
    END IF
END IF
'end of print using code

b = 0
e$ = ""
last = 0
FOR i = 2 TO n
    a2$ = getelement(ca$, i)
    IF a2$ = "(" THEN b = b + 1
    IF a2$ = ")" THEN b = b - 1
    IF b = 0 THEN
        IF a2$ = ";" OR a2$ = "," OR UCASE$(a2$) = "USING" THEN
            printlast:

            IF UCASE$(a2$) = "USING" THEN
                IF e$ <> "" THEN gotopu = 1 ELSE i = i + 1: GOTO pujump
            END IF

            IF LEN(e$) THEN
                ebak$ = e$
                pnrtnum = 0
                printnumber:
                e$ = fixoperationorder$(e$)
                IF pnrtnum = 0 THEN
                    IF last THEN l$ = l$ + sp + tlayout$ ELSE l$ = l$ + sp + tlayout$ + sp2 + a2$
                END IF
                e$ = evaluate(e$, typ)
                IF (typ AND ISSTRING) = 0 THEN
                    'not a string expresion!
                    e$ = "STR$" + sp + "(" + sp + ebak$ + sp + ")" + sp + "+" + sp + CHR$(34) + " " + CHR$(34)
                    pnrtnum = 1
                    GOTO printnumber
                END IF
                IF (typ AND ISREFERENCE) THEN e$ = refer(e$, typ, 0)
                PRINT #12, "tqbs=qbs_new(0,0);"
                PRINT #12, "qbs_set(tqbs," + e$ + ");"
                PRINT #12, "if (new_error) goto skip" + u$ + ";"
                if lp then PRINT #12, "lprint_makefit(tqbs);" else PRINT #12, "makefit(tqbs);"
                PRINT #12, "qbs_"+lp$+"print(tqbs,0);"
                PRINT #12, "qbs_free(tqbs);"
            END IF 'len(e$)
            IF a2$ = "," THEN PRINT #12, "tab();"
            e$ = ""

            IF gotopu THEN i = i + 1: GOTO pujump

            IF last THEN
                PRINT #12, "qbs_"+lp$+"print(nothingstring,1);" 'go to new line
                EXIT FOR
            END IF

            GOTO printnext
        END IF 'a2$
    END IF 'b=0

    IF LEN(e$) THEN e$ = e$ + sp + a2$ ELSE e$ = a2$
    printnext:
NEXT
IF LEN(e$) THEN a2$ = "": last = 1: GOTO printlast
IF n = 1 THEN PRINT #12, "qbs_"+lp$+"print(nothingstring,1);"
PRINT #12, "skip" + u$ + ":"
PRINT #12, cleanupstringprocessingcall$ + "0);"
tlayout$ = l$
END SUB




SUB xread (ca$, n)
l$ = "READ"
IF n = 1 THEN nerror (39)
i = 2
IF i > n THEN nerror (40)
a3$ = ""
b = 0
FOR i = i TO n
    a2$ = getelement$(ca$, i)
    IF a2$ = "(" THEN b = b + 1
    IF a2$ = ")" THEN b = b - 1
    IF (a2$ = "," AND b = 0) OR i = n THEN
        IF i = n THEN
            IF a3$ = "" THEN a3$ = a2$ ELSE a3$ = a3$ + sp + a2$
        END IF
        IF a3$ = "" THEN nerror (41)
        e$ = fixoperationorder$(a3$)
        l$ = l$ + sp + tlayout$: IF i <> n THEN l$ = l$ + sp2 + ","
        e$ = evaluate(e$, t)
        IF (t AND ISREFERENCE) = 0 THEN nerror (42)

        IF (t AND ISSTRING) THEN
            e$ = refer(e$, t, 0)
            PRINT #12, "sub_read_string(data,&data_offset,data_size," + e$ + ");"
            stringprocessinghappened = 1
        ELSE
            'not a string!
            'e$ = refer(e$, t, 1)
            '***INPORTANT NOTE: Modify t for non-0 bit offsets found in UDTs & arrays too
            t2 = t
            IF (t2 AND ISPOINTER) THEN t2 = t2 - ISPOINTER
            IF (t2 AND ISINCONVENTIONALMEMORY) THEN t2 = t2 - ISINCONVENTIONALMEMORY
            IF (t2 AND ISREFERENCE) THEN t2 = t2 - ISREFERENCE
            'PRINT #12, "sub_file_input_value(tmp_long," + str2(t) + "," + e$ + ");"
            IF (t AND 511) = 64 THEN
                IF (t AND ISUNSIGNED) THEN
                    setrefer e$, t, "func_read_uint64(data,&data_offset,data_size)", 1
                ELSE
                    setrefer e$, t, "func_read_int64(data,&data_offset,data_size)", 1
                END IF
            ELSE
                setrefer e$, t, "func_read_float(data,&data_offset,data_size," + str2(t) + ")", 1
            END IF

        END IF
        IF i = n THEN EXIT FOR
        a3$ = "": a2$ = ""
    END IF
    IF a3$ = "" THEN a3$ = a2$ ELSE a3$ = a3$ + sp + a2$
NEXT
IF stringprocessinghappened THEN PRINT #12, cleanupstringprocessingcall$ + "0);"
layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
END SUB

SUB xwrite (ca$, n)
l$ = "WRITE"
u$ = str2$(uniquenumber)
IF n = 1 THEN
    PRINT #12, "qbs_print(nothingstring,1);"
    GOTO writeblankline2
END IF
b = 0
e$ = ""
last = 0
FOR i = 2 TO n
    a2$ = getelement(ca$, i)
    IF a2$ = "(" THEN b = b + 1
    IF a2$ = ")" THEN b = b - 1
    IF b = 0 THEN
        IF a2$ = "," THEN
            writelast:
            IF last = 1 THEN newline = 1 ELSE newline = 0
            ebak$ = e$
            reevaled = 0
            writechecked:
            e$ = fixoperationorder$(e$)
            IF reevaled = 0 THEN
                l$ = l$ + sp + tlayout$
                IF last = 0 THEN l$ = l$ + sp2 + ","
            END IF
            e$ = evaluate(e$, typ)
            IF reevaled = 0 THEN
                IF (typ AND ISSTRING) = 0 THEN
                    e$ = "LTRIM$" + sp + "(" + sp + "STR$" + sp + "(" + sp + ebak$ + sp + ")" + sp + ")"
                    IF last = 0 THEN e$ = e$ + sp + "+" + sp + CHR$(34) + "," + CHR$(34) + ",1"
                    reevaled = 1
                    GOTO writechecked 'force re-evaluation
                ELSE
                    e$ = CHR$(34) + "\042" + CHR$(34) + ",1" + sp + "+" + sp + ebak$ + sp + "+" + sp + CHR$(34) + "\042" + CHR$(34) + ",1"
                    IF last = 0 THEN e$ = e$ + sp + "+" + sp + CHR$(34) + "," + CHR$(34) + ",1"
                    reevaled = 1
                    GOTO writechecked 'force re-evaluation
                END IF
            END IF
            IF (typ AND ISREFERENCE) THEN e$ = refer(e$, typ, 0)
            'format: string, (1/0) extraspace, (1/0) tab, (1/0)begin a new line
            PRINT #12, "qbs_print(" + e$ + ","; newline; ");"
            PRINT #12, "if (new_error) goto skip" + u$ + ";"
            e$ = ""
            IF last THEN EXIT FOR
            GOTO writenext
        END IF ',
    END IF 'b=0
    IF e$ <> "" THEN e$ = e$ + sp + a2$ ELSE e$ = a2$
    writenext:
NEXT
IF e$ <> "" THEN a2$ = ",": last = 1: GOTO writelast
writeblankline2:
PRINT #12, "skip" + u$ + ":"
PRINT #12, cleanupstringprocessingcall$ + "0);"
layoutdone = 1: IF LEN(layout$) THEN layout$ = layout$ + sp + l$ ELSE layout$ = l$
END SUB

FUNCTION evaluateconst$ (a2$, t AS LONG)
a$ = a2$
IF debug THEN PRINT #9, "evaluateconst:in:" + a$


DIM block(1000) AS STRING
DIM status(1000) AS INTEGER
'0=unprocessed (can be "")
'1=processed
DIM btype(1000) AS LONG 'for status=1 blocks

'put a$ into blocks
n = numelements(a$)
FOR i = 1 TO n
    block(i) = getelement$(a$, i)
NEXT

evalconstevalbrack:

'find highest bracket level
l = 0
b = 0
FOR i = 1 TO n
    IF block(i) = "(" THEN b = b + 1
    IF block(i) = ")" THEN b = b - 1
    IF b > l THEN l = b
NEXT

'if brackets exist, evaluate that item first
IF l THEN

    b = 0
    e$ = ""
    FOR i = 1 TO n

        IF block(i) = ")" THEN
            IF b = l THEN block(i) = "": EXIT FOR
            b = b - 1
        END IF

        IF b >= l THEN
            IF LEN(e$) = 0 THEN e$ = block(i) ELSE e$ = e$ + sp + block(i)
            block(i) = ""
        END IF

        IF block(i) = "(" THEN
            b = b + 1
            IF b = l THEN i2 = i: block(i) = ""
        END IF

    NEXT i

    status(i) = 1
    block(i) = evaluateconst$(e$, btype(i))
    GOTO evalconstevalbrack

END IF 'l

'linear equation remains with some pre-calculated & non-pre-calc blocks

'problem: type QBASIC assumes and type required to store calc. value may
'         differ dramatically. in qbasic, this would have caused an overflow,
'         but in qb64 it MUST work. eg. 32767% * 32767%
'solution: all interger calc. will be performed using a signed _INTEGER64
'          all float calc. will be performed using a _FLOAT

'convert non-calc block numbers into binary form with QBASIC-like type
FOR i = 1 TO n
    IF status(i) = 0 THEN
        IF LEN(block(i)) THEN

            a = ASC(block(i))
            IF (a = 45 AND LEN(block(i)) > 1) OR (a >= 48 AND a <= 57) THEN 'number?

                'integers
                e$ = RIGHT$(block(i), 3)
                IF e$ = "~&&" THEN btype(i) = UINTEGER64TYPE - ISPOINTER: GOTO gotconstblkityp
                IF e$ = "~%%" THEN btype(i) = UBYTETYPE - ISPOINTER: GOTO gotconstblkityp
                e$ = RIGHT$(block(i), 2)
                IF e$ = "&&" THEN btype(i) = INTEGER64TYPE - ISPOINTER: GOTO gotconstblkityp
                IF e$ = "%%" THEN btype(i) = BYTETYPE - ISPOINTER: GOTO gotconstblkityp
                IF e$ = "~%" THEN btype(i) = UINTEGERTYPE - ISPOINTER: GOTO gotconstblkityp
                IF e$ = "~&" THEN btype(i) = ULONGTYPE - ISPOINTER: GOTO gotconstblkityp
                e$ = RIGHT$(block(i), 1)
                IF e$ = "%" THEN btype(i) = INTEGERTYPE - ISPOINTER: GOTO gotconstblkityp
                IF e$ = "&" THEN btype(i) = LONGTYPE - ISPOINTER: GOTO gotconstblkityp

                'ubit-type?
                IF INSTR(block(i), "~`") THEN
                    x = INSTR(block(i), "~`")
                    IF x = LEN(block(i)) - 1 THEN block(i) = block(i) + "1"
                    btype(i) = UBITTYPE - ISPOINTER - 1 + VAL(RIGHT$(block(i), LEN(block(i)) - x - 1))
                    block(i) = _MK$(_INTEGER64, VAL(LEFT$(block(i), x - 1)))
                    status(i) = 1
                    GOTO gotconstblktyp
                END IF

                'bit-type?
                IF INSTR(block(i), "`") THEN
                    x = INSTR(block(i), "`")
                    IF x = LEN(block(i)) THEN block(i) = block(i) + "1"
                    btype(i) = BITTYPE - ISPOINTER - 1 + VAL(RIGHT$(block(i), LEN(block(i)) - x))
                    block(i) = _MK$(_INTEGER64, VAL(LEFT$(block(i), x - 1)))
                    status(i) = 1
                    GOTO gotconstblktyp
                END IF

                'floats
                IF INSTR(block(i), "E") THEN
                    block(i) = _MK$(_FLOAT, VAL(block(i)))
                    btype(i) = SINGLETYPE - ISPOINTER
                    status(i) = 1
                    GOTO gotconstblktyp
                END IF
                IF INSTR(block(i), "D") THEN
                    block(i) = _MK$(_FLOAT, VAL(block(i)))
                    btype(i) = DOUBLETYPE - ISPOINTER
                    status(i) = 1
                    GOTO gotconstblktyp
                END IF
                IF INSTR(block(i), "F") THEN
                    block(i) = _MK$(_FLOAT, VAL(block(i)))
                    btype(i) = FLOATTYPE - ISPOINTER
                    status(i) = 1
                    GOTO gotconstblktyp
                END IF

                qb64error "Invalid CONST expression.1"

                gotconstblkityp:
                block(i) = LEFT$(block(i), LEN(block(i)) - LEN(e$))
                block(i) = _MK$(_INTEGER64, VAL(block(i)))
                status(i) = 1
                gotconstblktyp:

            END IF 'a

            IF a = 34 THEN 'string?
                'no changes need to be made to block(i) which is of format "CHARACTERS",size
                btype(i) = STRINGTYPE - ISPOINTER
                status(i) = 1
            END IF

        END IF 'len<>0
    END IF 'status
NEXT

'remove NULL blocks
n2 = 0
FOR i = 1 TO n
    IF block(i) <> "" THEN
        n2 = n2 + 1
        block(n2) = block(i)
        status(n2) = status(i)
        btype(n2) = btype(i)
    END IF
NEXT
n = n2

'only one block?
IF n = 1 THEN
    IF status(1) = 0 THEN qb64error "Invalid CONST expression.2"
    t = btype(1)
    evaluateconst$ = block(1)
    EXIT FUNCTION
END IF 'n=1

'evaluate equation (equation cannot contain any STRINGs)

'[negation/not][variable]
e$ = block(1)
IF status(1) = 0 THEN
    IF n <> 2 THEN qb64error "Invalid CONST expression.4"
    IF status(2) = 0 THEN qb64error "Invalid CONST expression.5"
    IF btype(2) AND ISSTRING THEN qb64error "Invalid CONST expression.6"
    o$ = block(1)

    IF o$ = "ñ" THEN
        IF btype(2) AND ISFLOAT THEN
            r## = -_CV(_FLOAT, block(2))
            evaluateconst$ = _MK$(_FLOAT, r##)
        ELSE
            r&& = -_CV(_INTEGER64, block(2))
            evaluateconst$ = _MK$(_INTEGER64, r&&)
        END IF
        t = btype(2)
        EXIT FUNCTION
    END IF

    IF o$ = "NOT" THEN
        IF btype(2) AND ISFLOAT THEN
            r&& = _CV(_FLOAT, block(2))
        ELSE
            r&& = _CV(_INTEGER64, block(2))
        END IF
        r&& = NOT r&&
        t = btype(2)
        IF t AND ISFLOAT THEN t = LONGTYPE - ISPOINTER 'markdown to LONG
        evaluateconst$ = _MK$(_INTEGER64, r&&)
        EXIT FUNCTION
    END IF

    qb64error "Invalid CONST expression.7"
END IF

'[variable][bool-operator][variable]...

'get first variable
et = btype(1)
ev$ = block(1)

i = 2

evalconstequ:

'get operator
IF i >= n THEN qb64error "Invalid CONST expression.8"
o$ = block(i)
i = i + 1
IF isoperator(o$) = 0 THEN qb64error "Invalid CONST expression.9"
IF i > n THEN qb64error "Invalid CONST expression.10"

'string/numeric mismatch?
IF (btype(i) AND ISSTRING) <> (et AND ISSTRING) THEN qb64error "Invalid CONST expression.11"

IF et AND ISSTRING THEN
    IF o$ <> "+" THEN qb64error "Invalid CONST expression.12"
    'concat strings
    s1$ = RIGHT$(ev$, LEN(ev$) - 1)
    s1$ = LEFT$(s1$, INSTR(s1$, CHR$(34)) - 1)
    s1size = VAL(RIGHT$(ev$, LEN(ev$) - LEN(s1$) - 3))
    s2$ = RIGHT$(block(i), LEN(block(i)) - 1)
    s2$ = LEFT$(s2$, INSTR(s2$, CHR$(34)) - 1)
    s2size = VAL(RIGHT$(block(i), LEN(block(i)) - LEN(s2$) - 3))
    ev$ = CHR$(34) + s1$ + s2$ + CHR$(34) + "," + str2$(s1size + s2size)
    GOTO econstmarkedup
END IF

'prepare left and right values
IF et AND ISFLOAT THEN
    linteger = 0
    l## = _CV(_FLOAT, ev$)
    l&& = l##
ELSE
    linteger = 1
    l&& = _CV(_INTEGER64, ev$)
    l## = l&&
END IF
IF btype(i) AND ISFLOAT THEN
    rinteger = 0
    r## = _CV(_FLOAT, block(i))
    r&& = r##
ELSE
    rinteger = 1
    r&& = _CV(_INTEGER64, block(i))
    r## = r&&
END IF

IF linteger = 1 AND rinteger = 1 THEN
    IF o$ = "+" THEN r&& = l&& + r&&: GOTO econstmarkupi
    IF o$ = "-" THEN r&& = l&& - r&&: GOTO econstmarkupi
    IF o$ = "*" THEN r&& = l&& * r&&: GOTO econstmarkupi
    IF o$ = "^" THEN r## = l&& ^ r&&: GOTO econstmarkupf
    IF o$ = "/" THEN r## = l&& / r&&: GOTO econstmarkupf
    IF o$ = "\" THEN r&& = l&& \ r&&: GOTO econstmarkupi
    IF o$ = "MOD" THEN r&& = l&& MOD r&&: GOTO econstmarkupi
    IF o$ = "=" THEN r&& = l&& = r&&: GOTO econstmarkupi16
    IF o$ = ">" THEN r&& = l&& > r&&: GOTO econstmarkupi16
    IF o$ = "<" THEN r&& = l&& < r&&: GOTO econstmarkupi16
    IF o$ = ">=" THEN r&& = l&& >= r&&: GOTO econstmarkupi16
    IF o$ = "<=" THEN r&& = l&& <= r&&: GOTO econstmarkupi16
    IF o$ = "<>" THEN r&& = l&& <> r&&: GOTO econstmarkupi16
    IF o$ = "IMP" THEN r&& = l&& IMP r&&: GOTO econstmarkupi
    IF o$ = "EQV" THEN r&& = l&& EQV r&&: GOTO econstmarkupi
    IF o$ = "XOR" THEN r&& = l&& XOR r&&: GOTO econstmarkupi
    IF o$ = "OR" THEN r&& = l&& OR r&&: GOTO econstmarkupi
    IF o$ = "AND" THEN r&& = l&& AND r&&: GOTO econstmarkupi
END IF

IF o$ = "+" THEN r## = l## + r##: GOTO econstmarkupf
IF o$ = "-" THEN r## = l## - r##: GOTO econstmarkupf
IF o$ = "*" THEN r## = l## * r##: GOTO econstmarkupf
IF o$ = "^" THEN r## = l## ^ r##: GOTO econstmarkupf
IF o$ = "/" THEN r## = l## / r##: GOTO econstmarkupf
IF o$ = "\" THEN r&& = l## \ r##: GOTO econstmarkupi32
IF o$ = "MOD" THEN r&& = l## MOD r##: GOTO econstmarkupi32
IF o$ = "=" THEN r&& = l## = r##: GOTO econstmarkupi16
IF o$ = ">" THEN r&& = l## > r##: GOTO econstmarkupi16
IF o$ = "<" THEN r&& = l## < r##: GOTO econstmarkupi16
IF o$ = ">=" THEN r&& = l## >= r##: GOTO econstmarkupi16
IF o$ = "<=" THEN r&& = l## <= r##: GOTO econstmarkupi16
IF o$ = "<>" THEN r&& = l## <> r##: GOTO econstmarkupi16
IF o$ = "IMP" THEN r&& = l## IMP r##: GOTO econstmarkupi32
IF o$ = "EQV" THEN r&& = l## EQV r##: GOTO econstmarkupi32
IF o$ = "XOR" THEN r&& = l## XOR r##: GOTO econstmarkupi32
IF o$ = "OR" THEN r&& = l## OR r##: GOTO econstmarkupi32
IF o$ = "AND" THEN r&& = l## AND r##: GOTO econstmarkupi32

qb64error "Invalid CONST expression.13"

econstmarkupi16:
et = INTEGERTYPE - ISPOINTER
ev$ = _MK$(_INTEGER64, r&&)
GOTO econstmarkedup

econstmarkupi32:
et = LONGTYPE - ISPOINTER
ev$ = _MK$(_INTEGER64, r&&)
GOTO econstmarkedup

econstmarkupi:
IF et <> btype(i) THEN
    'keep unsigned?
    u = 0: IF (et AND ISUNSIGNED) <> 0 AND (btype(i) AND ISUNSIGNED) <> 0 THEN u = 1
    lb = et AND 511: rb = btype(i) AND 511
    ob = 0
    IF lb = rb THEN
        IF (et AND ISOFFSETINBITS) <> 0 AND (btype(i) AND ISOFFSETINBITS) <> 0 THEN ob = 1
        b = lb
    END IF
    IF lb > rb THEN
        IF (et AND ISOFFSETINBITS) <> 0 THEN ob = 1
        b = lb
    END IF
    IF lb < rb THEN
        IF (btype(i) AND ISOFFSETINBITS) <> 0 THEN ob = 1
        b = rb
    END IF
    et = b
    IF ob THEN et = et + ISOFFSETINBITS
    IF u THEN et = et + ISUNSIGNED
END IF
ev$ = _MK$(_INTEGER64, r&&)
GOTO econstmarkedup

econstmarkupf:
lfb = 0: rfb = 0
lib = 0: rib = 0
IF et AND ISFLOAT THEN lfb = et AND 511 ELSE lib = et AND 511
IF btype(i) AND ISFLOAT THEN rfb = btype(i) AND 511 ELSE rib = btype(i) AND 511
f = 32
IF lib > 16 OR rib > 16 THEN f = 64
IF lfb > 32 OR rfb > 32 THEN f = 64
IF lib > 32 OR rib > 32 THEN f = 256
IF lfb > 64 OR rfb > 64 THEN f = 256
et = ISFLOAT + f
ev$ = _MK$(_FLOAT, r##)

econstmarkedup:

i = i + 1

IF i <= n THEN GOTO evalconstequ

t = et
evaluateconst$ = ev$

END FUNCTION

FUNCTION typevalue2symbol$ (t)

IF t AND ISSTRING THEN
    IF t AND ISFIXEDLENGTH THEN qb64error "Cannot convert expression type to symbol"
    typevalue2symbol$ = "$"
    EXIT FUNCTION
END IF

s$ = ""

IF t AND ISUNSIGNED THEN s$ = "~"

b = t AND 511

IF t AND ISOFFSETINBITS THEN
    IF b > 1 THEN s$ = s$ + "`" + str2$(b) ELSE s$ = s$ + "`"
    typevalue2symbol$ = s$
    EXIT FUNCTION
END IF

IF t AND ISFLOAT THEN
    IF b = 32 THEN s$ = "!"
    IF b = 64 THEN s$ = "#"
    IF b = 256 THEN s$ = "##"
    typevalue2symbol$ = s$
    EXIT FUNCTION
END IF

IF b = 8 THEN s$ = s$ + "%%"
IF b = 16 THEN s$ = s$ + "%"
IF b = 32 THEN s$ = s$ + "&"
IF b = 64 THEN s$ = s$ + "&&"
typevalue2symbol$ = s$

END FUNCTION

FUNCTION symbol2fulltypename$ (s2$)
'note: accepts both symbols and type names
s$ = s2$

IF LEFT$(s$, 1) = "~" THEN
    u = 1
    IF LEN(typ$) = 1 THEN qb64error "Expected ~..."
    s$ = RIGHT$(s$, LEN(s$) - 1)
    u$ = "_UNSIGNED "
END IF

IF s$ = "%%" THEN t$ = u$ + "_BYTE": GOTO gotsym2typ
IF s$ = "%" THEN t$ = u$ + "INTEGER": GOTO gotsym2typ
IF s$ = "&" THEN t$ = u$ + "LONG": GOTO gotsym2typ
IF s$ = "&&" THEN t$ = u$ + "_INTEGER64": GOTO gotsym2typ

IF LEFT$(s$, 1) = "`" THEN
    IF LEN(s$) = 1 THEN
        t$ = u$ + "_BIT * 1"
        GOTO gotsym2typ
    END IF
    n$ = RIGHT$(s$, LEN(s$) - 1)
    IF isuinteger(n$) = 0 THEN qb64error "Expected number after symbol `"
    t$ = u$ + "_BIT * " + n$
    GOTO gotsym2typ
END IF

IF u = 1 THEN qb64error "Expected type symbol after ~"

IF s$ = "!" THEN t$ = "SINGLE": GOTO gotsym2typ
IF s$ = "#" THEN t$ = "DOUBLE": GOTO gotsym2typ
IF s$ = "##" THEN t$ = "_FLOAT": GOTO gotsym2typ
IF s$ = "$" THEN t$ = "STRING": GOTO gotsym2typ

IF LEFT$(s$, 1) = "$" THEN
    n$ = RIGHT$(s$, LEN(s$) - 1)
    IF isuinteger(n$) = 0 THEN qb64error "Expected number after symbol $"
    t$ = "STRING * " + n$
    GOTO gotsym2typ
END IF

t$ = s$

gotsym2typ:

IF RIGHT$(" " + t$, 5) = " _BIT" THEN t$ = t$ + " * 1" 'clarify (_UNSIGNED) _BIT as (_UNSIGNED) _BIT * 1

symbol2fulltypename$ = t$

END FUNCTION

SUB lineinput3load (f$)
OPEN f$ FOR BINARY AS #1
l = LOF(1)
lineinput3buffer$ = SPACE$(l)
GET #1, , lineinput3buffer$
IF LEN(lineinput3buffer$) THEN IF RIGHT$(lineinput3buffer$, 1) = CHR$(26) THEN lineinput3buffer$ = LEFT$(lineinput3buffer$, LEN(lineinput3buffer$) - 1)
CLOSE #1
lineinput3index = 1
END SUB

FUNCTION lineinput3$
'returns CHR$(13) if no more lines are available
l = LEN(lineinput3buffer$)
IF lineinput3index > l THEN lineinput3$ = CHR$(13): EXIT FUNCTION
c13 = INSTR(lineinput3index, lineinput3buffer$, CHR$(13))
c10 = INSTR(lineinput3index, lineinput3buffer$, CHR$(10))
IF c10 = 0 AND c13 = 0 THEN
    lineinput3$ = MID$(lineinput3buffer$, lineinput3index, l - lineinput3index + 1)
    lineinput3index = l + 1
    EXIT FUNCTION
END IF
IF c10 = 0 THEN c10 = 2147483647
IF c13 = 0 THEN c13 = 2147483647
IF c10 < c13 THEN
    '10 before 13
    lineinput3$ = MID$(lineinput3buffer$, lineinput3index, c10 - lineinput3index)
    lineinput3index = c10 + 1
    IF lineinput3index <= l THEN
        IF ASC(MID$(lineinput3buffer$, lineinput3index, 1)) = 13 THEN lineinput3index = lineinput3index + 1: END
    END IF
ELSE
    '13 before 10
    lineinput3$ = MID$(lineinput3buffer$, lineinput3index, c13 - lineinput3index)
    lineinput3index = c13 + 1
    IF lineinput3index <= l THEN
        IF ASC(MID$(lineinput3buffer$, lineinput3index, 1)) = 10 THEN lineinput3index = lineinput3index + 1
    END IF
END IF
END FUNCTION

FUNCTION getfilepath$ (f$)
FOR i = LEN(f$) TO 1 STEP -1
    a$ = MID$(f$, i, 1)
    IF a$ = pathsep$ THEN
        getfilepath$ = LEFT$(f$, i)
        EXIT FUNCTION
    END IF
NEXT
getfilepath$ = ""
END FUNCTION

FUNCTION eleucase$ (a$)
'this function upper-cases all elements except for quoted strings
'check first element
IF LEN(a$) = 0 THEN EXIT FUNCTION
i = 1
IF ASC(a$) = 34 THEN
    i2 = INSTR(a$, sp)
    IF i2 = 0 THEN eleucase$ = a$: EXIT FUNCTION
    a2$ = LEFT$(a$, i2 - 1)
    i = i2
END IF
'check other elements
sp34$ = sp + CHR$(34)
IF i < LEN(a$) THEN
    DO WHILE INSTR(i, a$, sp34$)
        i2 = INSTR(i, a$, sp34$)
        a2$ = a2$ + UCASE$(MID$(a$, i, i2 - i + 1)) 'everything prior including spacer
        i3 = INSTR(i2 + 1, a$, sp): IF i3 = 0 THEN i3 = LEN(a$) ELSE i3 = i3 - 1
        a2$ = a2$ + MID$(a$, i2 + 1, i3 - (i2 + 1) + 1) 'everything from " to before next spacer or end
        i = i3 + 1
        IF i > LEN(a$) THEN EXIT DO
    LOOP
END IF
a2$ = a2$ + UCASE$(MID$(a$, i, LEN(a$) - i + 1))
eleucase$ = a2$
END FUNCTION



'NEW IDE SPECIFIC
'------------------------------ IDE MODULE ------------------------------

DEFSNG A-Z
SUB getxymouse
STATIC oldmousex, oldmousey, oldmousebutton1
mousewheel = 0

DO WHILE _MOUSEINPUT

    mousex = _MOUSEX
    mousey = _MOUSEY
    IF _MOUSEBUTTON(1) THEN mousebutton1 = 1 ELSE mousebutton1 = 0
    mousewheel = mousewheel + _MOUSEWHEEL

    IF mousex <> oldmousex OR mousey <> oldmousey THEN
        IF mousebutton1 THEN change = 1
    END IF
    IF oldmousebutton1 <> mousebutton1 THEN change = 1
    IF mousewheel THEN change = 1

    oldmousex = mousex
    oldmousey = mousey
    oldmousebutton1 = mousebutton1

    IF change = 1 THEN EXIT SUB

LOOP
END SUB

DEFLNG A-Z
FUNCTION ide (ignore)
c$ = idecommand$

'report any IDE errors which have occurred
IF ideerror THEN
    mustdisplay = 1
    IF ideerror = 1 THEN ideerrormessage "IDE module error"
    IF ideerror = 2 THEN ideerrormessage "File not found"
    IF ideerror = 3 THEN ideerrormessage "File access error": CLOSE #150
    IF ideerror = 4 THEN ideerrormessage "Path not found"
END IF
ideerror = 1 'unknown IDE error

IF LEFT$(c$, 1) = CHR$(12) THEN
    f$ = RIGHT$(c$, LEN(c$) - 1)
    LOCATE , , 0
    COLOR 7, 1: LOCATE idewy - 3, 2: PRINT SPACE$(idewx - 2);: LOCATE idewy - 2, 2: PRINT SPACE$(idewx - 2);: LOCATE idewy - 1, 2: PRINT SPACE$(idewx - 2); 'clear status window
    LOCATE idewy - 3, 2

if os$="LNX" then
PRINT "Creating executable file named " + CHR$(34) + f$ + extension$ + CHR$(34) + "..."
else
PRINT "Creating .EXE file named " + CHR$(34) + f$ + extension$ + CHR$(34) + "..."
end if

    PCOPY 3, 0
    ide = 9: idereturn$ = f$
    EXIT FUNCTION
END IF

IF c$ = CHR$(100) THEN 'special call for next line (usually for the purpose of line continuation)
    idecompiledline = idecompiledline + 1 'must increment (to trigger no more lines avail. message later)
    IF idecompiledline < iden THEN
        idecompiledline$ = idegetline(idecompiledline)
        idereturn$ = idecompiledline$
    ELSE
        idecompiledline$ = ""
        idereturn$ = idecompiledline$ 'no more lines
    END IF
    EXIT FUNCTION
END IF

IF idelaunched = 0 THEN
    idelaunched = 1

'load keymap (if available)
open "keymap.txt" for binary as #150
if lof(150) then
close #150
open "keymap.txt" for input as #150
n=0
do until eof(150)
line input #150,a$
if len(a$) then
n=n+1
redim _preserve idekeymap_scancodes(1 to n) as string
redim _preserve idekeymap_output(1 to n) as _unsigned _byte
redim _preserve idekeymap_ready(1 to n) as _unsigned _byte
a2$=""
for x=1 to len(a$)
a3$=mid$(a$,x,1)
if a3$="," or a3$="=" then
idekeymap_scancodes(n)=idekeymap_scancodes(n)+chr$(val(a2$) and 255)
if a3$="=" then
idekeymap_output(n)=val(right$(a$,len(a$)-x))
exit for
end if
a2$=""
else
a2$=a2$+a3$
end if
next
end if
loop
close #150
idekeymap_n=n
else
close #150
kill "keymap.txt"
end if


    'ref: options.bin
    'SEEK 1
    '[2]   ideautolayout(=1)
    '[2]   ideautoindent(=1)
    '[2]   ideautoindentsize(=4)
    'SEEK 7
    '[2]   idewx(=80)
    '[2]   idewy(=25)
    '[2]   idecustomfont(=0)
    '[1024]idecustomfontfile(=c:\windows\fonts\lucon.ttf)
    '[2]   idecustomfontheight(=21)
    'SEEK 1039
    '[2]   ideupdatecheck(=1)
    '[2]   ideupdatedaily(=1)
    '[2]   ideupdateauto(=1)
    '[4]   ideupdatelast(=0)
    'SEEK 1049
    '[2]   codepage(=0)
    'total bytes: 1050

    OPEN ".\internal\temp\options.bin" FOR BINARY AS #150

    IF LOF(150) < 1048 THEN
        'remake options with defaults
        CLOSE #150
        OPEN ".\internal\temp\options.bin" FOR OUTPUT AS #150: CLOSE #150
        OPEN ".\internal\temp\options.bin" FOR BINARY AS #150
        v% = 1: PUT #150, , v%
        v% = 1: PUT #150, , v%
        v% = 4: PUT #150, , v%
        v% = 80: PUT #150, , v%
        v% = 25: PUT #150, , v%
        v% = 0: PUT #150, , v%
        v$ = SPACE$(1024): MID$(v$, 1) = "c:\windows\fonts\lucon.ttf": PUT #150, , v$
        v% = 21: PUT #150, , v%
        v% = 1: PUT #150, , v%
        v% = 1: PUT #150, , v%
        v% = 1: PUT #150, , v%
        PUT #150, , ideupdatelast& 'may have been set on init
        CLOSE #150
        OPEN ".\internal\temp\options.bin" FOR BINARY AS #150
    END IF
    IF LOF(150) < 1050 THEN
     SEEK #150,1049
     v&=0: PUT #150,,v%
    END IF

    'load options
    'layout:
    GET #150, , v%: IF v% <> 0 THEN v% = 1
    ideautolayout = v%
    GET #150, , v%: IF v% <> 0 THEN v% = 1
    ideautoindent = v%
    GET #150, , v%: IF v% < 0 OR v% > 64 THEN v% = 4
    ideautoindentsize = v%
    'display:
    GET #150, , v%: IF v% < 80 OR v% > 1000 THEN v% = 80
    idewx = v%
    GET #150, , v%: IF v% < 25 OR v% > 1000 THEN v% = 25
    idewy = v%
    GET #150, , v%: IF v% <> 0 THEN v% = 1
    idecustomfont = v%
    v$ = SPACE$(1024): GET #150, , v$: idecustomfontfile$ = RTRIM$(v$)
    GET #150, , v%: IF v% < 8 OR v% > 100 THEN v% = 21
    idecustomfontheight = v%
    GET #150, , v%: IF v% < 0 OR v% > 1 THEN v% = 1
    ideupdatecheck = v%
    GET #150, , v%: IF v% < 0 OR v% > 1 THEN v% = 1
    ideupdatedaily = v%
    GET #150, , v%: IF v% < 0 OR v% > 1 THEN v% = 1
    ideupdateauto = v%
    GET #150, , v&
    ideupdatelast = v&
    GET #150, , v%: if v%<0 or v%>idecpnum then v%=0
    idecpindex=v%
    CLOSE #150

    WIDTH idewx, idewy
    _FONT 16

'change codepage
if idecpindex then
 for x=128 to 255
 u=val("&H"+mid$(idecp(idecpindex),x*8+1,8)+"&")
 if u=0 then u=9744
 _MAPUNICODE u to x
 next
end if

    IF idecustomfont THEN
        idecustomfonthandle = _LOADFONT(idecustomfontfile$, idecustomfontheight, "MONOSPACE")
        IF idecustomfonthandle = -1 THEN
            'failed! - revert to default settings
            idecustomfont = 0: idecustomfontfile$ = "c:\windows\fonts\lucon.ttf": idecustomfontheight = 21
        ELSE
            _FONT idecustomfonthandle
        END IF
    END IF

    m = 1: i = 0
    menu$(m, i) = "File": i = i + 1
    menu$(m, i) = "#New": i = i + 1
    menu$(m, i) = "#Open...": i = i + 1
    menu$(m, i) = "#Save": i = i + 1
    menu$(m, i) = "Save #As...": i = i + 1
if os$="WIN" then
    menu$(m, i) = "-": i = i + 1
    menu$(m, i) = "#Update": i = i + 1
end if
    menu$(m, i) = "-": i = i + 1
    menu$(m, i) = "E#xit": i = i + 1
    menusize(m) = i - 1

    m = m + 1: i = 0
    menu$(m, i) = "Edit": i = i + 1
    menu$(m, i) = "Cu#t  Shift+Del or CTRL+X": i = i + 1
    menu$(m, i) = "#Copy  Ctrl+Ins or CTRL+C": i = i + 1
    menu$(m, i) = "#Paste  Shift+Ins or CTRL+V": i = i + 1
    menu$(m, i) = "Cl#ear  Del": i = i + 1
    menu$(m, i) = "Select #All  CTRL+A": i = i + 1
    menu$(m, i) = "-": i = i + 1
    menu$(m, i) = "New #SUB...": i = i + 1
    menu$(m, i) = "New #FUNCTION...": i = i + 1

    menusize(m) = i - 1

    m = m + 1: i = 0
    menu$(m, i) = "View": i = i + 1
    menu$(m, i) = "#SUBs...  F2": i = i + 1
    menusize(m) = i - 1

    m = m + 1: i = 0
    menu$(m, i) = "Search": i = i + 1
    menu$(m, i) = "#Find...": i = i + 1
    menu$(m, i) = "#Repeat Last Find  F3": i = i + 1
    menu$(m, i) = "#Change...": i = i + 1
    menusize(m) = i - 1

    m = m + 1: i = 0
    menu$(m, i) = "Run": i = i + 1
    menu$(m, i) = "#Start  F5": i = i + 1
    menu$(m, i) = "-": i = i + 1
    menu$(m, i) = "Start (#Detached)  Ctrl+F5": i = i + 1

if os$="LNX" then
    menu$(m, i) = "Make E#xecutable Only  F11": i = i + 1
else
    menu$(m, i) = "Make E#XE Only  F11": i = i + 1
end if

    menusize(m) = i - 1
    m = m + 1: i = 0
    menu$(m, i) = "Options": i = i + 1
    menu$(m, i) = "#Display...": i = i + 1
    menu$(m, i) = "#Language...": i = i + 1
    menu$(m, i) = "#Code layout...": i = i + 1
if os$="WIN" then
    menu$(m, i) = "#Update...": i = i + 1
end if
    menusize(m) = i - 1

    menus = m

    IF os$ = "WIN" THEN
        idepathsep$ = "\"
    END IF
    IF os$ = "LNX" THEN
        idepathsep$ = "/"
    END IF

    initmouse
    a$ = "QWERTYUIOP????ASDFGHJKL?????ZXCVBNM": x = 16: FOR i = 1 TO LEN(a$): idealtcode(ASC(MID$(a$, i, 1))) = x: x = x + 1: NEXT

    ideroot$ = idezgetroot$
    idepath$ = ideroot$

    'new blank text field
    idet$ = MKL$(0) + MKL$(0): idel = 1: ideli = 1: iden = 1

    ideunsaved = -1
    idechangemade = 1

    redraweverything:

    menubar$ = "   "
    FOR i = 1 TO menus
        menubar$ = menubar$ + menu$(i, 0) + "  "
    NEXT
    menubar$ = menubar$ + SPACE$(idewx - LEN(menubar$))

    SCREEN , , 3, 0
    VIEW PRINT 1 TO idewy
    LOCATE , , , 8, 8

    'static background
    COLOR 0, 7: LOCATE 1, 1: PRINT menubar$;
    COLOR 7, 1: idebox 1, 2, idewx, idewy - 5
    COLOR 7, 1: idebox 1, idewy - 4, idewx, 5
    'edit corners
    COLOR 7, 1: LOCATE idewy - 4, 1: PRINT "Ã";: LOCATE idewy - 4, idewx: PRINT "´";
    'add status title
    COLOR 7, 1: LOCATE idewy - 4, (idewx - 8) / 2: PRINT " Status "
    'status bar
    COLOR 0, 3: LOCATE idewy, 1: PRINT SPACE$(idewx);
    q = idevbar(idewx, idewy - 3, 3, 1, 1)
    q = idevbar(idewx, 3, idewy - 8, 1, 1)
    q = idehbar(2, idewy - 5, idewx - 2, 1, 1)
    idesx = 1
    idesy = 1
    idecx = 1
    idecy = 1
    DEF SEG = 0
    ideshowtext
    IF retval = 1 THEN GOTO skipload



    'restore autosave?
    OPEN tmpdir$ + "autosave.bin" FOR BINARY AS #150
    IF LOF(150) THEN
        GET #150, , n&
        IF n& THEN
            r$ = iderestore$
            PCOPY 3, 0: SCREEN , , 3, 0: idewait4mous: idewait4alt
            IF r$ = "Y" THEN
                ideunsaved = 1
                GET #150, , bytes&
                idet$ = SPACE$(bytes&)
                GET #150, , idet$
                iden = n&
            END IF
        END IF
    END IF
    CLOSE #150



    IF ideunsaved <> 1 THEN 'no file restored (takes priority over loading file from command line)
        IF LEFT$(c$, 1) = CHR$(1) THEN 'load file
            f$ = RIGHT$(c$, LEN(c$) - 1)
            IF LCASE$(RIGHT$(f$, 4)) <> ".bas" THEN f$ = f$ + ".bas" 'add .bas if necessary
            path$ = idezgetfilepath$(ideroot$, f$)

            '(copied from ideopen)
            ideerror = 2
            OPEN path$ + idepathsep$ + f$ FOR INPUT AS #150: CLOSE #150
            ideerror = 3
            idepath$ = path$
            lineinput3load path$ + idepathsep$ + f$
            idet$ = SPACE$(LEN(lineinput3buffer) * 8)
            i2 = 1
            n = 0
            chrtab$ = CHR$(9)
            space1$ = " ": space2$ = "  ": space3$ = "   ": space4$ = "    "
            chr7$ = CHR$(7): chr11$ = CHR$(11): chr12$ = CHR$(12): chr28$ = CHR$(28): chr29$ = CHR$(29): chr30$ = CHR$(30): chr31$ = CHR$(31)
            DO
                a$ = lineinput3$
                l = LEN(a$)
                IF l THEN asca = ASC(a$) ELSE asca = -1
                IF asca <> 13 THEN
                    IF asca <> -1 THEN
                        'fix tabs
                        ideopenfixtabsx:
                        x = INSTR(a$, chrtab$)
                        IF x THEN
                            x2 = (x - 1) MOD 4
                            IF x2 = 0 THEN a$ = LEFT$(a$, x - 1) + space4$ + RIGHT$(a$, l - x): l = l + 3: GOTO ideopenfixtabsx
                            IF x2 = 1 THEN a$ = LEFT$(a$, x - 1) + space3$ + RIGHT$(a$, l - x): l = l + 2: GOTO ideopenfixtabsx
                            IF x2 = 2 THEN a$ = LEFT$(a$, x - 1) + space2$ + RIGHT$(a$, l - x): l = l + 1: GOTO ideopenfixtabsx
                            IF x2 = 3 THEN a$ = LEFT$(a$, x - 1) + space1$ + RIGHT$(a$, l - x): GOTO ideopenfixtabsx
                        END IF

'cull control characters
cullctrlchrs2:
for x=1 to len(a$)
if control_chr(asc(a$,x)) then
a$=LEFT$(a$, x - 1)+right$(a$,len(a$)-x)
goto cullctrlchrs2
end if
next

                    END IF 'asca<>-1
                    MID$(idet$, i2, l + 8) = MKL$(l) + a$ + MKL$(l): i2 = i2 + l + 8: n = n + 1
                END IF
            LOOP UNTIL asca = 13
            lineinput3buffer = ""
            iden = n: IF n = 0 THEN idet$ = MKL$(0) + MKL$(0): iden = 1 ELSE idet$ = LEFT$(idet$, i2 - 1)
            ideerror = 1
            ideprogname = f$: _TITLE ideprogname + " - QB64"
        END IF 'message 1

    END IF 'no restore

    skipload:
END IF 'idelaunched

IF c$ = CHR$(3) THEN
    skipdisplay = 1 'assume .../starting already displayed
    sendnextline = 1

    'previous line was OK, so use layout if available

    IF ideautolayout = 0 AND ideautoindent = 0 THEN

        layout$ = ""
        idelayoutallow = 0

    ELSE

        IF LEN(layout$) THEN

            'calculate recommended indent level
            FOR i = 1 TO LEN(layout$)
                IF ASC(layout$, i) <> 32 OR i = LEN(layout$) THEN
                    indent = i - 1
                    layout$ = RIGHT$(layout$, LEN(layout$) - i + 1)
                    EXIT FOR
                END IF
            NEXT

            IF ideautolayout THEN
                spacelayout:
                ignoresp = 0
                FOR i = 1 TO LEN(layout$)
                    IF ASC(layout$, i) = 34 THEN
                        ignoresp = ignoresp + 1: IF ignoresp = 2 THEN ignoresp = 0
                    END IF
                    IF ignoresp = 0 THEN
                        IF MID$(layout$, i, 1) = sp THEN MID$(layout$, i, 1) = " "
                        IF MID$(layout$, i, 1) = sp2 THEN layout$ = LEFT$(layout$, i - 1) + RIGHT$(layout$, LEN(layout$) - i): GOTO spacelayout
                    END IF
                NEXT
            END IF

            IF ideautoindent = 0 THEN
                'note: can assume auto-format
                'calculate old indent (if any)
                a$ = idecompiledline$
                indent = 0
                FOR i = 1 TO LEN(a$)
                    IF ASC(a$, i) <> 32 OR i = LEN(a$) THEN
                        indent = i - 1
                        EXIT FOR
                    END IF
                NEXT
                indent$ = SPACE$(indent)
            ELSE
                indent$ = SPACE$(indent * ideautoindentsize)
            END IF

            IF ideautolayout = 0 THEN
                'note: can assume auto-indent
                a$ = idecompiledline$
                layout$ = ""
                FOR i = 1 TO LEN(a$)
                    IF ASC(a$, i) <> 32 OR i = LEN(a$) THEN
                        layout$ = RIGHT$(a$, LEN(a$) - i + 1)
                        EXIT FOR
                    END IF
                NEXT
            END IF

            layout$ = indent$ + layout$

            IF idecy <> idecompiledline OR idelayoutallow <> 0 THEN
                idelayoutallow = 0

                IF idecompiledline$ <> layout$ THEN
                    idesetline idecompiledline, layout$
                    IF idecompiledline >= idesy AND idecompiledline <= (idesy + 16) THEN skipdisplay = 0
                END IF

            ELSE

                IF idecompiledline$ <> layout$ THEN
                    idecurrentlinelayout = layout$
                    idecurrentlinelayouti = idecy
                END IF

            END IF

        END IF 'len(layout$)

    END IF 'using layout/indent

END IF '3

IF c$ = CHR$(6) THEN
    idecompiling = 0
    ready = 1
    IF ideautorun THEN ideautorun = 0: GOTO idemrunspecial
END IF

IF c$ = CHR$(11) THEN
    idecompiling = 0
    ready = 1
    ideautorun = 0
    showexecreated = 1
END IF

IF c$ = CHR$(7) THEN
    skipdisplay = 1 'assume .../starting already displayed
    idecompiledline = 0
    sendnextline = 1
END IF

IF LEFT$(c$, 1) = CHR$(8) THEN
    idecompiling = 0
    failed = 1
    ideautorun = 0
END IF

passback = 0
IF LEFT$(c$, 1) = CHR$(10) THEN 'passback
    skipdisplay = 1 'assume .../starting already displayed
    sendnextline = 1
    idecompiledline = idecompiledline - 1
    passback = 1
    passback$ = RIGHT$(c$, LEN(c$) - 1)
END IF

IF mustdisplay THEN skipdisplay = 0

IF skipdisplay = 0 THEN

    LOCATE , , 0

    'note: menu bar shouldn't need repairing!
    'COLOR 0, 7: LOCATE 1, 1: PRINT menubar$; 'repair menu bar

    IF c$ <> CHR$(3) THEN
        COLOR 7, 1: LOCATE idewy - 3, 2: PRINT SPACE$(idewx - 2);: LOCATE idewy - 2, 2: PRINT SPACE$(idewx - 2);: LOCATE idewy - 1, 2: PRINT SPACE$(idewx - 2); 'clear status window
        IF ready THEN LOCATE idewy - 3, 2: PRINT "OK"; 'report OK status
        IF showexecreated THEN
            showexecreated = 0
            LOCATE idewy - 3, 2

if os$="LNX" then
PRINT "Executable file created";
else
PRINT ".EXE file created";
end if

        END IF
    END IF

END IF 'skipdisplay

idefocusline = 0

'main loop
DO
    ideloop:

    idedeltxt 'removes temporary strings by setting an index to 0

    IF skipdisplay = 0 THEN

        LOCATE , , 0

        'update title of main window
        COLOR 7, 1: LOCATE 2, 2: PRINT STRING$(idewx - 2, "Ä");
        IF LEN(ideprogname) THEN a$ = ideprogname ELSE a$ = "Untitled" + tempfolderindexstr$
        a$ = " " + a$ + " "
        COLOR 1, 7: LOCATE 2, ((idewx / 2) - 1) - (LEN(a$) - 1) \ 2: PRINT a$;

        'alter cursor style to match insert mode
        IF ideinsert THEN LOCATE , , , 0, 31 ELSE LOCATE , , , 8, 8

        'display error message (if necessary)
        IF failed THEN
            COLOR 7, 1: LOCATE idewy - 3, 2: PRINT SPACE$(idewx - 2);: LOCATE idewy - 2, 2: PRINT SPACE$(idewx - 2);: LOCATE idewy - 1, 2: PRINT SPACE$(idewx - 2); 'clear status window

            'scrolling unavailable, but may span multiple lines
            a$ = MID$(c$, 2, LEN(c$) - 5)
            l = CVL(RIGHT$(c$, 4))
            IF l <> 0 THEN
                idefocusline = l
                IF idecy = l THEN a$ = a$ + " on current line" ELSE a$ = a$ + " on line" + STR$(l)
            END IF
            LOCATE idewy - 3, 2: IF LEN(a$) THEN PRINT LEFT$(a$, idewx - 2);
            IF LEN(a$) > (idewx - 2) THEN a$ = RIGHT$(a$, LEN(a$) - (idewx - 2)) ELSE a$ = ""
            LOCATE idewy - 2, 2: IF LEN(a$) THEN PRINT LEFT$(a$, (idewx - 2));
            IF LEN(a$) > (idewx - 2) THEN a$ = RIGHT$(a$, LEN(a$) - (idewx - 2)) ELSE a$ = ""
            LOCATE idewy - 1, 2: IF LEN(a$) THEN PRINT LEFT$(a$, (idewx - 2));

        END IF

        IF idechangemade THEN
            COLOR 7, 1: LOCATE idewy - 3, 2: PRINT SPACE$(idewx - 2);: LOCATE idewy - 2, 2: PRINT SPACE$(idewx - 2);: LOCATE idewy - 1, 2: PRINT SPACE$(idewx - 2); 'clear status window


            LOCATE idewy - 3, 2: PRINT "..."; 'assume new compilation will begin
        END IF

        ideshowtext
        LOCATE , , 1
        PCOPY 3, 0

    END IF 'skipdisplay

    IF idechangemade THEN

        IF idelayoutallow THEN idelayoutallow = idelayoutallow - 1

        idecurrentlinelayouti = 0 'invalidate

        idechangemade = 0
        IF ideunsaved = -1 THEN ideunsaved = 0 ELSE ideunsaved = 1

        'autosave
        ideautosave = ideautosave + 1
        IF ideautosave = 10 THEN
            ideautosave = 0

            OPEN tmpdir$ + "autosave.bin" FOR OUTPUT AS #150: CLOSE #150: OPEN tmpdir$ + "autosave.bin" FOR BINARY AS #150

            PUT #150, , iden
            l& = LEN(idet$)
            PUT #150, , l&
            PUT #150, , idet$
            CLOSE #150
        END IF

        'begin new compilation
        ideautorun = 0
        idecompiling = 1
        ide = 2
        idecompiledline$ = idegetline(1)
        idereturn$ = idecompiledline$
        idecompiledline = 1
        EXIT FUNCTION
    END IF 'idechangemade


    change = 0
    waitforinput:

    IF idecurrentlinelayouti THEN
        IF idecy <> idecurrentlinelayouti THEN
            idesetline idecurrentlinelayouti, idecurrentlinelayout$
            idecurrentlinelayouti = 0
            change = 1 'simulate a change to force a screen update
        END IF
    END IF

    exitvalue = _EXIT
    IF exitvalue AND 1 THEN GOTO quickexit

if UpdateHandle then
ContinueDownloads
IF DL(UpdateHandle).State=2 THEN 'download complete
update 0
UpdateHandle=0
change=1 'simulate a change to force a screen update
else
if abs(TIMER-ideupdatetimerval)>=5 then 'give up after 5 seconds
close DL(UpdateHandle).handle: DL(UpdateHandle).state=0: UpdateHandle=0
end if
end if
end if

    omb = mb
    getxymouse
    mx = mousex
    my = mousey
    mb = mousebutton1
    IF mb = 0 THEN idemouseselect = 0
    IF mb THEN change = 1
    IF mousewheel THEN change = 1

    k$ = INKEY$: IF LEN(k$) THEN change = 1


  'update keydown states (allows for key mapping)
  FOR x& = 1 TO 10
    i& = INP(&H60)
    IF (i& AND 128) THEN
     if KeyDown(i& XOR 128)<>0 then KeyDown(i& XOR 128) = 0
    end if
    IF (i& AND 128) = 0 THEN
     if KeyDown(i&)=0 then KeyDown(i&) = -1
    end if
  NEXT

'check keymaps
for n=1 to idekeymap_n
if len(idekeymap_scancodes(n))=0 then goto nokeymap
for i=1 to len(idekeymap_scancodes(n))
if keydown(asc(idekeymap_scancodes(n),i))=0 then
idekeymap_ready(n)=1
goto nokeymap
end if
next
if idekeymap_ready(n) then
idekeymap_ready(n)=0
k$=chr$(idekeymap_output(n))
change=1
end if
exit for
nokeymap:
next


    DEF SEG = 0
    p417 = PEEK(&H417)
    iderestrict417 p417

    IF p417 AND 8 THEN 'alt held

        IF idealthighlight = 0 THEN
            'highlist first letter of each menu item
            idealthighlight = 1
            LOCATE , , 0: COLOR 15, 7: x = 4
            FOR i = 1 TO menus
                LOCATE 1, x: PRINT LEFT$(menu$(i, 0), 1);
                x = x + LEN(menu$(i, 0)) + 2
            NEXT
            ideentermenu = 1 'alt has just been pressed, so any next keystroke could enter a menu)
            IF change = 0 THEN skipdisplay = 0: GOTO ideloop 'force update so cursor will be restored to correct position
            change = 1
        END IF

    ELSE 'alt not held

        IF idealthighlight = 1 THEN
            'remove highlight
            idealthighlight = 0
            LOCATE , , 0: COLOR 0, 7: LOCATE 1, 1: PRINT menubar$;
            IF ideentermenu = 1 AND change = 0 and (PEEK(&H417) and (4+8))=0 THEN 'alt was pressed then released
                LOCATE , , , 8, 8: skipdisplay = 0: ideentermenu = 0: GOTO startmenu
            END IF
            change = 1
        END IF

    END IF 'alt not held

    IF change = 0 THEN

        'continue compilation?
        IF idecompiling THEN
            IF sendnextline THEN
                IF idecompiledline < iden THEN
                    idecompiledline = idecompiledline + 1
                    ide = 4
                    IF passback THEN
                        idecompiledline$ = passback$
                        idereturn$ = idecompiledline$
                    ELSE
                        idecompiledline$ = idegetline(idecompiledline)
                        idereturn$ = idecompiledline$
                    END IF
                    EXIT FUNCTION
                ELSE
                    'finished compilation
                    ide = 5 'end of program reached, what next?
                    'could return:
                    'i) 6 code ready for export/run
                    'ii) 7 repass required (if so send data from the beginning again)
                    EXIT FUNCTION
                END IF
            END IF
        END IF

        _LIMIT 16

        GOTO waitforinput
    END IF 'change=0

    skipdisplay = 0

    IF k$ = CHR$(0) + CHR$(98) THEN 'run detached
        idemdetached:
        iderunmode = 1
        GOTO idemrunspecial
    END IF

    IF k$ = CHR$(0) + CHR$(133) THEN 'make exe only
        idemexe:
        iderunmode = 2
        GOTO idemrunspecial
    END IF

    'run: F5/shift+F5
    IF k$ = CHR$(0) + "?" OR k$ = CHR$(0) + "X" THEN
        idemrun:
        iderunmode = 0 'standard run
        idemrunspecial:

        'run program
        IF ready THEN

            LOCATE , , 0
            COLOR 7, 1: LOCATE idewy - 3, 2: PRINT SPACE$(idewx - 2);: LOCATE idewy - 2, 2: PRINT SPACE$(idewx - 2);: LOCATE idewy - 1, 2: PRINT SPACE$(idewx - 2); 'clear status window

            IF idecompiled THEN

                IF iderunmode = 2 THEN
                    LOCATE idewy - 3, 2

if os$="LNX" then
PRINT "Already created executable file!";
else
PRINT "Already created .EXE file!";
end if

                    GOTO specialchar
                END IF

                LOCATE idewy - 3, 2: PRINT "Starting program...";
            ELSE

if os$="LNX" then
LOCATE idewy - 3, 2: PRINT "Creating executable file...";
else
LOCATE idewy - 3, 2: PRINT "Creating .EXE file...";
end if

            END IF
            PCOPY 3, 0

            'send run request
            'prepare name
            IF ideprogname$ = "" THEN
                f$ = "untitled" + tempfolderindexstr$
            ELSE
                f$ = ideprogname$
                f$ = LEFT$(f$, LEN(f$) - 4) 'remove .bas
            END IF
            ide = 9: idereturn$ = f$
            EXIT FUNCTION
        END IF
        'not ready!
        IF failed = 1 THEN GOTO specialchar
        'assume still compiling ...
        ideautorun = 1

        'correct status message
        LOCATE , , 0
        COLOR 7, 1: LOCATE idewy - 3, 2: PRINT SPACE$(idewx - 2);: LOCATE idewy - 2, 2: PRINT SPACE$(idewx - 2);: LOCATE idewy - 1, 2: PRINT SPACE$(idewx - 2); 'clear status window


        LOCATE idewy - 3, 2: PRINT "Checking program... (editing program will cancel request)";

        'must move the cursor back to its correct location
        ideshowtext
        LOCATE , , 1
        PCOPY 3, 0

        GOTO specialchar
    END IF

    ideentermenu = 0

    LOCATE , , 0
    LOCATE , , , 8, 8


    DEF SEG = 0
    p417 = PEEK(&H417)
    iderestrict417 p417

    IF p417 AND 3 THEN shiftheld = 1 ELSE shiftheld = 0


    IF mb <> 0 AND omb = 0 AND idemouseselect = 0 THEN
        IF my = 1 THEN
            x = 3
            FOR i = 1 TO menus
                x2 = LEN(menu$(i, 0)) + 2
                IF mx >= x AND mx < x + x2 THEN
                    m = i
                    GOTO showmenu
                END IF
                x = x + x2
            NEXT
        END IF
    END IF

    IF LEN(k$) = 2 THEN
        FOR i = 1 TO menus
            a$ = UCASE$(LEFT$(menu$(i, 0), 1))
            IF ASC(RIGHT$(k$, 1)) = idealtcode(ASC(a$)) THEN
                m = i
                LOCATE 1, 1: COLOR 0, 7: PRINT menubar$;
                PCOPY 3, 0
                GOTO showmenu
            END IF
        NEXT
    END IF

    IF mb <> 0 AND omb = 0 THEN
        IF mx > 1 AND mx < idewx AND my > 2 AND my < (idewy - 5) THEN 'inside text box
            ideselect = 1
            idecx = mx - 1 + idesx - 1
            idecy = my - 2 + idesy - 1
            IF idecy > iden THEN idecy = iden
            ideselect = 1: ideselectx1 = idecx: ideselecty1 = idecy
            idemouseselect = 1
        END IF
    END IF

    IF mb <> 0 AND omb = 0 THEN
        IF mx = idewx THEN
            IF iden > 1 THEN 'take no action if not slider available
                y = idevbar(idewx, 3, idewy - 8, idecy, iden)
                IF y = my THEN
                    idemouseselect = 2
                    ideselect = 0
                END IF
            END IF
        END IF
    END IF

    IF mb <> 0 AND omb = 0 THEN
        IF my = idewy - 5 THEN
            x = idehbar(2, idewy - 5, idewx - 2, idesx, 608)
            IF x = mx THEN
                idemouseselect = 3
                ideselect = 0
            END IF
        END IF
    END IF

    IF mb <> 0 AND idemouseselect = 0 THEN
        IF mx = idewx AND my > 2 AND my < idewy - 5 THEN 'inside vbar
            ideselect = 0
            IF my = 3 THEN k$ = CHR$(0) + CHR$(72): idewait
            IF my = idewy - 6 THEN k$ = CHR$(0) + CHR$(80): idewait
            IF my > 3 AND my < (idewy - 6) THEN
                'assume not on slider
                IF iden > 1 THEN 'take no action if not slider available
                    y = idevbar(idewx, 3, idewy - 8, idecy, iden)
                    IF y <> my THEN
                        IF my < y THEN
                            k$ = CHR$(0) + CHR$(73): idewait
                        ELSE
                            k$ = CHR$(0) + CHR$(81): idewait
                        END IF
                    END IF
                END IF
            END IF
        END IF
    END IF

    IF mb <> 0 AND idemouseselect = 0 THEN
        IF my = idewy - 5 AND mx > 1 AND mx < idewx THEN 'inside hbar
            ideselect = 0
            IF mx = 2 THEN k$ = CHR$(0) + "K": idewait
            IF mx = idewx - 1 THEN k$ = CHR$(0) + "M": idewait
            IF mx > 2 AND mx < idewx - 1 THEN
                'assume not on slider
                x = idehbar(2, idewy - 5, idewx - 2, idesx, 608)
                IF x <> mx THEN
                    IF mx < x THEN
                        idecx = idecx - 8
                        IF idecx < 1 THEN idecx = 1
                        idewait
                    ELSE
                        idecx = idecx + 8
                        idewait
                    END IF
                END IF

            END IF
        END IF
    END IF

    IF mb <> 0 AND idemouseselect = 2 THEN
        'move vbar scroller (idecy) to appropriate position
        IF iden > 1 THEN
            IF my <= 4 THEN idecy = 1
            IF my >= idewy - 7 THEN idecy = iden
            IF my > 4 AND my < idewy - 7 THEN
                y = my
                p! = y - 3 - 2 + .5
                p! = p! / ((idewy - 8) - 4)
                i = p! * (iden - 1) + 1
                idecy = i
            END IF
        END IF
    END IF

    IF mb <> 0 AND idemouseselect = 3 THEN
        'move hbar scroller (idecx) to appropriate position
        IF mx <= 3 THEN idesx = 1: idecx = idesx
        IF mx >= idewx - 2 THEN idesx = 608: idecx = idesx
        IF mx > 3 AND mx < idewx - 2 THEN
            x = mx
            p! = x - 2 - 2 + .5
            p! = p! / ((idewx - 2) - 4)
            i = p! * (608 - 1) + 1
            idesx = i
            idecx = idesx
        END IF
    END IF

    IF mb AND idemouseselect <= 1 THEN
        IF mx > 1 AND mx < idewx AND my > 2 AND my < idewy - 5 THEN 'inside text box
            IF idemouseselect = 1 THEN
                idecx = mx - 1 + idesx - 1
                idecy = my - 2 + idesy - 1
                IF idecy > iden THEN idecy = iden
            END IF
        END IF
    END IF

    IF mb THEN
        IF mx = 1 OR mx = idewx OR my <= 2 OR my >= idewy - 5 THEN 'off text window area
            IF idemouseselect = 1 THEN
                'scroll window
                IF my >= idewy - 5 THEN idecy = idecy + 1: IF idecy > iden THEN idecy = iden
                IF my <= 2 THEN idecy = idecy - 1: IF idecy < 1 THEN idecy = 1
                IF mx = 1 THEN idecx = idecx - 1: IF idecx < 1 THEN idecx = 1
                IF mx = idewx THEN idecx = idecx + 1
                idewait
            END IF
        END IF
    END IF

    DEF SEG = 0
p417=PEEK(&H417)
    iderestrict417 p417

    IF p417 AND 4 THEN ctrlheld = 1 ELSE ctrlheld = 0

    IF k$ = CHR$(1) AND ctrlheld = 1 THEN 'select all
        idemselectall:
        ideselect = 1: ideselectx1 = 1: ideselecty1 = 1
        idecy = iden
        a$ = idegetline(idecy)
        idecx = LEN(a$) + 1
        GOTO specialchar
    END IF

    IF k$ = CHR$(0) + CHR$(61) THEN 'F3
        idemf3:
        IF idefindtext$ <> "" THEN
            idefindagain
        ELSE
            GOTO idefindjmp
        END IF
        GOTO specialchar
    END IF

    IF k$ = CHR$(0) + CHR$(60) THEN 'F2
        GOTO idesubsjmp
    END IF

    IF ((k$ = CHR$(0) + "S" AND shiftheld <> 0) OR (k$ = CHR$(24) AND ctrlheld = 1)) AND ideselect = 1 THEN 'cut to clipboard
        idemcut:
        idechangemade = 1
        GOTO copy2clip
    END IF

    IF k$ = CHR$(0) + "S" AND ideselect = 1 THEN 'delete selection
        idechangemade = 1
        GOSUB delselect
        GOTO specialchar
    END IF

    IF (k$ = CHR$(0) + "R" AND shiftheld <> 0) OR (k$ = CHR$(22) AND ctrlheld = 1) THEN 'paste from clipboard
        idempaste:

        clip$ = _CLIPBOARD$ 'read clipboard

        IF LEN(clip$) THEN
            IF ideselect THEN GOSUB delselect
            IF INSTR(clip$, CHR$(13)) OR INSTR(clip$, CHR$(10)) THEN

                'full lines paste

                idelayoutallow = 2
                a$ = clip$
                x3 = 1 'scan from position
                i = 0 'lines counter

                fullpastenextline:

                x = INSTR(x3, a$, CHR$(13))
                x2 = INSTR(x3, a$, CHR$(10))
                IF x = 0 THEN x = x2
                IF x2 = 0 THEN x2 = x
                IF x2 < x THEN SWAP x, x2
                IF x2 > x + 1 THEN x2 = x 'if seperated by more than one character, they are seperate line terminators
                'x to x2 is the range of the next line terminator (1 or 2 characters)

                IF x THEN
                    ideinsline idecy + i, converttabs$(MID$(a$, x3, x - x3))
                    i = i + 1
                    x3 = x2 + 1
                ELSE
                    ideinsline idecy + i, converttabs$(MID$(a$, x3, LEN(a$) - x3 + 1))
                    i = i + 1
                    x3 = LEN(a$) + 1
                END IF

                IF x3 <= LEN(a$) GOTO fullpastenextline

            ELSE

                'insert single line paste
                a$ = idegetline(idecy)
                IF LEN(a$) < idecx - 1 THEN a$ = a$ + SPACE$(idecx - 1 - LEN(a$))
                a$ = LEFT$(a$, idecx - 1) + clip$ + RIGHT$(a$, LEN(a$) - idecx + 1)
                idesetline idecy, converttabs$(a$)

            END IF

            idechangemade = 1
        END IF
        GOTO specialchar
    END IF

    IF (k$ = CHR$(0) + CHR$(146) OR (k$ = CHR$(3) AND ctrlheld = 1)) AND ideselect = 1 THEN 'copy to clipboard
        copy2clip:
        clip$ = ""
        sy1 = ideselecty1
        sy2 = idecy
        IF sy1 > sy2 THEN SWAP sy1, sy2
        sx1 = ideselectx1
        sx2 = idecx
        IF sx1 > sx2 THEN SWAP sx1, sx2
        FOR y = sy1 TO sy2
            IF y <= iden THEN
                a$ = idegetline(y)
                IF sy1 = sy2 THEN 'single line select
                    FOR x = sx1 TO sx2 - 1
                        IF x <= LEN(a$) THEN clip$ = clip$ + MID$(a$, x, 1) ELSE clip$ = clip$ + " "
                    NEXT
                ELSE 'multiline select
                    IF idecx = 1 AND y = sy2 AND idecy > sy1 THEN clip$ = clip$ + CHR$(13) + CHR$(10): GOTO nofinalcopy
                    IF clip$ = "" THEN clip$ = a$ ELSE clip$ = clip$ + CHR$(13) + CHR$(10) + a$
                    nofinalcopy:
                END IF
            END IF
        NEXT
        IF clip$ <> "" THEN _CLIPBOARD$ = clip$
        IF k$ = CHR$(0) + "S" OR (k$ = CHR$(24) AND ctrlheld = 1) THEN GOSUB delselect
        GOTO specialchar
    END IF

    IF k$ = CHR$(0) + "R" AND shiftheld = 0 THEN 'toggle INSERT mode
        ideinsert = ideinsert + 1
        IF ideinsert = 2 THEN ideinsert = 0
    END IF

    IF k$ = CHR$(0) + "H" THEN
        GOSUB selectcheck
        idecy = idecy - 1
        IF idecy < 1 THEN idecy = 1
        GOTO specialchar
    END IF

    IF k$ = CHR$(0) + "P" THEN
        GOSUB selectcheck
        idecy = idecy + 1
        IF idecy > iden THEN idecy = iden
        GOTO specialchar
    END IF

    IF mousewheel THEN
        GOSUB selectcheck
        'move relative to top/bottom
        IF mousewheel < 0 THEN idecy = idesy
        IF mousewheel > 0 THEN idecy = idesy + (idewy - 9)
        idecy = idecy + mousewheel * 3
        IF idecy < 1 THEN idecy = 1
        IF idecy > iden THEN idecy = iden
        GOTO specialchar
    END IF

    IF k$ = CHR$(0) + "K" THEN
        GOSUB selectcheck
        idecx = idecx - 1
        IF idecx < 1 THEN idecx = 1
        GOTO specialchar
    END IF

    IF k$ = CHR$(0) + "M" THEN
        GOSUB selectcheck
        idecx = idecx + 1
        GOTO specialchar
    END IF

    IF k$ = CHR$(0) + "G" THEN
        GOSUB selectcheck
        idecx = 1
        GOTO specialchar
    END IF

    IF k$ = CHR$(0) + "O" THEN
        GOSUB selectcheck
        a$ = idegetline(idecy)
        idecx = LEN(a$) + 1
        GOTO specialchar
    END IF

    IF k$ = CHR$(0) + "w" THEN
        GOSUB selectcheck
        idecx = 1
        idecy = 1
        GOTO specialchar
    END IF

    IF k$ = CHR$(0) + "u" THEN
        GOSUB selectcheck
        idecy = iden
        a$ = idegetline(idecy)
        idecx = LEN(a$) + 1
        GOTO specialchar
    END IF

    IF k$ = CHR$(0) + "I" THEN
        GOSUB selectcheck
        idecy = idecy - (idewy - 9)
        IF idecy < 1 THEN idecy = 1
        GOTO specialchar
    END IF

    IF k$ = CHR$(0) + "Q" THEN
        GOSUB selectcheck
        idecy = idecy + (idewy - 9)
        IF idecy > iden THEN idecy = iden
        GOTO specialchar
    END IF



    GOTO skipgosubs

    selectcheck:
    IF shiftheld = 1 AND ideselect = 0 THEN ideselect = 1: ideselectx1 = idecx: ideselecty1 = idecy
    IF shiftheld = 0 THEN ideselect = 0
    RETURN

    delselect:
    sy1 = ideselecty1
    sy2 = idecy
    IF sy1 > sy2 THEN SWAP sy1, sy2
    sx1 = ideselectx1
    sx2 = idecx
    IF sx1 > sx2 THEN SWAP sx1, sx2
    nolastlinedel = 0
    IF sy1 <> sy2 AND idecx = 1 AND idecy > sy1 THEN sy2 = sy2 - 1: nolastlinedel = 1 'ignore last line of multi-line select?
    FOR y = sy2 TO sy1 STEP -1
        IF sy1 = sy2 AND nolastlinedel = 0 THEN 'single line select
            a$ = idegetline(y)
            a2$ = ""
            IF sx1 <= LEN(a$) THEN a2$ = LEFT$(a$, sx1 - 1) ELSE a2$ = a$
            IF sx2 <= LEN(a$) THEN a2$ = a2$ + RIGHT$(a$, LEN(a$) - sx2 + 1)
            idesetline y, a2$
        ELSE 'multiline select
            IF iden = 1 AND y = 1 THEN idesetline y, "" ELSE idedelline y
        END IF
    NEXT
    idecx = sx1: IF sy1 <> sy2 OR nolastlinedel = 1 THEN idecx = 1
    idecy = sy1
    ideselect = 0
    RETURN

    skipgosubs:

    IF k$ = CHR$(13) THEN
        ideselect = 0
        idechangemade = 1
        a$ = idegetline(idecy)
        IF idecx > LEN(a$) THEN
            ideinsline idecy + 1, ""
        ELSE
            idesetline idecy, LEFT$(a$, idecx - 1)
            ideinsline idecy + 1, RIGHT$(a$, LEN(a$) - idecx + 1)
        END IF
        idecy = idecy + 1
        idecx = 1
        GOTO specialchar
    END IF

    IF k$ = CHR$(0) + "S" THEN
        idechangemade = 1
        a$ = idegetline(idecy)
        IF idecx <= LEN(a$) THEN
            a$ = LEFT$(a$, idecx - 1) + RIGHT$(a$, LEN(a$) - idecx)
            idesetline idecy, a$
        ELSE
            a$ = a$ + SPACE$(idecx - LEN(a$) - 1)
            a$ = a$ + idegetline(idecy + 1)
            idesetline idecy, a$
            idedelline idecy + 1
        END IF
        GOTO specialchar
    END IF

    IF k$ = CHR$(8) THEN
        ideselect = 0
        idechangemade = 1
        a$ = idegetline(idecy)
        IF idecx = 1 THEN
            IF idecy > 1 THEN
                a2$ = idegetline(idecy - 1)
                idesetline idecy - 1, a2$ + a$
                idedelline idecy
                idecx = LEN(a2$) + 1
                idecy = idecy - 1
            END IF
            GOTO specialchar
        END IF
        IF idecx > LEN(a$) + 1 THEN
            idecx = LEN(a$) + 1
        ELSE
            a$ = LEFT$(a$, idecx - 2) + RIGHT$(a$, LEN(a$) - idecx + 1)
            idesetline idecy, a$
            idecx = idecx - 1
        END IF
        GOTO specialchar
    END IF









    'patch#1
    IF LEN(k$) <> 1 THEN GOTO specialchar
    IF k$ = CHR$(9) THEN GOTO ideforceinput
    IF control_chr(asc(k$)) THEN GOTO specialchar
    ideforceinput:

    IF k$ = CHR$(9) THEN
        x = 4
        IF ideautoindent <> 0 AND ideautoindentsize <> 0 THEN x = ideautoindentsize
        k$ = SPACE$(x - ((idecx - 1) MOD x))
    END IF

    'standard character
    IF ideselect THEN GOSUB delselect
    idechangemade = 1
    a$ = idegetline(idecy)
    IF LEN(a$) < idecx - 1 THEN a$ = a$ + SPACE$(idecx - 1 - LEN(a$))

    IF ideinsert THEN
        a2$ = RIGHT$(a$, LEN(a$) - idecx + 1)
        IF LEN(a2$) THEN a2$ = RIGHT$(a$, LEN(a$) - idecx)
        a$ = LEFT$(a$, idecx - 1) + k$ + a2$
    ELSE
        a$ = LEFT$(a$, idecx - 1) + k$ + RIGHT$(a$, LEN(a$) - idecx + 1)
    END IF

    idesetline idecy, a$
    idecx = idecx + LEN(k$)
    specialchar:

LOOP


startmenu:
m = 1
startmenu2:
altheld = 1

DO

    LOCATE 1, 3
    FOR i = 1 TO menus
        IF m = i THEN COLOR 15, 0 ELSE COLOR 15, 7
        PRINT " " + LEFT$(menu$(i, 0), 1);
        IF m = i THEN COLOR 7, 0 ELSE COLOR 0, 7
        PRINT RIGHT$(menu$(i, 0), LEN(menu$(i, 0)) - 1) + " ";
    NEXT

    PCOPY 3, 0
    DO
        k$ = INKEY$

        lastaltheld = altheld
        DEF SEG = 0
        p417 = PEEK(&H417)
    iderestrict417 p417

        IF p417 AND 8 THEN altheld = 1 ELSE altheld = 0
        IF altheld <> 0 AND lastaltheld = 0 THEN
            DO WHILE PEEK(&H417) AND 8: LOOP 'wait till alt is released
            k$ = CHR$(27)
        END IF

        getxymouse
        mx = mousex
        my = mousey
        IF mousebutton1 THEN
            IF my = 1 THEN
                x = 3
                FOR i = 1 TO menus
                    x2 = LEN(menu$(i, 0)) + 2
                    IF mx >= x AND mx < x + x2 THEN
                        m = i
                        LOCATE 1, 1: COLOR 0, 7: PRINT menubar$;
                        PCOPY 3, 0
                        DO UNTIL mousebutton1 = 0: getxymouse: LOOP
                        GOTO showmenu
                    END IF
                    x = x + x2
                NEXT
            END IF 'my=1
            DO UNTIL mousebutton1 = 0: getxymouse: LOOP
            k$ = CHR$(27) 'exit menu selection
        END IF 'mousebutton1

        _LIMIT 16
    LOOP UNTIL k$ <> ""

    k$ = UCASE$(k$)
    FOR i = 1 TO menus
        a$ = UCASE$(LEFT$(menu$(i, 0), 1))
        x = 0
        IF LEN(k$) = 2 THEN
            IF ASC(RIGHT$(k$, 1)) = idealtcode(ASC(a$)) THEN x = i
        ELSE
            IF k$ = a$ THEN x = i
        END IF
        IF x THEN
            m = x
            LOCATE 1, 1: COLOR 0, 7: PRINT menubar$;
            PCOPY 3, 0
            GOTO showmenu
        END IF
    NEXT

    IF k$ = CHR$(0) + "K" THEN m = m - 1
    IF k$ = CHR$(0) + "M" THEN m = m + 1
    IF k$ = CHR$(27) THEN
        LOCATE 1, 1: COLOR 0, 7: PRINT menubar$;
        GOTO ideloop
    END IF
    IF m < 1 THEN m = menus
    IF m > menus THEN m = 1
    IF k$ = CHR$(0) + "P" OR k$ = CHR$(0) + "H" OR k$ = CHR$(13) THEN 'up/down/enter
        LOCATE 1, 1: COLOR 0, 7: PRINT menubar$;
        PCOPY 3, 0

        GOTO showmenu
    END IF
LOOP

showmenu:
altheld = 1
PCOPY 0, 2
SCREEN , , 1, 0
r = 1
DO
    PCOPY 2, 1

    'find pos of menu m
    x = 4: FOR i = 1 TO m - 1: x = x + LEN(menu$(i, 0)) + 2: NEXT: xx = x
    LOCATE 1, xx - 1: COLOR 7, 0: PRINT " " + menu$(m, 0) + " "
    COLOR 0, 7
    'calculate menu width
    w = 0
    FOR i = 1 TO menusize(m)
        m$ = menu$(m, i)
        l = LEN(m$)
        IF INSTR(m$, "#") THEN l = l - 1
        IF INSTR(m$, "  ") THEN l = l + 2 'min 4 spacing
        IF l > w THEN w = l
    NEXT
    ideboxshadow xx - 2, 2, w + 4, menusize(m) + 2

    'draw menu items
    FOR i = 1 TO menusize(m)
        m$ = menu$(m, i)
        IF m$ = "-" THEN
            COLOR 0, 7: LOCATE i + 2, xx - 2: PRINT "Ã" + STRING$(w + 2, "Ä") + "´";
        ELSE
            IF r = i THEN LOCATE i + 2, xx - 1: COLOR 7, 0: PRINT SPACE$(w + 2);
            LOCATE i + 2, xx
            h = -1: x = INSTR(m$, "#"): IF x THEN h = x: m$ = LEFT$(m$, x - 1) + RIGHT$(m$, LEN(m$) - x)
            x = INSTR(m$, "  "): IF x THEN m1$ = LEFT$(m$, x - 1): m2$ = RIGHT$(m$, LEN(m$) - x - 1): m$ = m1$ + SPACE$(w - LEN(m1$) - LEN(m2$)) + m2$
            FOR x = 1 TO LEN(m$)
                IF x = h THEN
                    IF r = i THEN COLOR 15, 0 ELSE COLOR 15, 7
                ELSE
                    IF r = i THEN COLOR 7, 0 ELSE COLOR 0, 7
                END IF
                PRINT MID$(m$, x, 1);

            NEXT



        END IF

    NEXT

    PCOPY 1, 0

    change = 0
    omb = mb

    DO

        k$ = INKEY$: IF k$ <> "" THEN change = 1

        'revert to previous menu
        lastaltheld = altheld
        DEF SEG = 0
        p417 = PEEK(&H417)
    iderestrict417 p417

        IF p417 AND 8 THEN altheld = 1 ELSE altheld = 0
        IF altheld <> 0 AND lastaltheld = 0 THEN
            DO WHILE PEEK(&H417) AND 8: LOOP 'wait till alt is released
            PCOPY 3, 0: SCREEN , , 3, 0
            GOTO startmenu2
        END IF

        mousedown = 0: mouseup = 0
        getxymouse
        mx = mousex
        my = mousey
        mb = mousebutton1
        IF mb THEN change = 1
        IF omb = 0 AND mb = 1 THEN mousedown = 1
        IF omb = 1 AND mb = 0 THEN change = 1: mouseup = 1


        omb = mb


        IF change = 0 THEN _LIMIT 16
    LOOP UNTIL change

    s = 0

    'mouse selection
    IF mouseup THEN
        'uses pre-calc xx & w
        IF mx >= xx - 2 AND mx < xx - 2 + w + 4 THEN
            IF my > 2 AND my <= menusize(m) + 2 THEN
                y = my - 2
                IF menu$(m, y) <> "-" THEN
                    s = r
                END IF
            END IF
        END IF

        IF mx < xx - 2 OR mx >= xx - 2 + w + 4 OR my > menusize(m) + 3 THEN
            PCOPY 3, 0: SCREEN , , 3, 0
            GOTO ideloop
        END IF

    END IF



    IF mb THEN

        'top row
        IF my = 1 THEN
            lastm = m
            x = 3
            FOR i = 1 TO menus
                x2 = LEN(menu$(i, 0)) + 2
                IF mx >= x AND mx < x + x2 THEN
                    m = i
                    r = 1
                    IF lastm = m AND mousedown = 1 THEN PCOPY 3, 0: SCREEN , , 3, 0: idewait4mous: GOTO ideloop
                    EXIT FOR
                END IF
                x = x + x2
            NEXT
        END IF

        'uses pre-calc xx & w
        IF mx >= xx - 2 AND mx < xx - 2 + w + 4 THEN
            IF my > 2 AND my <= menusize(m) + 2 THEN
                y = my - 2
                IF menu$(m, y) <> "-" THEN r = y
            END IF
        END IF

    END IF 'mb



    k$ = UCASE$(k$)

    IF k$ = CHR$(0) + "K" THEN m = m - 1: r = 1
    IF k$ = CHR$(0) + "M" THEN m = m + 1: r = 1
    IF m < 1 THEN m = menus
    IF m > menus THEN m = 1
    IF k$ = CHR$(27) THEN
        PCOPY 3, 0: SCREEN , , 3, 0
        GOTO ideloop
    END IF
    IF k$ = CHR$(0) + "P" THEN
        r = r + 1
        IF menu$(m, r) = "-" THEN r = r + 1
        IF r > menusize(m) THEN r = 1
    END IF

    IF k$ = CHR$(0) + "H" THEN
        r = r - 1
        IF menu$(m, r) = "-" THEN r = r - 1
        IF r < 1 THEN r = menusize(m)
    END IF

    'select?

    'with enter
    IF k$ = CHR$(13) THEN
        s = r
    END IF
    'with hotkey
    FOR r2 = 1 TO menusize(m)
        x = INSTR(menu$(m, r2), "#")
        IF x THEN
            a$ = UCASE$(MID$(menu$(m, r2), x + 1, 1))
            IF LEN(k$) = 2 THEN
                IF ASC(RIGHT$(k$, 1)) = idealtcode(ASC(a$)) THEN s = r2: EXIT FOR
            ELSE
                IF k$ = a$ THEN s = r2: EXIT FOR
            END IF
        END IF
    NEXT

    IF s THEN

        'set idehl, a shared variable used by various dialogue boxes
        'note: it shouldn't need to be shared!
        DEF SEG = 0
p417=PEEK(&H417)
    iderestrict417 p417

alt = p417 AND 8
 IF alt THEN idehl = 1 ELSE idehl = 0

        IF menu$(m, s) = "#Language..." THEN
            PCOPY 2, 0
            retval = idelanguagebox
            PCOPY 3, 0: SCREEN , , 3, 0: idewait4mous: idewait4alt
            GOTO ideloop
        END IF

        IF menu$(m, s) = "#Display..." THEN
            PCOPY 2, 0
            retval = idedisplaybox
            IF retval = 1 THEN
                'screen dimensions have changed and everything must be redrawn/reapplied
                WIDTH idewx, idewy
                IF idecustomfont THEN
                    _FONT idecustomfonthandle
                ELSE
                    _FONT 16
                END IF
                skipdisplay = 0
                GOTO redraweverything
            END IF
            PCOPY 3, 0: SCREEN , , 3, 0: idewait4mous: idewait4alt
            GOTO ideloop
        END IF

        IF menu$(m, s) = "#Code layout..." THEN
            PCOPY 2, 0
            retval = idelayoutbox
            IF retval THEN idechangemade = 1: idelayoutallow = 2 'recompile if options changed
            PCOPY 3, 0: SCREEN , , 3, 0: idewait4mous: idewait4alt
            GOTO ideloop
        END IF

        IF menu$(m, s) = "#Update..." THEN
            PCOPY 2, 0
            retval = ideupdatebox
            'retval is ignored
            PCOPY 3, 0: SCREEN , , 3, 0: idewait4mous: idewait4alt
            GOTO ideloop
        END IF

        IF menu$(m, s) = "#Update" THEN
            PCOPY 2, 0            
UpdateHandle = BeginDownload("www.qb64.net/update.txt")
if UpdateHandle then
ideupdatetimerval=TIMER
do until abs(TIMER-ideupdatetimerval)>=5
ContinueDownloads
IF DL(UpdateHandle).State=2 THEN 'download complete
update 1
UpdateHandle=0
GOTO ideloop
end if
_limit 10
loop
close DL(UpdateHandle).handle: DL(UpdateHandle).state=0: UpdateHandle=0
idemessagebox "Update","Could not connect to server."
else
idemessagebox "Update","Could not connect to server."
            PCOPY 3, 0: SCREEN , , 3, 0: idewait4mous: idewait4alt
end if 'updatehandle
           GOTO ideloop
        END IF

        IF menu$(m, s) = "New #SUB..." THEN
            PCOPY 2, 0
            idenewsf "SUB"
            ideselect = 0
            PCOPY 3, 0: SCREEN , , 3, 0: idewait4mous: idewait4alt
            GOTO ideloop
        END IF
        IF menu$(m, s) = "New #FUNCTION..." THEN
            PCOPY 2, 0
            idenewsf "FUNCTION"
            ideselect = 0
            PCOPY 3, 0: SCREEN , , 3, 0: idewait4mous: idewait4alt
            GOTO ideloop
        END IF

        IF menu$(m, s) = "#SUBs...  F2" THEN
            PCOPY 2, 0
            idesubsjmp:
            r$ = idesubs
            PCOPY 3, 0: SCREEN , , 3, 0: idewait4mous: idewait4alt
            GOTO ideloop
        END IF



        IF menu$(m, s) = "#Find..." THEN
            PCOPY 2, 0
            idefindjmp:
            r$ = idefind
            PCOPY 3, 0: SCREEN , , 3, 0: idewait4mous: idewait4alt
            '...
            GOTO ideloop
        END IF

        IF menu$(m, s) = "#Change..." THEN
            PCOPY 2, 0
            r$ = idechange
            PCOPY 3, 0: SCREEN , , 3, 0: idewait4mous: idewait4alt
            IF r$ = "C" OR r$ = "" THEN GOTO ideloop
            'assume "V", verify changes
            oldcx = idecx: oldcy = idecy
            found = 0: looped = 0
            'set temp variables
            s$ = idefindtext$
            IF idefindcasesens = 0 THEN s$ = UCASE$(s$)

            'attempt to locate next item to change
            l$ = idegetline(idecy)
            IF LEN(l$) <= idecx THEN 'advance cursor to next line?
                idechangenextline:
                idecy = idecy + 1
                IF idecy > iden THEN idecy = 1: looped = looped + 1
                l$ = idegetline(idecy)
                idecx = 0 '0 is invalid, but set for temporary purposes!
            END IF
            'check for possible finish...
            x1 = idecx + 1
            idechangeonce:
            IF (((x1 > oldcx AND idecy = oldcy) OR idecy > oldcy) AND looped = 1) OR looped > 1 THEN
                idecx = oldcx: idecy = oldcy
                IF found THEN
                    ideshowtext
                    SCREEN , , 0, 0: LOCATE , , 1: SCREEN , , 3, 0
                    PCOPY 3, 0
                    idechanged
                ELSE
                    idenomatch
                END IF
                PCOPY 3, 0: SCREEN , , 3, 0: idewait4mous: idewait4alt
                GOTO ideloop
            END IF

            IF idefindcasesens = 0 THEN l3$ = UCASE$(l$) ELSE l3$ = l$
            x = INSTR(x1, l3$, s$)

            IF x THEN
                IF idefindwholeword THEN
                    whole = 1
                    IF x > 1 THEN
                        c = ASC(UCASE$(MID$(l$, x - 1, 1)))
                        IF c >= 65 AND c <= 90 THEN whole = 0
                        IF c >= 48 AND c <= 57 THEN whole = 0
                    END IF
                    IF x + LEN(s$) <= LEN(l$) THEN
                        c = ASC(UCASE$(MID$(l$, x + LEN(s$), 1)))
                        IF c >= 65 AND c <= 90 THEN whole = 0
                        IF c >= 48 AND c <= 57 THEN whole = 0
                    END IF
                    IF whole = 0 THEN
                        x1 = x + 1
                        x = 0
                        IF x1 <= LEN(l$) THEN GOTO idechangeonce
                    END IF
                END IF
            END IF

            IF x THEN
                found = 1
                'verify change
                idecx = x
                ideselect = 1
                ideselecty1 = idecy
                ideselectx1 = idecx + LEN(s$)
                ideshowtext
                SCREEN , , 0, 0: LOCATE , , 1: SCREEN , , 3, 0
                PCOPY 3, 0
                r$ = idechangeit
                idedeltxt
                PCOPY 3, 0: SCREEN , , 3, 0: idewait4mous: idewait4alt
                ideselect = 0
                IF r$ = "C" THEN idecx = oldcx: idecy = oldcy: GOTO ideloop
                IF r$ = "Y" THEN
                    idechangemade = 1
                    IF LEN(l$) >= ideselectx1 THEN
                        l$ = LEFT$(l$, idecx - 1) + idechangeto$ + RIGHT$(l$, LEN(l$) - ideselectx1 + 1)
                    ELSE
                        l$ = LEFT$(l$, idecx - 1) + idechangeto$
                    END IF
                    idesetline idecy, l$
                    idecx = idecx + LEN(idechangeto$)
                ELSE
                    '"N"
                    idecx = idecx + 1
                END IF
                x1 = idecx
                IF x1 <= LEN(l$) THEN GOTO idechangeonce
            END IF

            GOTO idechangenextline

            GOTO ideloop
        END IF '#Change...

        IF menu$(m, s) = "#Repeat Last Find  F3" THEN
            PCOPY 3, 0: SCREEN , , 3, 0: idewait4mous: idewait4alt
            GOTO idemf3
        END IF

        IF menu$(m, s) = "Cl#ear  Del" THEN
            PCOPY 3, 0: SCREEN , , 3, 0: idewait4mous: idewait4alt
            IF ideselect = 1 THEN
                idechangemade = 1
                GOSUB delselect
            END IF
            GOTO ideloop
        END IF

        IF menu$(m, s) = "#Paste  Shift+Ins or CTRL+V" THEN
            PCOPY 3, 0: SCREEN , , 3, 0: idewait4mous: idewait4alt
            GOTO idempaste
        END IF

        IF menu$(m, s) = "#Copy  Ctrl+Ins or CTRL+C" THEN
            PCOPY 3, 0: SCREEN , , 3, 0: idewait4mous: idewait4alt
            IF ideselect = 1 THEN GOTO copy2clip
            GOTO ideloop
        END IF

        IF menu$(m, s) = "Cu#t  Shift+Del or CTRL+X" THEN
            PCOPY 3, 0: SCREEN , , 3, 0: idewait4mous: idewait4alt
            IF ideselect = 1 THEN
                k$ = CHR$(0) + "S" 'tricks handler into del after copy
                GOTO idemcut
            END IF
            GOTO ideloop
        END IF

        IF menu$(m, s) = "Select #All  CTRL+A" THEN
            PCOPY 3, 0: SCREEN , , 3, 0: idewait4mous: idewait4alt
            GOTO idemselectall
        END IF

        menu$(m, i) = "Select #All  CTRL+A": i = i + 1

        IF menu$(m, s) = "#Start  F5" THEN
            PCOPY 3, 0: SCREEN , , 3, 0: idewait4mous: idewait4alt
            GOTO idemrun
        END IF

        IF menu$(m, s) = "Start (#Detached)  Ctrl+F5" THEN
            PCOPY 3, 0: SCREEN , , 3, 0: idewait4mous: idewait4alt
            GOTO idemdetached
        END IF

        IF menu$(m, s) = "Make E#XE Only  F11" or menu$(m, s) = "Make E#xecutable Only  F11" THEN
            PCOPY 3, 0: SCREEN , , 3, 0: idewait4mous: idewait4alt
            GOTO idemexe
        END IF

        IF menu$(m, s) = "E#xit" THEN
            PCOPY 2, 0
            quickexit:
            IF ideunsaved = 1 THEN
                r$ = idesavenow
                PCOPY 3, 0: SCREEN , , 3, 0: idewait4mous: idewait4alt
                IF r$ = "C" THEN GOTO ideloop
                IF r$ = "Y" THEN
                    IF ideprogname = "" THEN
                        r$ = idesaveas$("untitled" + tempfolderindexstr$ + ".bas")
                        IF r$ = "C" THEN
                            PCOPY 3, 0: SCREEN , , 3, 0: idewait4mous: idewait4alt: GOTO ideloop
                        END IF
                    ELSE
                        idesave idepath$ + idepathsep$ + ideprogname$
                    END IF
                END IF
            END IF
            OPEN tmpdir$ + "autosave.bin" FOR OUTPUT AS #150: CLOSE #150
            SYSTEM
        END IF

        IF menu$(m, s) = "#New" THEN
            PCOPY 2, 0
            IF ideunsaved = 1 THEN
                r$ = idesavenow
                PCOPY 3, 0: SCREEN , , 3, 0: idewait4mous: idewait4alt
                IF r$ = "C" THEN GOTO ideloop
                IF r$ = "Y" THEN
                    IF ideprogname = "" THEN
                        a$ = idesaveas$("untitled" + tempfolderindexstr$ + ".bas")
                        PCOPY 3, 0: SCREEN , , 3, 0: idewait4mous: idewait4alt
                        IF r$ = "C" THEN GOTO ideloop
                    ELSE
                        idesave idepath$ + idepathsep$ + ideprogname$
                    END IF
                END IF
            END IF
            ideunsaved = -1
            'new blank text field
            idet$ = MKL$(0) + MKL$(0): idel = 1: ideli = 1: iden = 1
            idesx = 1
            idesy = 1
            idecx = 1
            idecy = 1
            ideselect = 0
            ideprogname$ = ""
            _TITLE "QB64"
            idechangemade = 1
            GOTO ideloop
        END IF

        IF menu$(m, s) = "#Open..." THEN
            PCOPY 2, 0
            IF ideunsaved THEN
                r$ = idesavenow
                PCOPY 3, 0: SCREEN , , 3, 0: idewait4mous: idewait4alt
                IF r$ = "C" THEN GOTO ideloop
                IF r$ = "Y" THEN
                    IF ideprogname = "" THEN
                        r$ = idesaveas$("untitled" + tempfolderindexstr$ + ".bas")
                        IF r$ = "C" THEN GOTO ideloop
                    ELSE
                        idesave idepath$ + idepathsep$ + ideprogname$
                    END IF
                    PCOPY 3, 0: SCREEN , , 3, 0: idewait4mous: idewait4alt
                END IF '"Y"
            END IF 'unsaved
            r$ = ideopen
            IF r$ <> "C" THEN ideunsaved = -1: idechangemade = 1: idelayoutallow = 2
            PCOPY 3, 0: SCREEN , , 3, 0: idewait4mous: idewait4alt: GOTO ideloop
        END IF

        IF menu$(m, s) = "#Save" THEN
            PCOPY 2, 0
            IF ideprogname = "" THEN
                a$ = idesaveas$("untitled" + tempfolderindexstr$ + ".bas")
            ELSE
                idesave idepath$ + idepathsep$ + ideprogname$
            END IF
            PCOPY 3, 0: SCREEN , , 3, 0: idewait4mous: idewait4alt: GOTO ideloop
        END IF


        IF menu$(m, s) = "Save #As..." THEN
            PCOPY 2, 0
            IF ideprogname = "" THEN
                a$ = idesaveas$("untitled" + tempfolderindexstr$ + ".bas")
            ELSE
                a$ = idesaveas$(ideprogname$)
            END IF
            PCOPY 3, 0: SCREEN , , 3, 0: idewait4mous: idewait4alt: GOTO ideloop
        END IF




        SCREEN , , 0, 0
        CLS: PRINT "MENU ITEM [" + menu$(m, s) + "] NOT IMPLEMENTED!": END
    END IF




LOOP

END FUNCTION

SUB idebox (x, y, w, h)
LOCATE y, x: PRINT "Ú" + STRING$(w - 2, "Ä") + "¿";
FOR y2 = y + 1 TO y + h - 2
    LOCATE y2, x: PRINT "³" + SPACE$(w - 2) + "³";
NEXT
LOCATE y + h - 1, x: PRINT "À" + STRING$(w - 2, "Ä") + "Ù";
END SUB

SUB ideboxshadow (x, y, w, h)

LOCATE y, x: PRINT "Ú" + STRING$(w - 2, "Ä") + "¿";
FOR y2 = y + 1 TO y + h - 2
    LOCATE y2, x: PRINT "³" + SPACE$(w - 2) + "³";
NEXT
LOCATE y + h - 1, x: PRINT "À" + STRING$(w - 2, "Ä") + "Ù";
'shadow
COLOR 8, 0
FOR y2 = y + 1 TO y + h - 1
    FOR x2 = x + w TO x + w + 1
        IF x2 <= idewx AND y2 <= idewy THEN
            LOCATE y2, x2: PRINT CHR$(SCREEN(y2, x2));
        END IF
    NEXT
NEXT

y2 = y + h
IF y2 <= idewy THEN
    FOR x2 = x + 2 TO x + w + 1
        IF x2 <= idewx THEN
            LOCATE y2, x2: PRINT CHR$(SCREEN(y2, x2));
        END IF
    NEXT
END IF


END SUB

FUNCTION idechange$


'-------- generic dialog box header --------
PCOPY 0, 2
PCOPY 0, 1
SCREEN , , 1, 0
focus = 1
DIM p AS idedbptype
DIM o(1 TO 100) AS idedbotype
DIM oo AS idedbotype
DIM sep AS STRING * 1
sep = CHR$(0)
'-------- end of generic dialog box header --------

'-------- init --------

'built initial search strings
IF ideselect THEN
    IF ideselecty1 = idecy THEN 'single line selected
        a$ = idegetline(idecy)
        a2$ = ""
        sx1 = ideselectx1: sx2 = idecx
        IF sx2 < sx1 THEN SWAP sx1, sx2
        FOR x = sx1 TO sx2 - 1
            IF x <= LEN(a$) THEN a2$ = a2$ + MID$(a$, x, 1) ELSE a2$ = a2$ + " "
        NEXT
    END IF
END IF
IF a2$ = "" THEN
    a2$ = idefindtext
END IF

i = 0
idepar p, 60, 11, "Change"
i = i + 1
o(i).typ = 1
o(i).y = 2
o(i).nam = idenewtxt("#Find What")
o(i).txt = idenewtxt(a2$)
o(i).v1 = LEN(a2$)

i = i + 1
o(i).typ = 1
o(i).y = 5
o(i).nam = idenewtxt("Change #To")
o(i).txt = idenewtxt(idechangeto)
o(i).v1 = LEN(idechangeto)

i = i + 1
o(i).typ = 4 'check box
o(i).y = 8
o(i).nam = idenewtxt("#Match Upper/Lowercase")
o(i).sel = idefindcasesens
i = i + 1
o(i).typ = 4 'check box
o(i).y = 9
o(i).nam = idenewtxt("#Whole Word")
o(i).sel = idefindwholeword

i = i + 1
o(i).typ = 3
o(i).y = 11
o(i).txt = idenewtxt("Find and #Verify" + sep + "#Change All" + sep + "Cancel")
o(i).def = 1
'-------- end of init --------

'-------- generic init --------
FOR i = 1 TO 100: o(i).par = p: NEXT 'set parent info of objects
'-------- end of generic init --------

DO 'main loop

    '-------- generic display dialog box & objects --------

    idedrawpar p
    f = 1: cx = 0: cy = 0
    FOR i = 1 TO 100

        IF o(i).typ THEN

            'prepare object
            o(i).foc = focus - f 'focus offset

            o(i).cx = 0: o(i).cy = 0

            idedrawobj o(i), f 'display object

            IF o(i).cx THEN cx = o(i).cx: cy = o(i).cy

        END IF
    NEXT i
    lastfocus = f - 1
    '-------- end of generic display dialog box & objects --------

    '-------- custom display changes --------
    '-------- end of custom display changes --------

    'update visual page and cursor position
    PCOPY 1, 0
    IF cx THEN SCREEN , , 0, 0: LOCATE cy, cx, 1: SCREEN , , 1, 0

    '-------- read input --------
    change = 0
    DO
        getxymouse
        mx = mousex: my = mousey: mb = mousebutton1
        IF mb <> 0 AND omb = 0 THEN mousedown = 1: change = 1
        IF mb = 0 AND omb <> 0 THEN mouseup = 1: change = 1
        IF mb THEN change = 1
        omb = mb
        k$ = INKEY$: IF LEN(k$) THEN change = 1
        DEF SEG = 0: alt = PEEK(&H417) AND 8: IF alt <> oldalt THEN change = 1
        oldalt = alt

        IF change = 0 THEN _LIMIT 16
    LOOP UNTIL change
    SCREEN , , 0, 0: LOCATE , , 0: SCREEN , , 1, 0
    IF alt THEN idehl = 1 ELSE idehl = 0
    'convert "alt+letter" scancode to letter's ASCII character
    altletter$ = ""
    IF alt THEN
        IF LEN(k$) = 2 THEN
            k = ASC(RIGHT$(k$, 1))
            FOR c = 65 TO 90
                IF k = idealtcode(c) THEN
                    altletter$ = CHR$(c)
                    EXIT FOR
                END IF
            NEXT
        END IF
    END IF
    '-------- end of read input --------

    '-------- generic input response --------
    info = 0
    IF k$ = "" THEN k$ = CHR$(255)
    IF k$ = CHR$(9) THEN focus = focus + 1
    IF k$ = CHR$(0) + CHR$(15) THEN focus = focus - 1
    IF focus < 1 THEN focus = lastfocus
    IF focus > lastfocus THEN focus = 1
    f = 1
    FOR i = 1 TO 100
        t = o(i).typ
        IF t THEN
            focusoffset = focus - f
            ideupdateobj o(i), focus, f, focusoffset, k$, altletter$, mb, mousedown, mouseup, mx, my, info
        END IF
    NEXT
    '-------- end of generic input response --------

    'specific post controls

    IF k$ = CHR$(27) OR (focus = 7 AND info <> 0) THEN
        idechange$ = "C"
        EXIT FUNCTION
    END IF




    IF focus = 6 AND info <> 0 THEN
        idefindcasesens = o(3).sel
        idefindwholeword = o(4).sel
        s$ = idetxt(o(1).txt)
        idefindtext$ = s$
        idechangeto$ = idetxt(o(2).txt)

        changed = 0
        s$ = idefindtext$
        IF idefindcasesens = 0 THEN s$ = UCASE$(s$)

        FOR y = 1 TO iden
            l$ = idegetline(y)
            l2$ = ""

            x1 = 1
            idechangeall:
            IF idefindcasesens = 0 THEN l3$ = UCASE$(l$) ELSE l3$ = l$
            x = INSTR(x1, l3$, s$)

            IF x THEN
                IF idefindwholeword THEN
                    whole = 1
                    IF x > 1 THEN
                        c = ASC(UCASE$(MID$(l$, x - 1, 1)))
                        IF c >= 65 AND c <= 90 THEN whole = 0
                        IF c >= 48 AND c <= 57 THEN whole = 0
                    END IF
                    IF x + LEN(s$) <= LEN(l$) THEN
                        c = ASC(UCASE$(MID$(l$, x + LEN(s$), 1)))
                        IF c >= 65 AND c <= 90 THEN whole = 0
                        IF c >= 48 AND c <= 57 THEN whole = 0
                    END IF
                    IF whole = 0 THEN
                        x1 = x + 1
                        x = 0
                        IF x1 <= LEN(l$) THEN GOTO idechangeall
                    END IF
                END IF
            END IF

            IF x THEN
                l2$ = l2$ + MID$(l$, x1, x - x1) + idechangeto$
                x1 = x + LEN(s$)
                IF x1 <= LEN(l$) THEN GOTO idechangeall
            END IF

            l2$ = l2$ + MID$(l$, x1, LEN(l$) - x1 + 1)
            IF l2$ <> l$ THEN idesetline y, l2$: changed = 1

        NEXT

        IF changed = 0 THEN idenomatch ELSE idechanged: idechangemade = 1
        EXIT FUNCTION

    END IF 'change all


    IF (focus = 5 AND info <> 0) OR k$ = CHR$(13) THEN
        idefindcasesens = o(3).sel
        idefindwholeword = o(4).sel
        idefindtext$ = idetxt(o(1).txt)
        idechangeto$ = idetxt(o(2).txt)
        idechange$ = "V"
        EXIT FUNCTION
    END IF


    'end of custom controls



    mousedown = 0
    mouseup = 0
LOOP


END FUNCTION

SUB idechanged

'-------- generic dialog box header --------
PCOPY 3, 0
PCOPY 0, 2
PCOPY 0, 1
SCREEN , , 1, 0
focus = 1
DIM p AS idedbptype
DIM o(1 TO 100) AS idedbotype
DIM oo AS idedbotype
DIM sep AS STRING * 1
sep = CHR$(0)
'-------- end of generic dialog box header --------

'-------- init --------
i = 0
idepar p, 19, 4, ""
i = i + 1
o(i).typ = 3
o(i).y = 4
o(i).txt = idenewtxt("OK")
o(i).def = 1
'-------- end of init --------

'-------- generic init --------
FOR i = 1 TO 100: o(i).par = p: NEXT 'set parent info of objects
'-------- end of generic init --------

DO 'main loop

    '-------- generic display dialog box & objects --------
    idedrawpar p
    f = 1: cx = 0: cy = 0
    FOR i = 1 TO 100
        IF o(i).typ THEN
            'prepare object
            o(i).foc = focus - f 'focus offset
            o(i).cx = 0: o(i).cy = 0
            idedrawobj o(i), f 'display object
            IF o(i).cx THEN cx = o(i).cx: cy = o(i).cy
        END IF
    NEXT i
    lastfocus = f - 1
    '-------- end of generic display dialog box & objects --------

    '-------- custom display changes --------
    COLOR 0, 7: LOCATE p.y + 2, p.x + 3: PRINT "Change Complete";
    '-------- end of custom display changes --------

    'update visual page and cursor position
    PCOPY 1, 0
    IF cx THEN SCREEN , , 0, 0: LOCATE cy, cx, 1: SCREEN , , 1, 0

    '-------- read input --------
    change = 0
    DO
        getxymouse
        mx = mousex: my = mousey: mb = mousebutton1
        IF mb <> 0 AND omb = 0 THEN mousedown = 1: change = 1
        IF mb = 0 AND omb <> 0 THEN mouseup = 1: change = 1
        IF mb THEN change = 1
        omb = mb
        k$ = INKEY$: IF LEN(k$) THEN change = 1
        'DEF SEG = 0: alt = PEEK(&H417) AND 8
        alt = 8
        IF alt <> oldalt THEN change = 1
        oldalt = alt

        IF change = 0 THEN _LIMIT 16
    LOOP UNTIL change
    SCREEN , , 0, 0: LOCATE , , 0: SCREEN , , 1, 0
    IF alt THEN idehl = 1 ELSE idehl = 0
    'convert "alt+letter" scancode to letter's ASCII character
    altletter$ = ""
    IF alt THEN
        IF LEN(k$) = 2 THEN
            k = ASC(RIGHT$(k$, 1))
            FOR c = 65 TO 90
                IF k = idealtcode(c) THEN
                    altletter$ = CHR$(c)
                    EXIT FOR
                END IF
            NEXT
        END IF
    END IF
    IF UCASE$(k$) = "Y" THEN altletter$ = "Y"
    IF UCASE$(k$) = "N" THEN altletter$ = "N"

    '-------- end of read input --------

    '-------- generic input response --------
    info = 0
    IF k$ = "" THEN k$ = CHR$(255)
    IF k$ = CHR$(9) THEN focus = focus + 1
    IF k$ = CHR$(0) + CHR$(15) THEN focus = focus - 1
    IF focus < 1 THEN focus = lastfocus
    IF focus > lastfocus THEN focus = 1
    f = 1
    FOR i = 1 TO 100
        t = o(i).typ
        IF t THEN
            focusoffset = focus - f
            ideupdateobj o(i), focus, f, focusoffset, k$, altletter$, mb, mousedown, mouseup, mx, my, info
        END IF
    NEXT
    '-------- end of generic input response --------

    IF k$ = CHR$(27) THEN
        EXIT SUB
    END IF

    IF info THEN
        EXIT SUB
    END IF

    'end of custom controls

    mousedown = 0
    mouseup = 0
LOOP

END SUB

FUNCTION idechangeit$

'-------- generic dialog box header --------
PCOPY 3, 0
PCOPY 0, 2
PCOPY 0, 1
SCREEN , , 1, 0
focus = 1
DIM p AS idedbptype
DIM o(1 TO 100) AS idedbotype
DIM oo AS idedbotype
DIM sep AS STRING * 1
sep = CHR$(0)
'-------- end of generic dialog box header --------

'-------- init --------
i = 0
w = 45
p.x = 40 - w \ 2
p.y = 21
p.w = w
p.h = 2
p.nam = idenewtxt("Change")

i = i + 1
o(i).typ = 3
o(i).y = 2
o(i).txt = idenewtxt("#Change" + sep + "#Skip" + sep + "Cancel")
o(i).def = 1
'-------- end of init --------

'-------- generic init --------
FOR i = 1 TO 100: o(i).par = p: NEXT 'set parent info of objects
'-------- end of generic init --------

DO 'main loop

    '-------- generic display dialog box & objects --------
    idedrawpar p
    f = 1: cx = 0: cy = 0
    FOR i = 1 TO 100
        IF o(i).typ THEN
            'prepare object
            o(i).foc = focus - f 'focus offset
            o(i).cx = 0: o(i).cy = 0
            idedrawobj o(i), f 'display object
            IF o(i).cx THEN cx = o(i).cx: cy = o(i).cy
        END IF
    NEXT i
    lastfocus = f - 1
    '-------- end of generic display dialog box & objects --------

    '-------- custom display changes --------
    '-------- end of custom display changes --------

    'update visual page and cursor position
    PCOPY 1, 0
    IF cx THEN SCREEN , , 0, 0: LOCATE cy, cx, 1: SCREEN , , 1, 0

    '-------- read input --------
    change = 0
    DO
        getxymouse
        mx = mousex: my = mousey: mb = mousebutton1
        IF mb <> 0 AND omb = 0 THEN mousedown = 1: change = 1
        IF mb = 0 AND omb <> 0 THEN mouseup = 1: change = 1
        IF mb THEN change = 1
        omb = mb
        k$ = INKEY$: IF LEN(k$) THEN change = 1
        'DEF SEG = 0: alt = PEEK(&H417) AND 8
        alt = 8
        IF alt <> oldalt THEN change = 1
        oldalt = alt

        IF change = 0 THEN _LIMIT 16
    LOOP UNTIL change
    SCREEN , , 0, 0: LOCATE , , 0: SCREEN , , 1, 0
    IF alt THEN idehl = 1 ELSE idehl = 0
    'convert "alt+letter" scancode to letter's ASCII character
    altletter$ = ""
    IF alt THEN
        IF LEN(k$) = 2 THEN
            k = ASC(RIGHT$(k$, 1))
            FOR c = 65 TO 90
                IF k = idealtcode(c) THEN
                    altletter$ = CHR$(c)
                    EXIT FOR
                END IF
            NEXT
        END IF
    END IF
    IF UCASE$(k$) = "C" THEN altletter$ = "C"
    IF UCASE$(k$) = "S" THEN altletter$ = "S"


    '-------- end of read input --------

    '-------- generic input response --------
    info = 0
    IF k$ = "" THEN k$ = CHR$(255)
    IF k$ = CHR$(9) THEN focus = focus + 1
    IF k$ = CHR$(0) + CHR$(15) THEN focus = focus - 1
    IF focus < 1 THEN focus = lastfocus
    IF focus > lastfocus THEN focus = 1
    f = 1
    FOR i = 1 TO 100
        t = o(i).typ
        IF t THEN
            focusoffset = focus - f
            ideupdateobj o(i), focus, f, focusoffset, k$, altletter$, mb, mousedown, mouseup, mx, my, info
        END IF
    NEXT
    '-------- end of generic input response --------

    IF k$ = CHR$(27) THEN
        idechangeit$ = "C"
        EXIT FUNCTION
    END IF

    IF info THEN
        IF info = 1 THEN idechangeit$ = "Y"
        IF info = 2 THEN idechangeit$ = "N"
        IF info = 3 THEN idechangeit$ = "C"
        EXIT FUNCTION
    END IF

    'end of custom controls
    mousedown = 0
    mouseup = 0
LOOP


END FUNCTION

SUB idedelline (i)
idegotoline i
textlen = CVL(MID$(idet$, ideli, 4))
idet$ = LEFT$(idet$, ideli - 1) + RIGHT$(idet$, LEN(idet$) - ideli + 1 - 8 - textlen)
iden = iden - 1


END SUB

SUB idedeltxt
idetxtlast = 0
END SUB

SUB idedrawobj (o AS idedbotype, f)
DIM sep AS STRING * 1
sep = CHR$(0)

'#1: SINGLE LINE TEXT INPUT BOX
IF o.typ = 1 THEN
    IF o.x = 0 THEN o.x = 2
    x = o.par.x + o.x: y = o.par.y + o.y
    COLOR 0, 7
    IF o.nam THEN
        a$ = idetxt(o.nam)
        LOCATE y, x: idehPRINT a$ + ":"
        x = x + idehlen(a$) + 2
    END IF
    IF o.w = 0 THEN x2 = o.par.x + o.par.w - 1: o.w = x2 - x - 3
    idebox x, y - 1, o.w + 4, 3
    IF o.txt = 0 THEN o.txt = idenewtxt("")
    a$ = idetxt(o.txt)
    IF o.v1 > LEN(a$) THEN o.v1 = LEN(a$) 'new
    cx = o.v1

    IF LEN(a$) > o.w THEN
        IF o.foc = 0 THEN
            tx = o.v1 - o.w + 1
            IF tx < 1 THEN tx = 1
            a$ = MID$(a$, tx, o.w)
            cx = cx - tx + 1
        ELSE
            a$ = LEFT$(a$, o.w)
        END IF
    END IF

    x = x + 2
    LOCATE y, x: PRINT a$;
    IF o.foc = 0 THEN o.cx = x + cx: o.cy = y
    f = f + 1
END IF '#1

'#2: VERTICAL SCROLLING SELECTION BOX
IF o.typ = 2 THEN
    IF o.x = 0 THEN o.x = 2
    IF o.w = 0 THEN o.w = o.par.w - 2 - o.x
    IF o.h = 0 THEN o.h = o.par.h - 1 - o.y
    x = o.par.x + o.x: y = o.par.y + o.y
    COLOR 0, 7
    idebox x, y, o.w + 2, o.h + 2
    IF o.nam THEN
        a$ = idetxt(o.nam)
        w = o.w + 2
        m = w \ 2: IF w AND 1 THEN m = m + 1
        LOCATE y, x + m - 1 - ((idehlen(a$) + 2) - 1) \ 2: idehPRINT " " + a$ + " "
    END IF 'nam
    'display list items
    IF o.sel = 0 THEN o.sel = -1
    IF o.txt = 0 THEN o.txt = idenewtxt("")
    IF o.stx = 0 THEN o.stx = idenewtxt("")
    IF o.v1 = 0 THEN o.v1 = 1
    s = ABS(o.sel)
    IF s >= o.v1 + o.h THEN o.v1 = s - o.h + 1
    IF s < o.v1 THEN o.v1 = s
    IF o.foc <> 0 AND o.sel > 0 THEN o.sel = -o.sel
    a$ = idetxt(o.txt)
    n = 1
    y = 1
    v1 = o.v1
    a3$ = ""
    FOR i2 = 1 TO LEN(a$)
        a2$ = MID$(a$, i2, 1)
        IF a2$ <> sep THEN a3$ = a3$ + a2$
        IF a2$ = sep OR i2 = LEN(a$) THEN
            IF n < v1 THEN
                'skip
            ELSE
                IF y <= o.h THEN
                    IF o.sel = n THEN COLOR 7, 0 ELSE COLOR 0, 7
                    IF (o.sel = n OR -o.sel = n) AND o.foc = 0 THEN o.cx = o.par.x + o.x + 2: o.cy = o.par.y + o.y + y
                    LOCATE o.par.y + o.y + y, o.par.x + o.x + 1
                    a3$ = " " + a3$ + SPACE$(o.w)
                    a3$ = LEFT$(a3$, o.w)
                    PRINT a3$;
                    y = y + 1
                END IF
            END IF
            n = n + 1
            a3$ = ""
        END IF
    NEXT
    o.num = n - 1

    tnum = o.num
    tsel = ABS(o.sel)

    q = idevbar(o.par.x + o.x + o.w + 1, o.par.y + o.y + 1, o.h, tsel, tnum)

    f = f + 1
END IF '#2

'#3: ACTION BUTTONS
IF o.typ = 3 THEN
    IF o.x = 0 THEN o.x = 2
    IF o.w = 0 THEN o.w = o.par.w - o.x 'spanable width
    IF o.txt = 0 THEN o.txt = idenewtxt("OK")
    a$ = idetxt(o.txt)
    n = 1
    c = 0
    FOR i2 = 1 TO LEN(a$)
        a2$ = MID$(a$, i2, 1)
        IF a2$ = CHR$(0) THEN
            n = n + 1
        ELSE
            IF a$ <> "#" THEN c = c + 1
        END IF
    NEXT
    w = o.w
    c = c + n * 4 'add characters for bracing < > buttons
    whitespace = w - c
    spacing = whitespace \ (n + 1)
    f2 = o.foc + 1
    IF f2 < 1 OR f2 > n THEN
        IF o.def THEN f2 = o.def
    END IF
    n2 = 1
    a3$ = ""
    LOCATE o.par.y + o.y, o.par.x + o.x
    x = o.par.x + o.x
    COLOR 0, 7
    FOR i2 = 1 TO LEN(a$)
        a2$ = MID$(a$, i2, 1)
        IF a2$ <> CHR$(0) THEN a3$ = a3$ + a2$
        IF a2$ = CHR$(0) OR i2 = LEN(a$) THEN
            PRINT SPACE$(spacing);
            x = x + spacing
            IF f2 = n2 THEN COLOR 15, 7 ELSE COLOR 0, 7
            PRINT "< ";
            COLOR 0, 7: idehPRINT a3$
            IF f2 = n2 THEN COLOR 15, 7 ELSE COLOR 0, 7
            IF n2 = o.foc + 1 THEN
                o.cx = x + 2: o.cy = o.par.y + o.y
            END IF
            PRINT " >";
            COLOR 0, 7
            x = x + idehlen(a3$) + 4
            a3$ = ""
            n2 = n2 + 1
        END IF
    NEXT
    f = f + n
END IF '#3

'#4: CHECK BOX
IF o.typ = 4 THEN
    IF o.x = 0 THEN o.x = 2
    x = o.par.x + o.x: y = o.par.y + o.y
    LOCATE y, x
    COLOR 0, 7
    IF o.sel THEN
        PRINT "[X] ";
    ELSE
        PRINT "[ ] ";
    END IF
    IF o.nam THEN
        a$ = idetxt(o.nam)
        idehPRINT a$
    END IF
    IF o.foc = 0 THEN o.cx = x + 1: o.cy = y
    f = f + 1
END IF '#4

END SUB

SUB idedrawpar (p AS idedbptype)
COLOR 0, 7: ideboxshadow p.x, p.y, p.w + 2, p.h + 2
IF p.nam THEN
    x = LEN(idetxt(p.nam)) + 2
    COLOR 0, 7: LOCATE p.y, (idewx \ 2) - (x - 1) \ 2: PRINT " " + idetxt(p.nam) + " ";
END IF
END SUB

SUB ideerrormessage (mess$)


'-------- generic dialog box header --------
PCOPY 3, 0
PCOPY 0, 2
PCOPY 0, 1
SCREEN , , 1, 0
focus = 1
DIM p AS idedbptype
DIM o(1 TO 100) AS idedbotype
DIM oo AS idedbotype
DIM sep AS STRING * 1
sep = CHR$(0)
'-------- end of generic dialog box header --------

'-------- init --------
i = 0
idepar p, LEN(mess$) + 4, 4, ""
i = i + 1
o(i).typ = 3
o(i).y = 4
o(i).txt = idenewtxt("OK")
o(i).def = 1
'-------- end of init --------

'-------- generic init --------
FOR i = 1 TO 100: o(i).par = p: NEXT 'set parent info of objects
'-------- end of generic init --------

DO 'main loop

    '-------- generic display dialog box & objects --------
    idedrawpar p
    f = 1: cx = 0: cy = 0
    FOR i = 1 TO 100
        IF o(i).typ THEN
            'prepare object
            o(i).foc = focus - f 'focus offset
            o(i).cx = 0: o(i).cy = 0
            idedrawobj o(i), f 'display object
            IF o(i).cx THEN cx = o(i).cx: cy = o(i).cy
        END IF
    NEXT i
    lastfocus = f - 1
    '-------- end of generic display dialog box & objects --------

    '-------- custom display changes --------
    COLOR 0, 7: LOCATE p.y + 2, p.x + 3: PRINT mess$;
    '-------- end of custom display changes --------

    'update visual page and cursor position
    PCOPY 1, 0
    IF cx THEN SCREEN , , 0, 0: LOCATE cy, cx, 1: SCREEN , , 1, 0

    '-------- read input --------
    change = 0
    DO
        getxymouse
        mx = mousex: my = mousey: mb = mousebutton1
        IF mb <> 0 AND omb = 0 THEN mousedown = 1: change = 1
        IF mb = 0 AND omb <> 0 THEN mouseup = 1: change = 1
        IF mb THEN change = 1
        omb = mb
        k$ = INKEY$: IF LEN(k$) THEN change = 1
        'DEF SEG = 0: alt = PEEK(&H417) AND 8
        alt = 8
        IF alt <> oldalt THEN change = 1
        oldalt = alt

        IF change = 0 THEN _LIMIT 16
    LOOP UNTIL change
    SCREEN , , 0, 0: LOCATE , , 0: SCREEN , , 1, 0
    IF alt THEN idehl = 1 ELSE idehl = 0
    'convert "alt+letter" scancode to letter's ASCII character
    altletter$ = ""
    IF alt THEN
        IF LEN(k$) = 2 THEN
            k = ASC(RIGHT$(k$, 1))
            FOR c = 65 TO 90
                IF k = idealtcode(c) THEN
                    altletter$ = CHR$(c)
                    EXIT FOR
                END IF
            NEXT
        END IF
    END IF
    IF UCASE$(k$) = "Y" THEN altletter$ = "Y"
    IF UCASE$(k$) = "N" THEN altletter$ = "N"

    '-------- end of read input --------

    '-------- generic input response --------
    info = 0
    IF k$ = "" THEN k$ = CHR$(255)
    IF k$ = CHR$(9) THEN focus = focus + 1
    IF k$ = CHR$(0) + CHR$(15) THEN focus = focus - 1
    IF focus < 1 THEN focus = lastfocus
    IF focus > lastfocus THEN focus = 1
    f = 1
    FOR i = 1 TO 100
        t = o(i).typ
        IF t THEN
            focusoffset = focus - f
            ideupdateobj o(i), focus, f, focusoffset, k$, altletter$, mb, mousedown, mouseup, mx, my, info
        END IF
    NEXT
    '-------- end of generic input response --------

    IF k$ = CHR$(27) THEN
        EXIT SUB
    END IF

    IF info THEN
        EXIT SUB
    END IF

    'end of custom controls

    mousedown = 0
    mouseup = 0
LOOP


END SUB

FUNCTION idefileexists$
'-------- generic dialog box header --------
PCOPY 3, 0
PCOPY 0, 2
PCOPY 0, 1
SCREEN , , 1, 0
focus = 1
DIM p AS idedbptype
DIM o(1 TO 100) AS idedbotype
DIM oo AS idedbotype
DIM sep AS STRING * 1
sep = CHR$(0)
'-------- end of generic dialog box header --------

'-------- init --------
i = 0
'idepar p, 30, 6, "File already exists. Overwrite?"
idepar p, 35, 4, ""
i = i + 1
o(i).typ = 3
o(i).y = 4
o(i).txt = idenewtxt("#Yes" + sep + "#No")
o(i).def = 1
'-------- end of init --------

'-------- generic init --------
FOR i = 1 TO 100: o(i).par = p: NEXT 'set parent info of objects
'-------- end of generic init --------

DO 'main loop

    '-------- generic display dialog box & objects --------
    idedrawpar p
    f = 1: cx = 0: cy = 0
    FOR i = 1 TO 100
        IF o(i).typ THEN
            'prepare object
            o(i).foc = focus - f 'focus offset
            o(i).cx = 0: o(i).cy = 0
            idedrawobj o(i), f 'display object
            IF o(i).cx THEN cx = o(i).cx: cy = o(i).cy
        END IF
    NEXT i
    lastfocus = f - 1
    '-------- end of generic display dialog box & objects --------

    '-------- custom display changes --------
    COLOR 0, 7: LOCATE p.y + 2, p.x + 3: PRINT "File already exists. Overwrite?";
    '-------- end of custom display changes --------

    'update visual page and cursor position
    PCOPY 1, 0
    IF cx THEN SCREEN , , 0, 0: LOCATE cy, cx, 1: SCREEN , , 1, 0

    '-------- read input --------
    change = 0
    DO
        getxymouse
        mx = mousex: my = mousey: mb = mousebutton1
        IF mb <> 0 AND omb = 0 THEN mousedown = 1: change = 1
        IF mb = 0 AND omb <> 0 THEN mouseup = 1: change = 1
        IF mb THEN change = 1
        omb = mb
        k$ = INKEY$: IF LEN(k$) THEN change = 1
        'DEF SEG = 0: alt = PEEK(&H417) AND 8
        alt = 8
        IF alt <> oldalt THEN change = 1
        oldalt = alt

        IF change = 0 THEN _LIMIT 16
    LOOP UNTIL change
    SCREEN , , 0, 0: LOCATE , , 0: SCREEN , , 1, 0
    IF alt THEN idehl = 1 ELSE idehl = 0
    'convert "alt+letter" scancode to letter's ASCII character
    altletter$ = ""
    IF alt THEN
        IF LEN(k$) = 2 THEN
            k = ASC(RIGHT$(k$, 1))
            FOR c = 65 TO 90
                IF k = idealtcode(c) THEN
                    altletter$ = CHR$(c)
                    EXIT FOR
                END IF
            NEXT
        END IF
    END IF
    IF UCASE$(k$) = "Y" THEN altletter$ = "Y"
    IF UCASE$(k$) = "N" THEN altletter$ = "N"

    '-------- end of read input --------

    '-------- generic input response --------
    info = 0
    IF k$ = "" THEN k$ = CHR$(255)
    IF k$ = CHR$(9) THEN focus = focus + 1
    IF k$ = CHR$(0) + CHR$(15) THEN focus = focus - 1
    IF focus < 1 THEN focus = lastfocus
    IF focus > lastfocus THEN focus = 1
    f = 1
    FOR i = 1 TO 100
        t = o(i).typ
        IF t THEN
            focusoffset = focus - f
            ideupdateobj o(i), focus, f, focusoffset, k$, altletter$, mb, mousedown, mouseup, mx, my, info
        END IF
    NEXT
    '-------- end of generic input response --------

    IF k$ = CHR$(27) THEN
        idefileexists$ = "N"
        EXIT FUNCTION
    END IF

    IF info THEN
        IF info = 1 THEN idefileexists$ = "Y" ELSE idefileexists$ = "N"
        EXIT FUNCTION
    END IF

    'end of custom controls
    mousedown = 0
    mouseup = 0
LOOP


END FUNCTION

FUNCTION idefind$


'-------- generic dialog box header --------
PCOPY 0, 2
PCOPY 0, 1
SCREEN , , 1, 0
focus = 1
DIM p AS idedbptype
DIM o(1 TO 100) AS idedbotype
DIM oo AS idedbotype
DIM sep AS STRING * 1
sep = CHR$(0)
'-------- end of generic dialog box header --------

'-------- init --------

'built initial search string
IF ideselect THEN
    IF ideselecty1 = idecy THEN 'single line selected
        a$ = idegetline(idecy)
        a2$ = ""
        sx1 = ideselectx1: sx2 = idecx
        IF sx2 < sx1 THEN SWAP sx1, sx2
        FOR x = sx1 TO sx2 - 1
            IF x <= LEN(a$) THEN a2$ = a2$ + MID$(a$, x, 1) ELSE a2$ = a2$ + " "
        NEXT
    END IF
END IF
IF a2$ = "" THEN
    a2$ = idefindtext
END IF


i = 0
idepar p, 60, 8, "Find"
i = i + 1
o(i).typ = 1
o(i).y = 2
o(i).nam = idenewtxt("#Find What")
o(i).txt = idenewtxt(a2$)
o(i).v1 = LEN(a2$)



i = i + 1
o(i).typ = 4 'check box
o(i).y = 5
o(i).nam = idenewtxt("#Match Upper/Lowercase")
o(i).sel = idefindcasesens
i = i + 1
o(i).typ = 4 'check box
o(i).y = 6
o(i).nam = idenewtxt("#Whole Word")
o(i).sel = idefindwholeword
i = i + 1
o(i).typ = 3
o(i).y = 8
o(i).txt = idenewtxt("OK" + sep + "#Cancel")
o(i).def = 1
'-------- end of init --------

'-------- generic init --------
FOR i = 1 TO 100: o(i).par = p: NEXT 'set parent info of objects
'-------- end of generic init --------

DO 'main loop


    '-------- generic display dialog box & objects --------
    idedrawpar p
    f = 1: cx = 0: cy = 0
    FOR i = 1 TO 100
        IF o(i).typ THEN

            'prepare object
            o(i).foc = focus - f 'focus offset
            o(i).cx = 0: o(i).cy = 0
            idedrawobj o(i), f 'display object
            IF o(i).cx THEN cx = o(i).cx: cy = o(i).cy
        END IF
    NEXT i
    lastfocus = f - 1
    '-------- end of generic display dialog box & objects --------

    '-------- custom display changes --------
    '-------- end of custom display changes --------

    'update visual page and cursor position
    PCOPY 1, 0
    IF cx THEN SCREEN , , 0, 0: LOCATE cy, cx, 1: SCREEN , , 1, 0

    '-------- read input --------
    change = 0
    DO
        getxymouse
        mx = mousex: my = mousey: mb = mousebutton1
        IF mb <> 0 AND omb = 0 THEN mousedown = 1: change = 1
        IF mb = 0 AND omb <> 0 THEN mouseup = 1: change = 1
        IF mb THEN change = 1
        omb = mb
        k$ = INKEY$: IF LEN(k$) THEN change = 1
        DEF SEG = 0: alt = PEEK(&H417) AND 8: IF alt <> oldalt THEN change = 1
        oldalt = alt

        IF change = 0 THEN _LIMIT 16
    LOOP UNTIL change
    SCREEN , , 0, 0: LOCATE , , 0: SCREEN , , 1, 0
    IF alt THEN idehl = 1 ELSE idehl = 0
    'convert "alt+letter" scancode to letter's ASCII character
    altletter$ = ""
    IF alt THEN
        IF LEN(k$) = 2 THEN
            k = ASC(RIGHT$(k$, 1))
            FOR c = 65 TO 90
                IF k = idealtcode(c) THEN
                    altletter$ = CHR$(c)
                    EXIT FOR
                END IF
            NEXT
        END IF
    END IF
    '-------- end of read input --------

    '-------- generic input response --------
    info = 0
    IF k$ = "" THEN k$ = CHR$(255)
    IF k$ = CHR$(9) THEN focus = focus + 1
    IF k$ = CHR$(0) + CHR$(15) THEN focus = focus - 1
    IF focus < 1 THEN focus = lastfocus
    IF focus > lastfocus THEN focus = 1
    f = 1
    FOR i = 1 TO 100
        t = o(i).typ
        IF t THEN
            focusoffset = focus - f
            ideupdateobj o(i), focus, f, focusoffset, k$, altletter$, mb, mousedown, mouseup, mx, my, info
        END IF
    NEXT
    '-------- end of generic input response --------

    'specific post controls

    IF k$ = CHR$(27) OR (focus = 5 AND info <> 0) THEN
        idefind$ = "C"
        EXIT FUNCTION
    END IF

    IF k$ = CHR$(13) OR (focus = 4 AND info <> 0) THEN
        idefindcasesens = o(2).sel
        idefindwholeword = o(3).sel
        s$ = idetxt(o(1).txt)
        idefindtext$ = s$

        s$ = idefindtext$
        IF idefindcasesens = 0 THEN s$ = UCASE$(s$)
        start = idecy
        y = start

        idefindnext:
        l$ = idegetline(y)
        IF idefindcasesens = 0 THEN l$ = UCASE$(l$)

        IF y = start THEN
            IF looped = 1 THEN
                IF LEN(l$) > idecx THEN l$ = LEFT$(l$, idecx)
            ELSE
                IF LEN(l$) > idecx THEN l$ = STRING$(idecx, 255) + RIGHT$(l$, LEN(l$) - idecx) ELSE l$ = ""
            END IF
        END IF

        x1 = 1
        idefindagain:
        x = INSTR(x1, l$, s$)

        IF x THEN
            IF idefindwholeword THEN
                whole = 1
                IF x > 1 THEN
                    c = ASC(UCASE$(MID$(l$, x - 1, 1)))
                    IF c >= 65 AND c <= 90 THEN whole = 0
                    IF c >= 48 AND c <= 57 THEN whole = 0
                END IF
                IF x + LEN(s$) <= LEN(l$) THEN
                    c = ASC(UCASE$(MID$(l$, x + LEN(s$), 1)))
                    IF c >= 65 AND c <= 90 THEN whole = 0
                    IF c >= 48 AND c <= 57 THEN whole = 0
                END IF
                IF whole = 0 THEN
                    x1 = x + 1
                    x = 0
                    IF x1 <= LEN(l$) THEN GOTO idefindagain
                END IF
            END IF
        END IF

        IF x THEN
            ideselect = 1
            idecx = x: idecy = y
            ideselectx1 = x + LEN(s$): ideselecty1 = y
            EXIT FUNCTION
        END IF

        y = y + 1
        IF y = start + 1 AND looped = 1 THEN
            idenomatch

            EXIT FUNCTION
        END IF
        IF y > iden THEN y = 1: looped = 1

        GOTO idefindnext
    END IF

    'end of custom controls



    mousedown = 0
    mouseup = 0
LOOP
END FUNCTION

SUB idefindagain

s$ = idefindtext$
IF idefindcasesens = 0 THEN s$ = UCASE$(s$)
start = idecy
y = start

idefindnext2:
l$ = idegetline(y)
IF idefindcasesens = 0 THEN l$ = UCASE$(l$)

IF y = start THEN
    IF looped = 1 THEN
        IF LEN(l$) > idecx THEN l$ = LEFT$(l$, idecx)
    ELSE
        IF LEN(l$) > idecx THEN l$ = STRING$(idecx, 255) + RIGHT$(l$, LEN(l$) - idecx) ELSE l$ = ""
    END IF
END IF

x1 = 1
idefindagain2:
x = INSTR(x1, l$, s$)

IF x THEN
    IF idefindwholeword THEN
        whole = 1
        IF x > 1 THEN
            c = ASC(UCASE$(MID$(l$, x - 1, 1)))
            IF c >= 65 AND c <= 90 THEN whole = 0
            IF c >= 48 AND c <= 57 THEN whole = 0
        END IF
        IF x + LEN(s$) <= LEN(l$) THEN
            c = ASC(UCASE$(MID$(l$, x + LEN(s$), 1)))
            IF c >= 65 AND c <= 90 THEN whole = 0
            IF c >= 48 AND c <= 57 THEN whole = 0
        END IF
        IF whole = 0 THEN
            x1 = x + 1
            x = 0
            IF x1 <= LEN(l$) THEN GOTO idefindagain2
        END IF
    END IF
END IF

IF x THEN
    ideselect = 1
    idecx = x: idecy = y
    ideselectx1 = x + LEN(s$): ideselecty1 = y
    EXIT SUB
END IF

y = y + 1
IF y = start + 1 AND looped = 1 THEN
    idenomatch

    EXIT SUB
END IF
IF y > iden THEN y = 1: looped = 1

GOTO idefindnext2

END SUB

FUNCTION idegetline$ (i)
IF i <> -1 THEN idegotoline i
idegetline$ = MID$(idet$, ideli + 4, CVL(MID$(idet$, ideli, 4)))
END FUNCTION

SUB idegotoline (i)
IF idel = i THEN EXIT SUB
IF i < 1 THEN ERROR 5
'scan backwards
IF i < idel THEN
    DO
        idel = idel - 1
        ideli = ideli - CVL(MID$(idet$, ideli - 4, 4)) - 8
    LOOP UNTIL idel = i
    EXIT SUB
END IF
'assume scan forwards
DO
    IF idel = iden THEN idet$ = idet$ + MKL$(0) + MKL$(0): iden = iden + 1 'insert blank line at end?
    idel = idel + 1
    ideli = ideli + CVL(MID$(idet$, ideli, 4)) + 8
LOOP UNTIL idel = i
END SUB

FUNCTION idehbar (x, y, h, i2, n2)
i = i2: n = n2

'COLOR 0, 7
'LOCATE y, x: PRINT CHR$(27);
'LOCATE y, x + w - 1: PRINT CHR$(26);
'FOR x2 = x + 1 TO x + w - 2
'LOCATE y, x2: PRINT "°";
'NEXT
'IF w > 3 THEN
'p2! = w - 2 - .00001
'x2 = x + 1 + INT(p2! * p!)
'LOCATE y, x2: PRINT "Û";
'END IF


'h is size in characters (inc. arrows)

'draw background & arrows
COLOR 0, 7
LOCATE y, x: PRINT CHR$(27);
LOCATE y, x + h - 1: PRINT CHR$(26);
FOR x2 = x + 1 TO x + h - 2
    LOCATE y, x2: PRINT "°";
NEXT

'draw slider

IF n < 1 THEN n = 1
IF i < 1 THEN i = 1
IF i > n THEN i = n

IF h = 2 THEN
    idehbar = x 'not position for slider exists
    EXIT FUNCTION
END IF

IF h = 3 THEN
    idehbar = x + 1 'dummy value
    'no slider
    EXIT FUNCTION
END IF

IF h = 4 THEN
    IF n = 1 THEN
        idehbar = x + 1 'dummy value
        'no slider required for 1 item
        EXIT FUNCTION
    ELSE
        'show whichever is closer of the two positions
        p! = (i - 1) / (n - 1)
        IF p! < .5 THEN x2 = x + 1 ELSE x2 = x + 2
        LOCATE y, x2: PRINT "Û";
        idehbar = x2
        EXIT FUNCTION
    END IF
END IF

IF h > 4 THEN
    IF n = 1 THEN
        idehbar = x + h \ 4 'dummy value
        'no slider required for 1 item
        EXIT FUNCTION
    END IF
    IF i = 1 THEN
        x2 = x + 1
        LOCATE y, x2: PRINT "Û";
        idehbar = x2
        EXIT FUNCTION
    END IF
    IF i = n THEN
        x2 = x + h - 2
        LOCATE y, x2: PRINT "Û";
        idehbar = x2
        EXIT FUNCTION
    END IF
    'between i=1 and i=n
    p! = (i - 1) / (n - 1)
    p! = p! * (h - 4)
    x2 = x + 2 + INT(p!)
    LOCATE y, x2: PRINT "Û";
    idehbar = x2
    EXIT FUNCTION
END IF


END FUNCTION

FUNCTION idehlen (a$)
IF INSTR(a$, "#") THEN idehlen = LEN(a$) - 1 ELSE idehlen = LEN(a$)
END FUNCTION

SUB idehPRINT (a$)
COLOR 0, 7
FOR i = 1 TO LEN(a$)
    c$ = MID$(a$, i, 1)
    IF c$ = "#" THEN
        IF idehl THEN COLOR 15, 7
    ELSE
        PRINT c$;: COLOR 0, 7
    END IF
NEXT
END SUB

SUB ideinsline (i, text$)
'note: cursor remains on line i

text$ = RTRIM$(text$)

IF i = -1 THEN i = idel
'if at end, use idesetline
IF i > iden THEN
    idesetline i, text$
    EXIT SUB
END IF
idegotoline i
'insert line
textlen = LEN(text$)
idet$ = LEFT$(idet$, ideli - 1) + MKL$(textlen) + text$ + MKL$(textlen) + RIGHT$(idet$, LEN(idet$) - ideli + 1)
iden = iden + 1
END SUB

SUB idenewsf (sf AS STRING)


'-------- generic dialog box header --------
PCOPY 0, 2
PCOPY 0, 1
SCREEN , , 1, 0
focus = 1
DIM p AS idedbptype
DIM o(1 TO 100) AS idedbotype
DIM oo AS idedbotype
DIM sep AS STRING * 1
sep = CHR$(0)
'-------- end of generic dialog box header --------

'-------- init --------

'built initial name if word selected
IF ideselect THEN
    IF ideselecty1 = idecy THEN 'single line selected
        a$ = idegetline(idecy)
        a2$ = ""
        sx1 = ideselectx1: sx2 = idecx
        IF sx2 < sx1 THEN SWAP sx1, sx2
        FOR x = sx1 TO sx2 - 1
            IF x <= LEN(a$) THEN a2$ = a2$ + MID$(a$, x, 1) ELSE a2$ = a2$ + " "
        NEXT
    END IF
END IF

i = 0

idepar p, 60, 5, "New " + sf$

i = i + 1
o(i).typ = 1
o(i).y = 2
o(i).nam = idenewtxt("#Name")
o(i).txt = idenewtxt(a2$)
o(i).v1 = LEN(a2$)

i = i + 1
o(i).typ = 3
o(i).y = 5
o(i).txt = idenewtxt("OK" + sep + "#Cancel")
o(i).def = 1
'-------- end of init --------

'-------- generic init --------
FOR i = 1 TO 100: o(i).par = p: NEXT 'set parent info of objects
'-------- end of generic init --------

DO 'main loop


    '-------- generic display dialog box & objects --------
    idedrawpar p
    f = 1: cx = 0: cy = 0
    FOR i = 1 TO 100
        IF o(i).typ THEN

            'prepare object
            o(i).foc = focus - f 'focus offset
            o(i).cx = 0: o(i).cy = 0
            idedrawobj o(i), f 'display object
            IF o(i).cx THEN cx = o(i).cx: cy = o(i).cy
        END IF
    NEXT i
    lastfocus = f - 1
    '-------- end of generic display dialog box & objects --------

    '-------- custom display changes --------
    '-------- end of custom display changes --------

    'update visual page and cursor position
    PCOPY 1, 0
    IF cx THEN SCREEN , , 0, 0: LOCATE cy, cx, 1: SCREEN , , 1, 0

    '-------- read input --------
    change = 0
    DO
        getxymouse
        mx = mousex: my = mousey: mb = mousebutton1
        IF mb <> 0 AND omb = 0 THEN mousedown = 1: change = 1
        IF mb = 0 AND omb <> 0 THEN mouseup = 1: change = 1
        IF mb THEN change = 1
        omb = mb
        k$ = INKEY$: IF LEN(k$) THEN change = 1
        DEF SEG = 0: alt = PEEK(&H417) AND 8: IF alt <> oldalt THEN change = 1
        oldalt = alt

        IF change = 0 THEN _LIMIT 16
    LOOP UNTIL change
    SCREEN , , 0, 0: LOCATE , , 0: SCREEN , , 1, 0
    IF alt THEN idehl = 1 ELSE idehl = 0
    'convert "alt+letter" scancode to letter's ASCII character
    altletter$ = ""
    IF alt THEN
        IF LEN(k$) = 2 THEN
            k = ASC(RIGHT$(k$, 1))
            FOR c = 65 TO 90
                IF k = idealtcode(c) THEN
                    altletter$ = CHR$(c)
                    EXIT FOR
                END IF
            NEXT
        END IF
    END IF
    '-------- end of read input --------

    '-------- generic input response --------
    info = 0
    IF k$ = "" THEN k$ = CHR$(255)
    IF k$ = CHR$(9) THEN focus = focus + 1
    IF k$ = CHR$(0) + CHR$(15) THEN focus = focus - 1
    IF focus < 1 THEN focus = lastfocus
    IF focus > lastfocus THEN focus = 1
    f = 1
    FOR i = 1 TO 100
        t = o(i).typ
        IF t THEN
            focusoffset = focus - f
            ideupdateobj o(i), focus, f, focusoffset, k$, altletter$, mb, mousedown, mouseup, mx, my, info
        END IF
    NEXT
    '-------- end of generic input response --------

    'specific post controls

    IF k$ = CHR$(27) OR (focus = 3 AND info <> 0) THEN
        EXIT SUB
    END IF

    IF k$ = CHR$(13) OR (focus = 2 AND info <> 0) THEN
        y = iden
        y = y + 1: idesetline y, ""
        y = y + 1: idesetline y, sf$ + " " + idetxt(o(1).txt)
        idesy = y
        y = y + 1: idesetline y, ""
        idecy = y
        y = y + 1: idesetline y, "END " + sf$
        idecx = 1: idesx = 1
        idechangemade = 1
        EXIT SUB
    END IF

    'end of custom controls

    mousedown = 0
    mouseup = 0
LOOP



END SUB

FUNCTION idenewtxt (a$)
idetxtlast = idetxtlast + 1
idetxt$(idetxtlast) = a$
idenewtxt = idetxtlast
END FUNCTION

SUB idenomatch

'-------- generic dialog box header --------
PCOPY 3, 0
PCOPY 0, 2
PCOPY 0, 1
SCREEN , , 1, 0
focus = 1
DIM p AS idedbptype
DIM o(1 TO 100) AS idedbotype
DIM oo AS idedbotype
DIM sep AS STRING * 1
sep = CHR$(0)
'-------- end of generic dialog box header --------

'-------- init --------
i = 0
idepar p, 19, 4, ""
i = i + 1
o(i).typ = 3
o(i).y = 4
o(i).txt = idenewtxt("OK")
o(i).def = 1
'-------- end of init --------

'-------- generic init --------
FOR i = 1 TO 100: o(i).par = p: NEXT 'set parent info of objects
'-------- end of generic init --------

DO 'main loop

    '-------- generic display dialog box & objects --------
    idedrawpar p
    f = 1: cx = 0: cy = 0
    FOR i = 1 TO 100
        IF o(i).typ THEN
            'prepare object
            o(i).foc = focus - f 'focus offset
            o(i).cx = 0: o(i).cy = 0
            idedrawobj o(i), f 'display object
            IF o(i).cx THEN cx = o(i).cx: cy = o(i).cy
        END IF
    NEXT i
    lastfocus = f - 1
    '-------- end of generic display dialog box & objects --------

    '-------- custom display changes --------
    COLOR 0, 7: LOCATE p.y + 2, p.x + 3: PRINT "Match not found";
    '-------- end of custom display changes --------

    'update visual page and cursor position
    PCOPY 1, 0
    IF cx THEN SCREEN , , 0, 0: LOCATE cy, cx, 1: SCREEN , , 1, 0

    '-------- read input --------
    change = 0
    DO
        getxymouse
        mx = mousex: my = mousey: mb = mousebutton1
        IF mb <> 0 AND omb = 0 THEN mousedown = 1: change = 1
        IF mb = 0 AND omb <> 0 THEN mouseup = 1: change = 1
        IF mb THEN change = 1
        omb = mb
        k$ = INKEY$: IF LEN(k$) THEN change = 1
        'DEF SEG = 0: alt = PEEK(&H417) AND 8
        alt = 8
        IF alt <> oldalt THEN change = 1
        oldalt = alt

        IF change = 0 THEN _LIMIT 16
    LOOP UNTIL change
    SCREEN , , 0, 0: LOCATE , , 0: SCREEN , , 1, 0
    IF alt THEN idehl = 1 ELSE idehl = 0
    'convert "alt+letter" scancode to letter's ASCII character
    altletter$ = ""
    IF alt THEN
        IF LEN(k$) = 2 THEN
            k = ASC(RIGHT$(k$, 1))
            FOR c = 65 TO 90
                IF k = idealtcode(c) THEN
                    altletter$ = CHR$(c)
                    EXIT FOR
                END IF
            NEXT
        END IF
    END IF
    IF UCASE$(k$) = "Y" THEN altletter$ = "Y"
    IF UCASE$(k$) = "N" THEN altletter$ = "N"

    '-------- end of read input --------

    '-------- generic input response --------
    info = 0
    IF k$ = "" THEN k$ = CHR$(255)
    IF k$ = CHR$(9) THEN focus = focus + 1
    IF k$ = CHR$(0) + CHR$(15) THEN focus = focus - 1
    IF focus < 1 THEN focus = lastfocus
    IF focus > lastfocus THEN focus = 1
    f = 1
    FOR i = 1 TO 100
        t = o(i).typ
        IF t THEN
            focusoffset = focus - f
            ideupdateobj o(i), focus, f, focusoffset, k$, altletter$, mb, mousedown, mouseup, mx, my, info
        END IF
    NEXT
    '-------- end of generic input response --------

    IF k$ = CHR$(27) THEN
        EXIT SUB
    END IF

    IF info THEN
        EXIT SUB
    END IF

    'end of custom controls

    mousedown = 0
    mouseup = 0
LOOP

END SUB

FUNCTION ideopen$

'-------- generic dialog box header --------
PCOPY 0, 2
PCOPY 0, 1
SCREEN , , 1, 0
focus = 1
DIM p AS idedbptype
DIM o(1 TO 100) AS idedbotype
DIM oo AS idedbotype
DIM sep AS STRING * 1
sep = CHR$(0)
'-------- end of generic dialog box header --------

'-------- init --------
path$ = idepath$
filelist$ = idezfilelist$(path$)
pathlist$ = idezpathlist$(path$)

i = 0
idepar p, 70, idewy - 7, "Open"
i = i + 1
o(i).typ = 1
o(i).y = 2
o(i).nam = idenewtxt("File #Name")
i = i + 1
o(i).typ = 2
o(i).y = 5
o(i).w = 32: o(i).h = idewy - 14
o(i).nam = idenewtxt("#Files")
o(i).txt = idenewtxt(filelist$): filelist$ = ""
i = i + 1
o(i).typ = 2
o(i).x = 37: o(i).y = 5
o(i).w = 31: o(i).h = idewy - 14
o(i).nam = idenewtxt("#Paths")
o(i).txt = idenewtxt(pathlist$): pathlist$ = ""
i = i + 1
o(i).typ = 3
o(i).y = idewy - 7
o(i).txt = idenewtxt("OK" + sep + "#Cancel")
o(i).def = 1
'-------- end of init --------

'-------- generic init --------
FOR i = 1 TO 100: o(i).par = p: NEXT 'set parent info of objects
'-------- end of generic init --------

DO 'main loop

    '-------- generic display dialog box & objects --------
    idedrawpar p
    f = 1: cx = 0: cy = 0
    FOR i = 1 TO 100
        IF o(i).typ THEN
            'prepare object
            o(i).foc = focus - f 'focus offset
            o(i).cx = 0: o(i).cy = 0
            idedrawobj o(i), f 'display object
            IF o(i).cx THEN cx = o(i).cx: cy = o(i).cy
        END IF
    NEXT i
    lastfocus = f - 1
    '-------- end of generic display dialog box & objects --------

    '-------- custom display changes --------
    COLOR 0, 7: LOCATE p.y + 4, p.x + 2: PRINT "Path: ";
    a$ = path$
    w = p.w - 8
    IF LEN(a$) > w - 3 THEN a$ = "úúú" + RIGHT$(a$, w - 3)
    PRINT a$;
    '-------- end of custom display changes --------

    'update visual page and cursor position
    PCOPY 1, 0
    IF cx THEN SCREEN , , 0, 0: LOCATE cy, cx, 1: SCREEN , , 1, 0

    '-------- read input --------
    change = 0
    DO
        getxymouse
        mx = mousex: my = mousey: mb = mousebutton1
        IF mb <> 0 AND omb = 0 THEN mousedown = 1: change = 1
        IF mb = 0 AND omb <> 0 THEN mouseup = 1: change = 1
        IF mb THEN change = 1
        omb = mb
        k$ = INKEY$: IF LEN(k$) THEN change = 1
        DEF SEG = 0: alt = PEEK(&H417) AND 8: IF alt <> oldalt THEN change = 1
        oldalt = alt

        IF change = 0 THEN _LIMIT 16
    LOOP UNTIL change
    SCREEN , , 0, 0: LOCATE , , 0: SCREEN , , 1, 0
    IF alt THEN idehl = 1 ELSE idehl = 0
    'convert "alt+letter" scancode to letter's ASCII character
    altletter$ = ""
    IF alt THEN
        IF LEN(k$) = 2 THEN
            k = ASC(RIGHT$(k$, 1))
            FOR c = 65 TO 90
                IF k = idealtcode(c) THEN
                    altletter$ = CHR$(c)
                    EXIT FOR
                END IF
            NEXT
        END IF
    END IF
    '-------- end of read input --------

    '-------- generic input response --------
    info = 0
    IF k$ = "" THEN k$ = CHR$(255)
    IF k$ = CHR$(9) THEN focus = focus + 1
    IF k$ = CHR$(0) + CHR$(15) THEN focus = focus - 1
    IF focus < 1 THEN focus = lastfocus
    IF focus > lastfocus THEN focus = 1
    f = 1
    FOR i = 1 TO 100
        t = o(i).typ
        IF t THEN
            focusoffset = focus - f
            ideupdateobj o(i), focus, f, focusoffset, k$, altletter$, mb, mousedown, mouseup, mx, my, info
        END IF
    NEXT
    '-------- end of generic input response --------










    'specific post controls


    IF k$ = CHR$(27) OR (focus = 5 AND info <> 0) THEN
        ideopen$ = "C"
        EXIT FUNCTION
    END IF

    IF idetxt(o(2).stx) <> "" THEN
        idetxt(o(1).txt) = idetxt(o(2).stx)
        o(1).v1 = LEN(idetxt(o(1).txt))
    END IF

    IF focus = 3 THEN
        IF k$ = CHR$(13) OR info = 1 THEN

            path$ = idezchangepath(path$, idetxt(o(3).stx))
            idetxt(o(2).txt) = idezfilelist$(path$)
            idetxt(o(3).txt) = idezpathlist$(path$)

            o(2).sel = -1
            o(3).sel = 1
            IF info = 1 THEN o(3).sel = -1
            GOTO ideopenloop
        END IF
    END IF

    'load file
    IF k$ = CHR$(13) OR (info = 1 AND focus = 2) OR (focus = 4 AND info <> 0) THEN
        f$ = idetxt(o(1).txt)

        'change path?
        IF f$ = ".." OR f$ = "." THEN f$ = f$ + idepathsep$
        IF RIGHT$(f$, 1) = idepathsep$ THEN
            path$ = idezgetfilepath$(path$, f$) 'note: path ending with pathsep needn't contain a file
            idetxt(o(1).txt) = ""
            idetxt(o(2).txt) = idezfilelist$(path$)
            o(2).sel = -1
            idetxt(o(3).txt) = idezpathlist$(path$)
            o(3).sel = -1
            GOTO ideopenloop
        END IF

        'add .bas if not given
        IF LCASE$(RIGHT$(f$, 4)) <> ".bas" THEN f$ = f$ + ".bas"
        'check/acquire file path
        path$ = idezgetfilepath$(path$, f$)
        'check file exists
        ideerror = 2
        OPEN path$ + idepathsep$ + f$ FOR INPUT AS #150: CLOSE #150
        'load file
        ideerror = 3
        idet$ = MKL$(0) + MKL$(0): idel = 1: ideli = 1: iden = 1
        idesx = 1
        idesy = 1
        idecx = 1
        idecy = 1
        ideselect = 0
        lineinput3load path$ + idepathsep$ + f$
        idet$ = SPACE$(LEN(lineinput3buffer) * 8)
        i2 = 1
        n = 0
        chrtab$ = CHR$(9)
        space1$ = " ": space2$ = "  ": space3$ = "   ": space4$ = "    "
        chr7$ = CHR$(7): chr11$ = CHR$(11): chr12$ = CHR$(12): chr28$ = CHR$(28): chr29$ = CHR$(29): chr30$ = CHR$(30): chr31$ = CHR$(31)
        DO
            a$ = lineinput3$
            l = LEN(a$)
            IF l THEN asca = ASC(a$) ELSE asca = -1
            IF asca <> 13 THEN
                IF asca <> -1 THEN
                    'fix tabs
                    ideopenfixtabs:
                    x = INSTR(a$, chrtab$)
                    IF x THEN
                        x2 = (x - 1) MOD 4
                        IF x2 = 0 THEN a$ = LEFT$(a$, x - 1) + space4$ + RIGHT$(a$, l - x): l = l + 3: GOTO ideopenfixtabs
                        IF x2 = 1 THEN a$ = LEFT$(a$, x - 1) + space3$ + RIGHT$(a$, l - x): l = l + 2: GOTO ideopenfixtabs
                        IF x2 = 2 THEN a$ = LEFT$(a$, x - 1) + space2$ + RIGHT$(a$, l - x): l = l + 1: GOTO ideopenfixtabs
                        IF x2 = 3 THEN a$ = LEFT$(a$, x - 1) + space1$ + RIGHT$(a$, l - x): GOTO ideopenfixtabs
                    END IF

'cull control characters
cullctrlchrs3:
for x=1 to len(a$)
if control_chr(asc(a$,x)) then
a$=LEFT$(a$, x - 1)+right$(a$,len(a$)-x)
goto cullctrlchrs3
end if
next

                END IF 'asca<>-1
                MID$(idet$, i2, l + 8) = MKL$(l) + a$ + MKL$(l): i2 = i2 + l + 8: n = n + 1
            END IF
        LOOP UNTIL asca = 13
        lineinput3buffer = ""
        iden = n: IF n = 0 THEN idet$ = MKL$(0) + MKL$(0): iden = 1 ELSE idet$ = LEFT$(idet$, i2 - 1)
        ideerror = 1
        ideprogname = f$: _TITLE ideprogname + " - QB64"
        idepath$ = path$
        EXIT FUNCTION
    END IF

    ideopenloop:

    'end of custom controls
    mousedown = 0
    mouseup = 0
LOOP
END FUNCTION

SUB idepar (par AS idedbptype, w, h, title$)
par.x = (idewx \ 2) - w \ 2
par.y = (idewy \ 2) - h \ 2
par.w = w
par.h = h
IF LEN(title$) THEN par.nam = idenewtxt(title$)
END SUB

FUNCTION iderestore$

'-------- generic dialog box header --------
PCOPY 3, 0
PCOPY 0, 2
PCOPY 0, 1
SCREEN , , 1, 0
focus = 1
DIM p AS idedbptype
DIM o(1 TO 100) AS idedbotype
DIM oo AS idedbotype
DIM sep AS STRING * 1
sep = CHR$(0)
'-------- end of generic dialog box header --------

'-------- init --------
i = 0
'idepar p, 30, 6, "File already exists. Overwrite?"
idepar p, 43, 4, ""
i = i + 1
o(i).typ = 3
o(i).y = 4
o(i).txt = idenewtxt("#Yes" + sep + "#No")
o(i).def = 1
'-------- end of init --------

'-------- generic init --------
FOR i = 1 TO 100: o(i).par = p: NEXT 'set parent info of objects
'-------- end of generic init --------

DO 'main loop

    '-------- generic display dialog box & objects --------
    idedrawpar p
    f = 1: cx = 0: cy = 0
    FOR i = 1 TO 100
        IF o(i).typ THEN
            'prepare object
            o(i).foc = focus - f 'focus offset
            o(i).cx = 0: o(i).cy = 0
            idedrawobj o(i), f 'display object
            IF o(i).cx THEN cx = o(i).cx: cy = o(i).cy
        END IF
    NEXT i
    lastfocus = f - 1
    '-------- end of generic display dialog box & objects --------

    '-------- custom display changes --------
    COLOR 0, 7: LOCATE p.y + 2, p.x + 3: PRINT "Recover program from auto-saved backup?";
    '-------- end of custom display changes --------

    'update visual page and cursor position
    PCOPY 1, 0
    IF cx THEN SCREEN , , 0, 0: LOCATE cy, cx, 1: SCREEN , , 1, 0

    '-------- read input --------
    change = 0
    DO
        getxymouse
        mx = mousex: my = mousey: mb = mousebutton1
        IF mb <> 0 AND omb = 0 THEN mousedown = 1: change = 1
        IF mb = 0 AND omb <> 0 THEN mouseup = 1: change = 1
        IF mb THEN change = 1
        omb = mb
        k$ = INKEY$: IF LEN(k$) THEN change = 1
        'DEF SEG = 0: alt = PEEK(&H417) AND 8
        alt = 8
        IF alt <> oldalt THEN change = 1
        oldalt = alt

        IF change = 0 THEN _LIMIT 16
    LOOP UNTIL change
    SCREEN , , 0, 0: LOCATE , , 0: SCREEN , , 1, 0
    IF alt THEN idehl = 1 ELSE idehl = 0
    'convert "alt+letter" scancode to letter's ASCII character
    altletter$ = ""
    IF alt THEN
        IF LEN(k$) = 2 THEN
            k = ASC(RIGHT$(k$, 1))
            FOR c = 65 TO 90
                IF k = idealtcode(c) THEN
                    altletter$ = CHR$(c)
                    EXIT FOR
                END IF
            NEXT
        END IF
    END IF
    IF UCASE$(k$) = "Y" THEN altletter$ = "Y"
    IF UCASE$(k$) = "N" THEN altletter$ = "N"

    '-------- end of read input --------

    '-------- generic input response --------
    info = 0
    IF k$ = "" THEN k$ = CHR$(255)
    IF k$ = CHR$(9) THEN focus = focus + 1
    IF k$ = CHR$(0) + CHR$(15) THEN focus = focus - 1
    IF focus < 1 THEN focus = lastfocus
    IF focus > lastfocus THEN focus = 1
    f = 1
    FOR i = 1 TO 100
        t = o(i).typ
        IF t THEN
            focusoffset = focus - f
            ideupdateobj o(i), focus, f, focusoffset, k$, altletter$, mb, mousedown, mouseup, mx, my, info
        END IF
    NEXT
    '-------- end of generic input response --------

    IF info THEN
        IF info = 1 THEN iderestore$ = "Y" ELSE iderestore$ = "N"
        EXIT FUNCTION
    END IF

    'end of custom controls
    mousedown = 0
    mouseup = 0
LOOP

END FUNCTION

SUB idesave (f$)
OPEN f$ FOR OUTPUT AS #150
FOR i = 1 TO iden
    a$ = idegetline(i)
    PRINT #150, a$
NEXT
CLOSE #150
ideunsaved = 0
END SUB

FUNCTION idesaveas$ (programname$)
'-------- generic dialog box header --------
PCOPY 0, 2
PCOPY 0, 1
SCREEN , , 1, 0
focus = 1
DIM p AS idedbptype
DIM o(1 TO 100) AS idedbotype
DIM oo AS idedbotype
DIM sep AS STRING * 1
sep = CHR$(0)
'-------- end of generic dialog box header --------

'-------- init --------
path$ = idepath$
pathlist$ = idezpathlist$(path$)

i = 0
idepar p, 48, idewy - 7, "Save As"

i = i + 1
o(i).typ = 1
o(i).y = 2
o(i).nam = idenewtxt("File #Name")
o(i).txt = idenewtxt(programname$)
o(i).v1 = LEN(programname$)

'i = i + 1
'o(i).typ = 2
'o(i).y = 5
'o(i).w = 32: o(i).h = 11
'o(i).nam = idenewtxt("#Files")
'o(i).txt = idenewtxt(filelist$): filelist$ = ""

i = i + 1
o(i).typ = 2
'o(i).x = 10:
o(i).y = 5
o(i).w = 44: o(i).h = idewy - 14
o(i).nam = idenewtxt("#Paths")
o(i).txt = idenewtxt(pathlist$): pathlist$ = ""

i = i + 1
o(i).typ = 3
o(i).y = idewy - 7
o(i).txt = idenewtxt("OK" + sep + "#Cancel")
o(i).def = 1
'-------- end of init --------

'-------- generic init --------
FOR i = 1 TO 100: o(i).par = p: NEXT 'set parent info of objects
'-------- end of generic init --------

DO 'main loop

    '-------- generic display dialog box & objects --------
    idedrawpar p
    f = 1: cx = 0: cy = 0
    FOR i = 1 TO 100
        IF o(i).typ THEN
            'prepare object
            o(i).foc = focus - f 'focus offset
            o(i).cx = 0: o(i).cy = 0
            idedrawobj o(i), f 'display object
            IF o(i).cx THEN cx = o(i).cx: cy = o(i).cy
        END IF
    NEXT i
    lastfocus = f - 1
    '-------- end of generic display dialog box & objects --------

    '-------- custom display changes --------
    COLOR 0, 7: LOCATE p.y + 4, p.x + 2: PRINT "Path: ";
    a$ = path$
    w = p.w - 8
    IF LEN(a$) > w - 3 THEN a$ = "úúú" + RIGHT$(a$, w - 3)
    PRINT a$;
    '-------- end of custom display changes --------

    'update visual page and cursor position
    PCOPY 1, 0
    IF cx THEN SCREEN , , 0, 0: LOCATE cy, cx, 1: SCREEN , , 1, 0

    '-------- read input --------
    change = 0
    DO
        getxymouse
        mx = mousex: my = mousey: mb = mousebutton1
        IF mb <> 0 AND omb = 0 THEN mousedown = 1: change = 1
        IF mb = 0 AND omb <> 0 THEN mouseup = 1: change = 1
        IF mb THEN change = 1
        omb = mb
        k$ = INKEY$: IF LEN(k$) THEN change = 1
        DEF SEG = 0: alt = PEEK(&H417) AND 8: IF alt <> oldalt THEN change = 1
        oldalt = alt

        IF change = 0 THEN _LIMIT 16
    LOOP UNTIL change
    SCREEN , , 0, 0: LOCATE , , 0: SCREEN , , 1, 0
    IF alt THEN idehl = 1 ELSE idehl = 0
    'convert "alt+letter" scancode to letter's ASCII character
    altletter$ = ""
    IF alt THEN
        IF LEN(k$) = 2 THEN
            k = ASC(RIGHT$(k$, 1))
            FOR c = 65 TO 90
                IF k = idealtcode(c) THEN
                    altletter$ = CHR$(c)
                    EXIT FOR
                END IF
            NEXT
        END IF
    END IF
    '-------- end of read input --------

    '-------- generic input response --------
    info = 0
    IF k$ = "" THEN k$ = CHR$(255)
    IF k$ = CHR$(9) THEN focus = focus + 1
    IF k$ = CHR$(0) + CHR$(15) THEN focus = focus - 1
    IF focus < 1 THEN focus = lastfocus
    IF focus > lastfocus THEN focus = 1
    f = 1
    FOR i = 1 TO 100
        t = o(i).typ
        IF t THEN
            focusoffset = focus - f
            ideupdateobj o(i), focus, f, focusoffset, k$, altletter$, mb, mousedown, mouseup, mx, my, info
        END IF
    NEXT
    '-------- end of generic input response --------

    IF k$ = CHR$(27) OR (focus = 4 AND info <> 0) THEN
        idesaveas$ = "C"
        EXIT FUNCTION
    END IF

    IF focus = 2 THEN
        IF k$ = CHR$(13) OR info = 1 THEN
            path$ = idezchangepath(path$, idetxt(o(2).stx))
            idetxt(o(2).txt) = idezpathlist$(path$)
            o(2).sel = 1
            IF info = 1 THEN o(2).sel = -1
        END IF
    END IF

    IF (k$ = CHR$(13) AND focus <> 2) OR (focus = 3 AND info <> 0) THEN
        f$ = idetxt(o(1).txt)

        'change path?
        IF f$ = ".." OR f$ = "." THEN f$ = f$ + idepathsep$
        IF RIGHT$(f$, 1) = idepathsep$ THEN
            path$ = idezgetfilepath$(path$, f$) 'note: path ending with pathsep needn't contain a file
            idetxt(o(1).txt) = ""
            idetxt(o(2).txt) = idezpathlist$(path$)
            o(2).sel = -1
            GOTO idesaveasloop
        END IF

        IF LCASE$(RIGHT$(f$, 4)) <> ".bas" THEN f$ = f$ + ".bas"
        path$ = idezgetfilepath$(path$, f$)
        ideerror = 3
        OPEN path$ + idepathsep$ + f$ FOR BINARY AS #150
        ideerror = 1
        IF LOF(150) THEN
            CLOSE #150
            a$ = idefileexists
            IF a$ = "N" THEN
                idesaveas$ = "C"
                EXIT FUNCTION 'user didn't agree to overwrite
            END IF
        ELSE
            CLOSE #150
        END IF
        ideprogname$ = f$: _TITLE ideprogname + " - QB64"
        idesave path$ + idepathsep$ + f$
        idepath$ = path$
        EXIT FUNCTION
    END IF

    idesaveasloop:

    'end of custom controls
    mousedown = 0
    mouseup = 0
LOOP

END FUNCTION

FUNCTION idesavenow$

'-------- generic dialog box header --------
PCOPY 3, 0
PCOPY 0, 2
PCOPY 0, 1
SCREEN , , 1, 0
focus = 1
DIM p AS idedbptype
DIM o(1 TO 100) AS idedbotype
DIM oo AS idedbotype
DIM sep AS STRING * 1
sep = CHR$(0)
'-------- end of generic dialog box header --------

'-------- init --------
i = 0
idepar p, 40, 4, ""
i = i + 1
o(i).typ = 3
o(i).y = 4
o(i).txt = idenewtxt("#Yes" + sep + "#No" + sep + "#Cancel")
o(i).def = 1
'-------- end of init --------

'-------- generic init --------
FOR i = 1 TO 100: o(i).par = p: NEXT 'set parent info of objects
'-------- end of generic init --------

DO 'main loop

    '-------- generic display dialog box & objects --------
    idedrawpar p
    f = 1: cx = 0: cy = 0
    FOR i = 1 TO 100
        IF o(i).typ THEN
            'prepare object
            o(i).foc = focus - f 'focus offset
            o(i).cx = 0: o(i).cy = 0
            idedrawobj o(i), f 'display object
            IF o(i).cx THEN cx = o(i).cx: cy = o(i).cy
        END IF
    NEXT i
    lastfocus = f - 1
    '-------- end of generic display dialog box & objects --------

    '-------- custom display changes --------
    COLOR 0, 7: LOCATE p.y + 2, p.x + 4: PRINT "Program is not saved. Save it now?";
    '-------- end of custom display changes --------

    'update visual page and cursor position
    PCOPY 1, 0
    IF cx THEN SCREEN , , 0, 0: LOCATE cy, cx, 1: SCREEN , , 1, 0

    '-------- read input --------
    change = 0
    DO
        getxymouse
        mx = mousex: my = mousey: mb = mousebutton1
        IF mb <> 0 AND omb = 0 THEN mousedown = 1: change = 1
        IF mb = 0 AND omb <> 0 THEN mouseup = 1: change = 1
        IF mb THEN change = 1
        omb = mb
        k$ = INKEY$: IF LEN(k$) THEN change = 1
        'DEF SEG = 0: alt = PEEK(&H417) AND 8
        alt = 8
        IF alt <> oldalt THEN change = 1
        oldalt = alt


        IF change = 0 THEN _LIMIT 16
    LOOP UNTIL change
    SCREEN , , 0, 0: LOCATE , , 0: SCREEN , , 1, 0
    IF alt THEN idehl = 1 ELSE idehl = 0
    'convert "alt+letter" scancode to letter's ASCII character
    altletter$ = ""
    IF alt THEN
        IF LEN(k$) = 2 THEN
            k = ASC(RIGHT$(k$, 1))
            FOR c = 65 TO 90
                IF k = idealtcode(c) THEN
                    altletter$ = CHR$(c)
                    EXIT FOR
                END IF
            NEXT
        END IF
    END IF
    IF UCASE$(k$) = "Y" THEN altletter$ = "Y"
    IF UCASE$(k$) = "N" THEN altletter$ = "N"
    IF UCASE$(k$) = "C" THEN altletter$ = "C"

    '-------- end of read input --------

    '-------- generic input response --------
    info = 0
    IF k$ = "" THEN k$ = CHR$(255)
    IF k$ = CHR$(9) THEN focus = focus + 1
    IF k$ = CHR$(0) + CHR$(15) THEN focus = focus - 1
    IF focus < 1 THEN focus = lastfocus
    IF focus > lastfocus THEN focus = 1
    f = 1
    FOR i = 1 TO 100
        t = o(i).typ
        IF t THEN
            focusoffset = focus - f
            ideupdateobj o(i), focus, f, focusoffset, k$, altletter$, mb, mousedown, mouseup, mx, my, info
        END IF
    NEXT
    '-------- end of generic input response --------

    IF k$ = CHR$(27) THEN
        idesavenow$ = "C"
        EXIT FUNCTION
    END IF

    IF info THEN
        IF info = 1 THEN idesavenow$ = "Y"
        IF info = 2 THEN idesavenow$ = "N"
        IF info = 3 THEN idesavenow$ = "C"
        EXIT FUNCTION
    END IF

    'end of custom controls
    mousedown = 0
    mouseup = 0
LOOP

END FUNCTION

SUB idesetline (i, text$)

text$ = RTRIM$(text$)

IF i <> -1 THEN idegotoline i
textlen = LEN(text$)
idet$ = LEFT$(idet$, ideli - 1) + MKL$(textlen) + text$ + MKL$(textlen) + RIGHT$(idet$, LEN(idet$) - ideli + 1 - CVL(MID$(idet$, ideli, 4)) - 8)

END SUB

SUB ideshowtext

IF idecx < idesx THEN idesx = idecx
IF idecy < idesy THEN idesy = idecy
IF idecx - idesx >= (idewx - 2) THEN idesx = idecx - (idewx - 3)
IF idecy - idesy >= (idewy - 8) THEN idesy = idecy - (idewy - 9)

sy1 = ideselecty1
sy2 = idecy
IF sy1 > sy2 THEN SWAP sy1, sy2
sx1 = ideselectx1
sx2 = idecx
IF sx1 > sx2 THEN SWAP sx1, sx2

COLOR 7, 1
l = idesy
FOR y = 0 TO (idewy - 9)
    IF l = idefocusline AND idecy <> l THEN COLOR 7, 4 ELSE COLOR 7, 1
    LOCATE y + 3, 2
    IF l <= iden THEN
        a$ = idegetline(l)
        a2$ = SPACE$(idesx + (idewx - 3))
        MID$(a2$, 1) = a$
        a2$ = RIGHT$(a2$, (idewx - 2))
    ELSE
        a2$ = SPACE$((idewx - 2))
    END IF
    PRINT a2$;

    'apply selection color change if necessary
    IF ideselect THEN
        IF l >= sy1 AND l <= sy2 THEN
            IF sy1 = sy2 THEN 'single line select
                COLOR 1, 7
                x2 = idesx
                FOR x = 2 TO (idewx - 2)
                    IF x2 >= sx1 AND x2 < sx2 THEN
                        a = SCREEN(y + 3, x): LOCATE y + 3, x: PRINT CHR$(a);
                    END IF
                    x2 = x2 + 1
                NEXT
                COLOR 7, 1
            ELSE 'multiline select
                IF idecx = 1 AND l = sy2 AND idecy > sy1 THEN GOTO nofinalselect
                LOCATE y + 3, 2
                COLOR 1, 7: PRINT a2$;
                COLOR 7, 1
                nofinalselect:
            END IF
        END IF
    END IF

    l = l + 1
NEXT

q = idevbar(idewx, 3, (idewy - 8), idecy, iden)
q = idehbar(2, (idewy - 5), (idewx - 2), idesx, 608)

'update cursor pos in status bar
COLOR 0, 3
LOCATE idewy, idewx - 15: PRINT "          :     ";
IF idecx < 100000 THEN
    LOCATE idewy, idewx - 4
    a$ = LTRIM$(STR$(idecx))
    PRINT a$;
END IF
a$ = LTRIM$(STR$(idecy))
LOCATE idewy, (idewx - 5) - LEN(a$)
PRINT a$;

SCREEN , , 0, 0: LOCATE idecy - idesy + 3, idecx - idesx + 2: SCREEN , , 3, 0

END SUB

FUNCTION idesubs$

'-------- generic dialog box header --------
PCOPY 0, 2
PCOPY 0, 1
SCREEN , , 1, 0
focus = 1
DIM p AS idedbptype
DIM o(1 TO 100) AS idedbotype
DIM oo AS idedbotype
DIM sep AS STRING * 1
sep = CHR$(0)
'-------- end of generic dialog box header --------

'-------- init --------

ly$ = MKL$(1)
l$ = ideprogname$
IF l$ = "" THEN l$ = "Untitled" + tempfolderindexstr$
FOR y = 1 TO iden
    a$ = idegetline(y)
    a$ = LTRIM$(RTRIM$(a$))
    sf = 0
    nca$ = UCASE$(a$)
    IF LEFT$(nca$, 4) = "SUB " THEN sf = 1: sf$ = "SUB  "
    IF LEFT$(nca$, 9) = "FUNCTION " THEN sf = 2: sf$ = "FUNC "
    IF sf THEN
        IF RIGHT$(nca$, 7) = " STATIC" THEN
            a$ = RTRIM$(LEFT$(a$, LEN(a$) - 7))
        END IF
        ly$ = ly$ + MKL$(y)
        IF sf = 1 THEN
            a$ = RIGHT$(a$, LEN(a$) - 4)
        ELSE
            a$ = RIGHT$(a$, LEN(a$) - 9)
        END IF
        a$ = LTRIM$(RTRIM$(a$))
        x = INSTR(a$, "(")
        IF x THEN
            n$ = RTRIM$(LEFT$(a$, x - 1))
            args$ = RIGHT$(a$, LEN(a$) - x + 1)
        ELSE
            n$ = a$
            args$ = ""
        END IF
        IF LEN(n$) <= 20 THEN
            n$ = n$ + SPACE$(20 - LEN(n$))
        ELSE
            n$ = LEFT$(n$, 17) + "úúú"
        END IF
        IF LEN(args$) <= (idewx - 41) THEN
            args$ = args$ + SPACE$((idewx - 41) - LEN(args$))
        ELSE
            args$ = LEFT$(args$, (idewx - 44)) + "úúú"
        END IF
        l$ = l$ + sep + "ÃÄ" + n$ + " " + sf$ + args$

    END IF
NEXT

FOR x = LEN(l$) TO 1 STEP -1
    a$ = MID$(l$, x, 1)
    IF a$ = "Ã" THEN MID$(l$, x, 1) = "À": EXIT FOR
NEXT



'72,19
i = 0
idepar p, idewx - 8, idewy - 6, "SUBs"

i = i + 1
o(i).typ = 2
o(i).y = 1
'68
o(i).w = idewx - 12: o(i).h = idewy - 9
o(i).txt = idenewtxt(l$)
o(i).sel = 1
o(i).nam = idenewtxt("Program Items")


i = i + 1
o(i).typ = 3
o(i).y = idewy - 6
o(i).txt = idenewtxt("#Edit" + sep + "#Cancel")
o(i).def = 1

'-------- end of init --------

'-------- generic init --------
FOR i = 1 TO 100: o(i).par = p: NEXT 'set parent info of objects
'-------- end of generic init --------

DO 'main loop

    '-------- generic display dialog box & objects --------
    idedrawpar p
    f = 1: cx = 0: cy = 0
    FOR i = 1 TO 100
        IF o(i).typ THEN
            'prepare object
            o(i).foc = focus - f 'focus offset
            o(i).cx = 0: o(i).cy = 0
            idedrawobj o(i), f 'display object
            IF o(i).cx THEN cx = o(i).cx: cy = o(i).cy
        END IF
    NEXT i
    lastfocus = f - 1
    '-------- end of generic display dialog box & objects --------

    '-------- custom display changes --------
    '-------- end of custom display changes --------

    'update visual page and cursor position
    PCOPY 1, 0
    IF cx THEN SCREEN , , 0, 0: LOCATE cy, cx, 1: SCREEN , , 1, 0

    '-------- read input --------
    change = 0
    DO
        getxymouse
        mx = mousex: my = mousey: mb = mousebutton1
        IF mb <> 0 AND omb = 0 THEN mousedown = 1: change = 1
        IF mb = 0 AND omb <> 0 THEN mouseup = 1: change = 1
        IF mb THEN change = 1
        omb = mb
        k$ = INKEY$: IF LEN(k$) THEN change = 1
        DEF SEG = 0: alt = PEEK(&H417) AND 8: IF alt <> oldalt THEN change = 1
        oldalt = alt

        IF change = 0 THEN _LIMIT 16
    LOOP UNTIL change
    SCREEN , , 0, 0: LOCATE , , 0: SCREEN , , 1, 0
    IF alt THEN idehl = 1 ELSE idehl = 0
    'convert "alt+letter" scancode to letter's ASCII character
    altletter$ = ""
    IF alt THEN
        IF LEN(k$) = 2 THEN
            k = ASC(RIGHT$(k$, 1))
            FOR c = 65 TO 90
                IF k = idealtcode(c) THEN
                    altletter$ = CHR$(c)
                    EXIT FOR
                END IF
            NEXT
        END IF
    END IF
    '-------- end of read input --------

    '-------- generic input response --------
    info = 0
    IF k$ = "" THEN k$ = CHR$(255)
    IF k$ = CHR$(9) THEN focus = focus + 1
    IF k$ = CHR$(0) + CHR$(15) THEN focus = focus - 1
    IF focus < 1 THEN focus = lastfocus
    IF focus > lastfocus THEN focus = 1
    f = 1
    FOR i = 1 TO 100
        t = o(i).typ
        IF t THEN
            focusoffset = focus - f
            ideupdateobj o(i), focus, f, focusoffset, k$, altletter$, mb, mousedown, mouseup, mx, my, info
        END IF
    NEXT
    '-------- end of generic input response --------

    IF k$ = CHR$(27) OR (focus = 3 AND info <> 0) THEN
        idesubs$ = "C"
        EXIT FUNCTION
    END IF

    IF k$ = CHR$(13) OR (focus = 2 AND info <> 0) OR (info = 1 AND focus = 1) THEN
        y = o(1).sel
        IF y < 1 THEN y = -y
        idecy = CVL(MID$(ly$, y * 4 - 3, 4))
        idesy = idecy
        idecx = 1
        idesx = 1
        EXIT FUNCTION
    END IF


    'end of custom controls
    mousedown = 0
    mouseup = 0
LOOP



END FUNCTION


FUNCTION idelanguagebox

'-------- generic dialog box header --------
PCOPY 0, 2
PCOPY 0, 1
SCREEN , , 1, 0
focus = 1
DIM p AS idedbptype
DIM o(1 TO 100) AS idedbotype
DIM oo AS idedbotype
DIM sep AS STRING * 1
sep = CHR$(0)
'-------- end of generic dialog box header --------

'-------- init --------

'generate list of available code pages
l$=idecpname(1)
for x=2 to idecpnum
l$=l$+sep+idecpname(x)
next
l$=ucase$(l$)

i = 0
idepar p, idewx - 8, idewy - 6, "Language"

i = i + 1
o(i).typ = 2
o(i).y = 2
o(i).w = idewx - 12: o(i).h = idewy-10
o(i).txt = idenewtxt(l$)
o(i).sel = 1: if idecpindex then o(i).sel=idecpindex
o(i).nam = idenewtxt("Code Pages")

i = i + 1
o(i).typ = 3
o(i).y = idewy - 6
o(i).txt = idenewtxt("#OK" + sep + "#Cancel")
o(i).def = 1





'-------- end of init --------

'-------- generic init --------
FOR i = 1 TO 100: o(i).par = p: NEXT 'set parent info of objects
'-------- end of generic init --------

DO 'main loop

    '-------- generic display dialog box & objects --------
    idedrawpar p
    f = 1: cx = 0: cy = 0
    FOR i = 1 TO 100
        IF o(i).typ THEN
            'prepare object
            o(i).foc = focus - f 'focus offset
            o(i).cx = 0: o(i).cy = 0
            idedrawobj o(i), f 'display object
            IF o(i).cx THEN cx = o(i).cx: cy = o(i).cy
        END IF
    NEXT i
    lastfocus = f - 1
    '-------- end of generic display dialog box & objects --------

    '-------- custom display changes --------
    COLOR 0, 7: LOCATE p.y + 1, p.x + 2: PRINT "Code-page for ASCII-UNICODE mapping: (Default: CP437)"

    '-------- end of custom display changes --------

    'update visual page and cursor position
    PCOPY 1, 0
    IF cx THEN SCREEN , , 0, 0: LOCATE cy, cx, 1: SCREEN , , 1, 0

    '-------- read input --------
    change = 0
    DO
        getxymouse
        mx = mousex: my = mousey: mb = mousebutton1
        IF mb <> 0 AND omb = 0 THEN mousedown = 1: change = 1
        IF mb = 0 AND omb <> 0 THEN mouseup = 1: change = 1
        IF mb THEN change = 1
        omb = mb
        k$ = INKEY$: IF LEN(k$) THEN change = 1
        DEF SEG = 0: alt = PEEK(&H417) AND 8: IF alt <> oldalt THEN change = 1
        oldalt = alt

        IF change = 0 THEN _LIMIT 16
    LOOP UNTIL change
    SCREEN , , 0, 0: LOCATE , , 0: SCREEN , , 1, 0
    IF alt THEN idehl = 1 ELSE idehl = 0
    'convert "alt+letter" scancode to letter's ASCII character
    altletter$ = ""
    IF alt THEN
        IF LEN(k$) = 2 THEN
            k = ASC(RIGHT$(k$, 1))
            FOR c = 65 TO 90
                IF k = idealtcode(c) THEN
                    altletter$ = CHR$(c)
                    EXIT FOR
                END IF
            NEXT
        END IF
    END IF
    '-------- end of read input --------

    '-------- generic input response --------
    info = 0
    IF k$ = "" THEN k$ = CHR$(255)
    IF k$ = CHR$(9) THEN focus = focus + 1
    IF k$ = CHR$(0) + CHR$(15) THEN focus = focus - 1
    IF focus < 1 THEN focus = lastfocus
    IF focus > lastfocus THEN focus = 1
    f = 1
    FOR i = 1 TO 100
        t = o(i).typ
        IF t THEN
            focusoffset = focus - f
            ideupdateobj o(i), focus, f, focusoffset, k$, altletter$, mb, mousedown, mouseup, mx, my, info
        END IF
    NEXT
    '-------- end of generic input response --------

    IF k$ = CHR$(27) OR (focus = 3 AND info <> 0) THEN
'        idesubs$ = "C"
        EXIT FUNCTION
    END IF

    IF k$ = CHR$(13) OR (focus = 2 AND info <> 0) OR (info = 1 AND focus = 1) THEN
        y = o(1).sel
        IF y < 1 THEN y = -y

for x=128 to 255
u=val("&H"+mid$(idecp(y),x*8+1,8)+"&")
if u=0 then u=9744
_MAPUNICODE u to x
next

'SEEK 1049
    '[2]   codepage(=0)
    'total bytes: 1050

        'save changes
        OPEN ".\internal\temp\options.bin" FOR BINARY AS #150
        SEEK #150,1049
        v% = y: PUT #150, , v%: idecpindex=v%
        CLOSE #150

        EXIT FUNCTION
    END IF


    'end of custom controls
    mousedown = 0
    mouseup = 0
LOOP



END FUNCTION




SUB ideupdateobj (o AS idedbotype, focus, f, focusoffset, k$, altletter$, mb, mousedown, mouseup, mx, my, info)
DIM sep AS STRING * 1
sep = CHR$(0)

t = o.typ

IF t = 1 THEN
    IF mousedown THEN
        x1 = o.par.x + o.x: y = o.par.y + o.y
        x2 = x1
        IF o.nam THEN
            x2 = x2 + idehlen(idetxt(o.nam)) + 2
        END IF
        IF my >= y - 1 AND my <= y + 1 THEN
            IF mx >= x1 AND mx <= x2 + o.w + 3 THEN
                focus = f
                'change cursor location?
                IF my = y THEN
                    IF mx > x2 + 1 AND mx < x2 + o.w + 2 THEN
                        a$ = idetxt(o.txt)
                        x = mx - x2 - 2 '0-?
                        IF x <= LEN(a$) THEN o.v1 = x ELSE o.v1 = LEN(a$)
                    END IF
                END IF
            END IF
        END IF
    END IF 'mousedown
    IF focusoffset = 0 THEN
        a$ = idetxt(o.txt)
        IF LEN(k$) = 1 THEN
            k = ASC(k$)
            IF k = 8 AND o.v1 > 0 THEN
                a1$ = LEFT$(a$, o.v1 - 1)
                IF o.v1 <= LEN(a$) THEN a2$ = RIGHT$(a$, LEN(a$) - o.v1) ELSE a2$ = ""
                a$ = a1$ + a2$: o.v1 = o.v1 - 1
            END IF
            IF k >= 32 AND k <= 126 THEN
                IF o.v1 > 0 THEN a1$ = LEFT$(a$, o.v1) ELSE a1$ = ""
                IF o.v1 <= LEN(a$) THEN a2$ = RIGHT$(a$, LEN(a$) - o.v1) ELSE a2$ = ""
                a$ = a1$ + k$ + a2$: o.v1 = o.v1 + 1
            END IF
            idetxt(o.txt) = a$
        END IF
        IF k$ = CHR$(0) + "S" THEN 'DEL
            IF o.v1 > 0 THEN a1$ = LEFT$(a$, o.v1) ELSE a1$ = ""
            IF o.v1 < LEN(a$) THEN a2$ = RIGHT$(a$, LEN(a$) - o.v1 - 1) ELSE a2$ = ""
            a$ = a1$ + a2$
            idetxt(o.txt) = a$
        END IF
        'cursor control
        IF k$ = CHR$(0) + "K" THEN o.v1 = o.v1 - 1
        IF k$ = CHR$(0) + "M" THEN o.v1 = o.v1 + 1
        IF k$ = CHR$(0) + "G" THEN o.v1 = 0
        IF k$ = CHR$(0) + "O" THEN o.v1 = LEN(a$)
        IF o.v1 < 0 THEN o.v1 = 0
        IF o.v1 > LEN(a$) THEN o.v1 = LEN(a$)
    END IF
    'hot-key focus
    IF LEN(altletter$) THEN
        IF o.nam THEN
            x = INSTR(idetxt(o.nam), "#")
            IF x THEN
                IF UCASE$(MID$(idetxt(o.nam), x + 1, 1)) = altletter$ THEN focus = f
            END IF
        END IF
    END IF
    f = f + 1
END IF '1

IF t = 2 THEN
    idetxt(o.stx) = ""

    IF mousedown THEN
        x1 = o.par.x + o.x: y1 = o.par.y + o.y
        x2 = x1 + o.w + 1: y2 = y1 + o.h + 1
        IF mx >= x1 AND mx <= x2 AND my >= y1 AND my <= y2 THEN
            focus = f
            IF mx > x1 AND mx < x2 AND my > y1 AND my < y2 THEN
                y = my - y1 - 1
                y = y + o.v1
                IF o.sel = y THEN info = 1
                o.sel = y
                IF o.sel > o.num THEN o.sel = o.num
            END IF
        END IF

    END IF 'mousedown

    IF mb THEN
        IF focusoffset = 0 THEN

            x1 = o.par.x + o.x: y1 = o.par.y + o.y
            x2 = x1 + o.w + 1: y2 = y1 + o.h + 1
            IF mx >= x1 AND mx <= x2 AND my >= y1 AND my <= y2 THEN

                IF mx = x2 AND my > y1 + 1 AND my < y2 - 1 THEN

                    tsel = ABS(o.sel)
                    tnum = o.num
                    q = idevbar(x2, y1 + 1, o.h, tsel, tnum)

                    IF my < q THEN
                        k$ = CHR$(0) + CHR$(73)
                        idewait
                    END IF
                    IF my > q THEN
                        k$ = CHR$(0) + CHR$(81)
                        idewait
                    END IF
                END IF

                IF mx = x2 AND my = y1 + 1 THEN
                    k$ = CHR$(0) + CHR$(72)
                    idewait
                END IF
                IF mx = x2 AND my = y2 - 1 THEN
                    k$ = CHR$(0) + CHR$(80)
                    idewait
                END IF

            END IF
        END IF
    END IF 'mb


    IF focusoffset = 0 THEN


        IF k$ = CHR$(0) + CHR$(72) THEN
            IF o.sel < 0 THEN
                o.sel = -o.sel
            ELSE
                o.sel = o.sel - 1
                IF o.sel < 1 THEN o.sel = 1
            END IF
        END IF

        IF k$ = CHR$(0) + CHR$(80) THEN
            IF o.sel < 0 THEN
                o.sel = -o.sel
            ELSE
                o.sel = o.sel + 1
                IF o.sel > o.num THEN o.sel = o.num
            END IF
        END IF

        IF k$ = CHR$(0) + CHR$(73) THEN
            IF o.sel < 0 THEN
                o.sel = -o.sel
            END IF
            o.sel = o.sel - o.h + 1
            IF o.sel < 1 THEN o.sel = 1
        END IF

        IF k$ = CHR$(0) + CHR$(81) THEN
            IF o.sel < 0 THEN
                o.sel = -o.sel
            END IF
            o.sel = o.sel + o.h - 1
            IF o.sel > o.num THEN o.sel = o.num
        END IF

        IF k$ = CHR$(0) + "w" THEN
            o.sel = 1
        END IF

        IF k$ = CHR$(0) + "u" THEN
            o.sel = o.num
        END IF

        k = ASC(UCASE$(k$)): IF k >= 32 AND k <= 126 THEN k2$ = CHR$(k) ELSE k2$ = CHR$(255)
        a$ = idetxt(o.txt)
        n = 1
        a3$ = ""
        m = 0
        FOR i2 = 1 TO LEN(a$)
            a2$ = MID$(a$, i2, 1)
            IF a2$ <> sep THEN a3$ = a3$ + a2$
            IF a2$ = sep OR i2 = LEN(a$) THEN
                IF UCASE$(a3$) >= k2$ AND m = 0 THEN
                    m = 1
                    o.sel = n
                END IF
                IF n = o.sel THEN idetxt(o.stx) = a3$
                n = n + 1
                a3$ = ""
            END IF
        NEXT



    END IF

    'hot-key focus
    IF LEN(altletter$) THEN
        IF o.nam THEN
            x = INSTR(idetxt(o.nam), "#")
            IF x THEN
                IF UCASE$(MID$(idetxt(o.nam), x + 1, 1)) = altletter$ THEN focus = f
            END IF
        END IF
    END IF
    f = f + 1
END IF '2

IF t = 3 THEN

    'count buttons & check for hotkey(s)
    a$ = idetxt(o.txt)
    n = 1
    x = 0
    FOR i2 = 1 TO LEN(a$)
        a2$ = MID$(a$, i2, 1)
        IF a2$ = CHR$(0) THEN n = n + 1
        IF x = 1 THEN
            IF UCASE$(a2$) = altletter$ THEN
                focus = f + n - 1
                info = n
            END IF
        END IF
        IF a2$ = "#" THEN x = 1 ELSE x = 0
    NEXT

    'check for mouse click on button(s)
    IF mousedown THEN
        IF my = o.par.y + o.y THEN
            a$ = idetxt(o.txt)
            n = 1
            c = 0
            FOR i2 = 1 TO LEN(a$)
                a2$ = MID$(a$, i2, 1)
                IF a2$ = CHR$(0) THEN
                    n = n + 1
                ELSE
                    IF a$ <> "#" THEN c = c + 1
                END IF
            NEXT
            w = o.w
            c = c + n * 4 'add characters for bracing < > buttons
            whitespace = w - c
            spacing = whitespace \ (n + 1)
            'f2 = o.foc + 1
            'IF f2 < 1 OR f2 > n THEN
            'IF o.def THEN f2 = o.def
            'END IF
            n2 = 1
            a3$ = ""
            'LOCATE o.par.y + o.y, o.par.x + o.x
            x = o.par.x + o.x
            'COLOR 0, 7
            FOR i2 = 1 TO LEN(a$)
                a2$ = MID$(a$, i2, 1)
                IF a2$ <> CHR$(0) THEN a3$ = a3$ + a2$
                IF a2$ = CHR$(0) OR i2 = LEN(a$) THEN
                    'PRINT SPACE$(spacing);
                    x = x + spacing
                    'IF f2 = n2 THEN COLOR 15, 7 ELSE COLOR 0, 7
                    'PRINT "< ";
                    'COLOR 0, 7: idehPRINT a3$
                    'IF f2 = n2 THEN COLOR 15, 7 ELSE COLOR 0, 7
                    'IF n2 = o.foc + 1 THEN
                    'o.cx = x + 2: o.cy = o.par.y + o.y
                    'END IF
                    'PRINT " >";
                    'COLOR 0, 7
                    x2 = idehlen(a3$) + 4
                    IF mx >= x AND mx < x + x2 THEN info = n2: focus = f + n2 - 1


                    x = x + x2
                    a3$ = ""
                    n2 = n2 + 1
                END IF
            NEXT
        END IF 'my
    END IF 'mousedown

    IF focusoffset >= 0 AND focusoffset < n THEN
        f2 = f + focusoffset
        IF k$ = CHR$(13) THEN
            info = focusoffset + 1
        END IF
    END IF

    f = f + n
END IF '3

IF t = 4 THEN 'checkbox

    IF mousedown THEN
        y = o.par.y + o.y
        x1 = o.par.x + o.x: x2 = x1 + 2
        IF o.nam THEN
            x2 = x2 + 1 + idehlen(idetxt(o.nam))
        END IF
        IF my = y THEN
            IF mx >= x1 AND mx <= x2 THEN
                focus = f
                o.sel = o.sel + 1: IF o.sel > 1 THEN o.sel = 0 'toggle
            END IF
        END IF
    END IF 'mousedown
    IF focusoffset = 0 THEN

        'a$ = idetxt(o.txt)
        'IF LEN(k$) = 1 THEN
        'k = ASC(k$)
        'IF k = 8 AND o.v1 > 0 THEN
        'a1$ = LEFT$(a$, o.v1 - 1)
        'IF o.v1 <= LEN(a$) THEN a2$ = RIGHT$(a$, LEN(a$) - o.v1) ELSE a2$ = ""
        'a$ = a1$ + a2$: o.v1 = o.v1 - 1
        'END IF
        'IF k >= 32 AND k <= 126 THEN
        'IF o.v1 > 0 THEN a1$ = LEFT$(a$, o.v1) ELSE a1$ = ""
        'IF o.v1 <= LEN(a$) THEN a2$ = RIGHT$(a$, LEN(a$) - o.v1) ELSE a2$ = ""
        'a$ = a1$ + k$ + a2$: o.v1 = o.v1 + 1
        'END IF
        'idetxt(o.txt) = a$
        'END IF
        'IF k$ = CHR$(0) + "S" THEN 'DEL
        'IF o.v1 > 0 THEN a1$ = LEFT$(a$, o.v1) ELSE a1$ = ""
        'IF o.v1 < LEN(a$) THEN a2$ = RIGHT$(a$, LEN(a$) - o.v1 - 1) ELSE a2$ = ""
        'a$ = a1$ + a2$
        'idetxt(o.txt) = a$
        'END IF
        ''cursor control
        'IF k$ = CHR$(0) + "K" THEN o.v1 = o.v1 - 1
        'IF k$ = CHR$(0) + "M" THEN o.v1 = o.v1 + 1
        'IF k$ = CHR$(0) + "G" THEN o.v1 = 0
        'IF k$ = CHR$(0) + "O" THEN o.v1 = LEN(a$)
        'IF o.v1 < 0 THEN o.v1 = 0
        'IF o.v1 > LEN(a$) THEN o.v1 = LEN(a$)

        IF k$ = CHR$(0) + "H" THEN o.sel = 1
        IF k$ = CHR$(0) + "P" THEN o.sel = 0
        IF k$ = " " THEN
            o.sel = o.sel + 1: IF o.sel > 1 THEN o.sel = 0 'toggle
        END IF

    END IF 'in focus
    'hot-key focus
    IF LEN(altletter$) THEN
        IF o.nam THEN
            x = INSTR(idetxt(o.nam), "#")
            IF x THEN
                IF UCASE$(MID$(idetxt(o.nam), x + 1, 1)) = altletter$ THEN focus = f
            END IF
        END IF
    END IF
    f = f + 1
END IF '4


END SUB

FUNCTION idevbar (x, y, h, i2, n2)
i = i2: n = n2

'h is height in charatcers (inc. arrows)

'draw background & arrows
COLOR 0, 7
LOCATE y, x: PRINT CHR$(24);
LOCATE y + h - 1, x: PRINT CHR$(25);
FOR y2 = y + 1 TO y + h - 2
    LOCATE y2, x: PRINT "°";
NEXT

'draw slider

IF n < 1 THEN n = 1
IF i < 1 THEN i = 1
IF i > n THEN i = n

IF h = 2 THEN
    idevbar = y 'not position for slider exists
    EXIT FUNCTION
END IF

IF h = 3 THEN
    idevbar = y + 1 'dummy value
    'no slider
    EXIT FUNCTION
END IF

IF h = 4 THEN
    IF n = 1 THEN
        idevbar = y + 1 'dummy value
        'no slider required for 1 item
        EXIT FUNCTION
    ELSE
        'show whichever is closer of the two positions
        p! = (i - 1) / (n - 1)
        IF p! < .5 THEN y2 = y + 1 ELSE y2 = y + 2
        LOCATE y2, x: PRINT "Û";
        idevbar = y2
        EXIT FUNCTION
    END IF
END IF

IF h > 4 THEN
    IF n = 1 THEN
        idevbar = y + h \ 4 'dummy value
        'no slider required for 1 item
        EXIT FUNCTION
    END IF
    IF i = 1 THEN
        y2 = y + 1
        LOCATE y2, x: PRINT "Û";
        idevbar = y2
        EXIT FUNCTION
    END IF
    IF i = n THEN
        y2 = y + h - 2
        LOCATE y2, x: PRINT "Û";
        idevbar = y2
        EXIT FUNCTION
    END IF
    'between i=1 and i=n
    p! = (i - 1) / (n - 1)
    p! = p! * (h - 4)
    y2 = y + 2 + INT(p!)
    LOCATE y2, x: PRINT "Û";
    idevbar = y2
    EXIT FUNCTION
END IF
END FUNCTION

SUB idewait
FOR i = 1 TO 2
    t! = TIMER
    DO: LOOP WHILE TIMER = t!
NEXT
END SUB

SUB idewait4alt
DEF SEG = 0
DO
LOOP WHILE PEEK(&H417) AND 8
END SUB

SUB idewait4mous
DO
    getxymouse
    mx = mousex
    my = mousey
    mb = mousebutton1
LOOP WHILE mb
END SUB

FUNCTION idezfilename$ (f$)

IF os$ = "WIN" THEN
    idezfilename$ = CHR$(34) + f$ + CHR$(34)
    EXIT FUNCTION
END IF

IF os$ = "LNX" THEN
    idezfilename$ = "'" + f$ + "'"
    EXIT FUNCTION
END IF

END FUNCTION

FUNCTION idezchangepath$ (path$, newpath$)

idezchangepath$ = path$ 'default (for unsuccessful cases)

IF os$ = "WIN" THEN
    'go back a path
    IF newpath$ = ".." THEN
        FOR x = LEN(path$) TO 1 STEP -1
            a$ = MID$(path$, x, 1)
            IF a$ = "\" THEN
                idezchangepath$ = LEFT$(path$, x - 1)
                EXIT FOR
            END IF
        NEXT
        EXIT FUNCTION
    END IF
    'change drive
    IF LEN(newpath$) = 2 AND RIGHT$(newpath$, 1) = ":" THEN
        idezchangepath$ = newpath$
        EXIT FUNCTION
    END IF
    idezchangepath$ = path$ + "\" + newpath$
    EXIT FUNCTION
END IF

IF os$ = "LNX" THEN

    'go back a path
    IF newpath$ = ".." THEN
        FOR x = LEN(path$) TO 1 STEP -1
            a$ = MID$(path$, x, 1)
            IF a$ = "/" THEN
                idezchangepath$ = LEFT$(path$, x - 1)
                IF x = 1 THEN idezchangepath$ = "/" 'root path cannot be ""
                EXIT FOR
            END IF
        NEXT
        EXIT FUNCTION
    END IF
    IF path$ = "/" THEN idezchangepath$ = "/" + newpath$ ELSE idezchangepath$ = path$ + "/" + newpath$
    EXIT FUNCTION
END IF

END FUNCTION

FUNCTION idezfilelist$ (path$)
DIM sep AS STRING * 1
sep = CHR$(0)

IF os$ = "WIN" THEN
    OPEN ".\internal\temp\files.txt" FOR OUTPUT AS #150: CLOSE #150
    SHELL _HIDE "dir /b /ON /A-D " + idezfilename$(path$) + "\*.bas >.\internal\temp\files.txt"
    filelist$ = ""
    OPEN ".\internal\temp\files.txt" FOR INPUT AS #150
    DO UNTIL EOF(150)
        LINE INPUT #150, a$
        IF LEN(a$) THEN 'skip blank entries
            IF filelist$ = "" THEN filelist$ = a$ ELSE filelist$ = filelist$ + sep + a$
        END IF
    LOOP
    CLOSE #150
    idezfilelist$ = filelist$
    EXIT FUNCTION
END IF

IF os$ = "LNX" THEN
    filelist$ = ""
    FOR i = 1 TO 2
        OPEN "./internal/temp/files.txt" FOR OUTPUT AS #150: CLOSE #150
        IF i = 1 THEN SHELL _HIDE "find " + idezfilename$(path$) + " -maxdepth 1 -type f -name " + CHR$(34) + "*.bas" + CHR$(34) + " >./internal/temp/files.txt"
        IF i = 2 THEN SHELL _HIDE "find " + idezfilename$(path$) + " -maxdepth 1 -type f -name " + CHR$(34) + "*.BAS" + CHR$(34) + " >./internal/temp/files.txt"
        OPEN "./internal/temp/files.txt" FOR INPUT AS #150
        DO UNTIL EOF(150)
            LINE INPUT #150, a$
            IF LEN(a$) = 0 THEN EXIT DO
            FOR x = LEN(a$) TO 1 STEP -1
                a2$ = MID$(a$, x, 1)
                IF a2$ = "/" THEN
                    a$ = RIGHT$(a$, LEN(a$) - x)
                    EXIT FOR
                END IF
            NEXT
            IF filelist$ = "" THEN filelist$ = a$ ELSE filelist$ = filelist$ + sep + a$
        LOOP
        CLOSE #150
    NEXT
    idezfilelist$ = filelist$
    EXIT FUNCTION
END IF

END FUNCTION

FUNCTION idezgetroot$
'note: does NOT including a trailing / or \ on the right

IF os$ = "WIN" THEN
    SHELL _HIDE "cd >.\internal\temp\root.txt"
    OPEN ".\internal\temp\root.txt" FOR INPUT AS #150
    LINE INPUT #150, a$
    idezgetroot$ = a$
    CLOSE #150
    EXIT FUNCTION
END IF

IF os$ = "LNX" THEN
    SHELL _HIDE "pwd >./internal/temp/root.txt"
    OPEN "./internal/temp/root.txt" FOR INPUT AS #150
    LINE INPUT #150, a$
    idezgetroot$ = a$
    CLOSE #150
    EXIT FUNCTION
END IF

END FUNCTION

FUNCTION idezpathlist$ (path$)
DIM sep AS STRING * 1
sep = CHR$(0)

IF os$ = "WIN" THEN
    OPEN ".\internal\temp\paths.txt" FOR OUTPUT AS #150: CLOSE #150
    a$ = "": IF RIGHT$(path$, 1) = ":" THEN a$ = "\" 'use a \ after a drive letter
    SHELL _HIDE "dir /b /ON /AD " + idezfilename$(path$ + a$) + " >.\internal\temp\paths.txt"
    pathlist$ = ""
    OPEN ".\internal\temp\paths.txt" FOR INPUT AS #150
    DO UNTIL EOF(150)
        LINE INPUT #150, a$
        IF pathlist$ = "" THEN pathlist$ = a$ ELSE pathlist$ = pathlist$ + sep + a$
    LOOP
    CLOSE #150
    'count instances of / or \
    c = 0
    FOR x = 1 TO LEN(path$)
        b$ = MID$(path$, x, 1)
        IF b$ = idepathsep$ THEN c = c + 1
    NEXT
    IF c >= 1 THEN
        IF LEN(pathlist$) THEN pathlist$ = ".." + sep + pathlist$ ELSE pathlist$ = ".."
    END IF
    'add drive paths
    FOR i = 0 TO 25
        IF LEN(pathlist$) THEN pathlist$ = pathlist$ + sep
        pathlist$ = pathlist$ + CHR$(65 + i) + ":"
    NEXT
    idezpathlist$ = pathlist$
    EXIT FUNCTION
END IF

IF os$ = "LNX" THEN
    pathlist$ = ""
    OPEN "./internal/temp/paths.txt" FOR OUTPUT AS #150: CLOSE #150
    SHELL _HIDE "find " + idezfilename$(path$) + " -maxdepth 1 -mindepth 1 -type d >./internal/temp/paths.txt"
    OPEN "./internal/temp/paths.txt" FOR INPUT AS #150
    DO UNTIL EOF(150)
        LINE INPUT #150, a$
        IF LEN(a$) = 0 THEN EXIT DO
        FOR x = LEN(a$) TO 1 STEP -1
            a2$ = MID$(a$, x, 1)
            IF a2$ = "/" THEN
                a$ = RIGHT$(a$, LEN(a$) - x)
                EXIT FOR
            END IF
        NEXT
        IF pathlist$ = "" THEN pathlist$ = a$ ELSE pathlist$ = pathlist$ + sep + a$
    LOOP
    CLOSE #150

    IF path$ <> "/" THEN
        a$ = ".."

        IF pathlist$ = "" THEN pathlist$ = a$ ELSE pathlist$ = a$ + sep + pathlist$
    END IF

    idezpathlist$ = pathlist$
    EXIT FUNCTION
END IF

END FUNCTION

FUNCTION ideztakepath$ (f$) 'assume f$ contains a filename with an optional path
p$ = ""

IF os$ = "WIN" THEN
    FOR i = LEN(f$) TO 1 STEP -1
        a$ = MID$(f$, i, 1)
        IF a$ = "\" THEN
            p$ = LEFT$(f$, i - 1)
            f$ = RIGHT$(f$, LEN(f$) - i)
            EXIT FOR
        END IF
    NEXT
    ideztakepath$ = p$
    EXIT FUNCTION
END IF

IF os$ = "LNX" THEN
    FOR i = LEN(f$) TO 1 STEP -1
        a$ = MID$(f$, i, 1)
        IF a$ = "/" THEN
            p$ = LEFT$(f$, i - 1)
            f$ = RIGHT$(f$, LEN(f$) - i)
            EXIT FOR
        END IF
    NEXT
    ideztakepath$ = p$
    EXIT FUNCTION
END IF

END FUNCTION

'file f$ exists, and may contain a path
'return the FULL path (even if it was passed as a relative path)
'f$ is altered to only contain the name of the actual file
'root$ is the path to apply relative paths to
FUNCTION idezgetfilepath$ (root$, f$)
'step #1: seperate file's name from its path (if any)
p$ = ideztakepath$(f$) 'note: this is a simple seperation of the string
'step #2: if path was undefined, set it to root
IF LEN(p$) = 0 THEN p$ = root$
'step #3: if path is relative, make it relative to root$
IF LEFT$(p$, 1) = "." THEN p$ = root$ + idepathsep$ + p$
'step #4: attempt a CHDIR to the path to (i)  validate its existance
'                                      & (ii) allow listing the paths full name
ideerror = 4 'path not found
p2$ = p$
IF os$ = "WIN" THEN
    IF RIGHT$(p2$, 1) = ":" THEN p2$ = p2$ + "\" 'force change to root of drive
END IF
CHDIR p2$
ideerror = 1
'step #5: get the path's full name (assume success)
IF os$ = "WIN" THEN
    SHELL _HIDE "cd >" + idezfilename$(ideroot$) + "\internal\temp\root.txt"
    OPEN ideroot$ + "\internal\temp\root.txt" FOR INPUT AS #150
    LINE INPUT #150, p$
    IF RIGHT$(p$, 1) = "\" THEN p$ = LEFT$(p$, LEN(p$) - 1) 'strip trailing \ after root drive path
    CLOSE #150
END IF
IF os$ = "LNX" THEN
    SHELL _HIDE "pwd >" + idezfilename$(ideroot$) + "/internal/temp/root.txt"
    OPEN ideroot$ + "/internal/temp/root.txt" FOR INPUT AS #150
    LINE INPUT #150, p$
    CLOSE #150
END IF
'step #6: restore root path (assume success)
CHDIR ideroot$
'important: no validation of f$ necessary
idezgetfilepath$ = p$
END FUNCTION

SUB initmouse
_MOUSESHOW
END SUB






FUNCTION idelayoutbox

'-------- generic dialog box header --------
PCOPY 0, 2
PCOPY 0, 1
SCREEN , , 1, 0
focus = 1
DIM p AS idedbptype
DIM o(1 TO 100) AS idedbotype
DIM oo AS idedbotype
DIM sep AS STRING * 1
sep = CHR$(0)
'-------- end of generic dialog box header --------

'-------- init --------
i = 0
idepar p, 60, 7, "Code Layout"

i = i + 1
o(i).typ = 4 'check box
o(i).y = 2
o(i).nam = idenewtxt("#Auto Spacing & Upper/Lowercase Formatting")
o(i).sel = ideautolayout

i = i + 1
o(i).typ = 4 'check box
o(i).y = 4
o(i).nam = idenewtxt("Auto #Indent -")
o(i).sel = ideautoindent

a2$ = str2$(ideautoindentsize)
i = i + 1
o(i).typ = 1
o(i).x = 20
o(i).y = 4
o(i).nam = idenewtxt("#Spacing")
o(i).txt = idenewtxt(a2$)
o(i).v1 = LEN(a2$)

i = i + 1
o(i).typ = 3
o(i).y = 7
o(i).txt = idenewtxt("OK" + sep + "#Cancel")
o(i).def = 1
'-------- end of init --------

'-------- generic init --------
FOR i = 1 TO 100: o(i).par = p: NEXT 'set parent info of objects
'-------- end of generic init --------

DO 'main loop


    '-------- generic display dialog box & objects --------
    idedrawpar p
    f = 1: cx = 0: cy = 0
    FOR i = 1 TO 100
        IF o(i).typ THEN

            'prepare object
            o(i).foc = focus - f 'focus offset
            o(i).cx = 0: o(i).cy = 0
            idedrawobj o(i), f 'display object
            IF o(i).cx THEN cx = o(i).cx: cy = o(i).cy
        END IF
    NEXT i
    lastfocus = f - 1
    '-------- end of generic display dialog box & objects --------

    '-------- custom display changes --------
    '-------- end of custom display changes --------

    'update visual page and cursor position
    PCOPY 1, 0
    IF cx THEN SCREEN , , 0, 0: LOCATE cy, cx, 1: SCREEN , , 1, 0

    '-------- read input --------
    change = 0
    DO
        getxymouse
        mx = mousex: my = mousey: mb = mousebutton1
        IF mb <> 0 AND omb = 0 THEN mousedown = 1: change = 1
        IF mb = 0 AND omb <> 0 THEN mouseup = 1: change = 1
        IF mb THEN change = 1
        omb = mb
        k$ = INKEY$: IF LEN(k$) THEN change = 1
        DEF SEG = 0: alt = PEEK(&H417) AND 8: IF alt <> oldalt THEN change = 1
        oldalt = alt

        IF change = 0 THEN _LIMIT 16
    LOOP UNTIL change
    SCREEN , , 0, 0: LOCATE , , 0: SCREEN , , 1, 0
    IF alt THEN idehl = 1 ELSE idehl = 0
    'convert "alt+letter" scancode to letter's ASCII character
    altletter$ = ""
    IF alt THEN
        IF LEN(k$) = 2 THEN
            k = ASC(RIGHT$(k$, 1))
            FOR c = 65 TO 90
                IF k = idealtcode(c) THEN
                    altletter$ = CHR$(c)
                    EXIT FOR
                END IF
            NEXT
        END IF
    END IF
    '-------- end of read input --------

    '-------- generic input response --------
    info = 0
    IF k$ = "" THEN k$ = CHR$(255)
    IF k$ = CHR$(9) THEN focus = focus + 1
    IF k$ = CHR$(0) + CHR$(15) THEN focus = focus - 1
    IF focus < 1 THEN focus = lastfocus
    IF focus > lastfocus THEN focus = 1
    f = 1
    FOR i = 1 TO 100
        t = o(i).typ
        IF t THEN
            focusoffset = focus - f
            ideupdateobj o(i), focus, f, focusoffset, k$, altletter$, mb, mousedown, mouseup, mx, my, info
        END IF
    NEXT
    '-------- end of generic input response --------

    'specific post controls

    a$ = idetxt(o(3).txt)
    IF LEN(a$) > 2 THEN a$ = LEFT$(a$, 2) '2 character limit
    FOR i = 1 TO LEN(a$)
        a = ASC(a$, i)
        IF i = 2 AND ASC(a$, 1) = 48 THEN a$ = "0": EXIT FOR
        IF a < 48 OR a > 57 THEN a$ = "": EXIT FOR
    NEXT
    IF LEN(a$) THEN
        a = VAL(a$)
        IF a > 64 THEN a$ = "64"
    END IF
    idetxt(o(3).txt) = a$

    IF k$ = CHR$(27) OR (focus = 5 AND info <> 0) THEN EXIT FUNCTION
    IF k$ = CHR$(13) OR (focus = 4 AND info <> 0) THEN
        'save changes
        OPEN ".\internal\temp\options.bin" FOR BINARY AS #150
        v% = o(1).sel: IF v% <> 0 THEN v% = 1 'ideautolayout
        PUT #150, , v%
        IF ideautolayout <> v% THEN ideautolayout = v%: idelayoutbox = 1
        v% = o(2).sel: IF v% <> 0 THEN v% = 1 'ideautoindent
        PUT #150, , v%
        IF ideautoindent <> v% THEN ideautoindent = v%: idelayoutbox = 1
        v$ = idetxt(o(3).txt) 'ideautoindentsize
        IF v$ = "" THEN v$ = "4"
        v% = VAL(v$)
        IF v% < 0 OR v% > 64 THEN v% = 4
        PUT #150, , v%
        IF ideautoindentsize <> v% THEN
            ideautoindentsize = v%
            IF ideautoindent <> 0 THEN idelayoutbox = 1
        END IF
        CLOSE #150
        EXIT FUNCTION
    END IF

    'end of custom controls

    mousedown = 0
    mouseup = 0
LOOP
END FUNCTION






FUNCTION ideupdatebox

'-------- generic dialog box header --------
PCOPY 0, 2
PCOPY 0, 1
SCREEN , , 1, 0
focus = 1
DIM p AS idedbptype
DIM o(1 TO 100) AS idedbotype
DIM oo AS idedbotype
DIM sep AS STRING * 1
sep = CHR$(0)
'-------- end of generic dialog box header --------

'-------- init --------
i = 0
idepar p, 40, 8, "Update"

i = i + 1
o(i).typ = 4 'check box
o(i).y = 2
o(i).nam = idenewtxt("#Check for updates:")
o(i).sel = ideupdatecheck

i = i + 1
o(i).typ = 4 'check box
o(i).y = 4
o(i).x = 8
o(i).nam = idenewtxt("#Only check once per day")
o(i).sel = ideupdatedaily

i = i + 1
o(i).typ = 4 'check box
o(i).y = 6
o(i).x = 8
o(i).nam = idenewtxt("#Automatically apply updates")
o(i).sel = ideupdateauto

i = i + 1
o(i).typ = 3
o(i).y = 8
o(i).txt = idenewtxt("OK" + sep + "#Cancel")
o(i).def = 1
'-------- end of init --------

'-------- generic init --------
FOR i = 1 TO 100: o(i).par = p: NEXT 'set parent info of objects
'-------- end of generic init --------

DO 'main loop


    '-------- generic display dialog box & objects --------
    idedrawpar p
    f = 1: cx = 0: cy = 0
    FOR i = 1 TO 100
        IF o(i).typ THEN

            'prepare object
            o(i).foc = focus - f 'focus offset
            o(i).cx = 0: o(i).cy = 0
            idedrawobj o(i), f 'display object
            IF o(i).cx THEN cx = o(i).cx: cy = o(i).cy
        END IF
    NEXT i
    lastfocus = f - 1
    '-------- end of generic display dialog box & objects --------

    '-------- custom display changes --------
    '-------- end of custom display changes --------

    'update visual page and cursor position
    PCOPY 1, 0
    IF cx THEN SCREEN , , 0, 0: LOCATE cy, cx, 1: SCREEN , , 1, 0

    '-------- read input --------
    change = 0
    DO
        getxymouse
        mx = mousex: my = mousey: mb = mousebutton1
        IF mb <> 0 AND omb = 0 THEN mousedown = 1: change = 1
        IF mb = 0 AND omb <> 0 THEN mouseup = 1: change = 1
        IF mb THEN change = 1
        omb = mb
        k$ = INKEY$: IF LEN(k$) THEN change = 1
        DEF SEG = 0: alt = PEEK(&H417) AND 8: IF alt <> oldalt THEN change = 1
        oldalt = alt

        IF change = 0 THEN _LIMIT 16
    LOOP UNTIL change
    SCREEN , , 0, 0: LOCATE , , 0: SCREEN , , 1, 0
    IF alt THEN idehl = 1 ELSE idehl = 0
    'convert "alt+letter" scancode to letter's ASCII character
    altletter$ = ""
    IF alt THEN
        IF LEN(k$) = 2 THEN
            k = ASC(RIGHT$(k$, 1))
            FOR c = 65 TO 90
                IF k = idealtcode(c) THEN
                    altletter$ = CHR$(c)
                    EXIT FOR
                END IF
            NEXT
        END IF
    END IF
    '-------- end of read input --------

    '-------- generic input response --------
    info = 0
    IF k$ = "" THEN k$ = CHR$(255)
    IF k$ = CHR$(9) THEN focus = focus + 1
    IF k$ = CHR$(0) + CHR$(15) THEN focus = focus - 1
    IF focus < 1 THEN focus = lastfocus
    IF focus > lastfocus THEN focus = 1
    f = 1
    FOR i = 1 TO 100
        t = o(i).typ
        IF t THEN
            focusoffset = focus - f
            ideupdateobj o(i), focus, f, focusoffset, k$, altletter$, mb, mousedown, mouseup, mx, my, info
        END IF
    NEXT
    '-------- end of generic input response --------

    'specific post controls
    IF k$ = CHR$(27) OR (focus = 5 AND info <> 0) THEN EXIT FUNCTION
    IF k$ = CHR$(13) OR (focus = 4 AND info <> 0) THEN
        'save changes
        OPEN ".\internal\temp\options.bin" FOR BINARY AS #150
        SEEK #150,1039
        v% = o(1).sel: IF v% <> 0 THEN v% = 1
        PUT #150, , v%
        ideupdatecheck=v%
        v% = o(2).sel: IF v% <> 0 THEN v% = 1
        PUT #150, , v%
        ideupdatedaily=v%
        v% = o(3).sel: IF v% <> 0 THEN v% = 1
        PUT #150, , v%
        ideupdateauto=v%
        CLOSE #150
        EXIT FUNCTION
    END IF
    'end of custom controls

    mousedown = 0
    mouseup = 0
LOOP
END FUNCTION





SUB idemessagebox (titlestr$,messagestr$)

'-------- generic dialog box header --------
PCOPY 0, 2
PCOPY 0, 1
SCREEN , , 1, 0
focus = 1
DIM p AS idedbptype
DIM o(1 TO 100) AS idedbotype
DIM oo AS idedbotype
DIM sep AS STRING * 1
sep = CHR$(0)
'-------- end of generic dialog box header --------

'-------- init --------
i = 0
w=len(messagestr$)+2
w2=len(titlestr$)+4
if w<w2 then w=w2
idepar p, w, 4, titlestr$

i = i + 1
o(i).typ = 3
o(i).y = 4
o(i).txt = idenewtxt("OK")
o(i).def = 1
'-------- end of init --------

'-------- generic init --------
FOR i = 1 TO 100: o(i).par = p: NEXT 'set parent info of objects
'-------- end of generic init --------

DO 'main loop


    '-------- generic display dialog box & objects --------
    idedrawpar p
    f = 1: cx = 0: cy = 0
    FOR i = 1 TO 100
        IF o(i).typ THEN

            'prepare object
            o(i).foc = focus - f 'focus offset
            o(i).cx = 0: o(i).cy = 0
            idedrawobj o(i), f 'display object
            IF o(i).cx THEN cx = o(i).cx: cy = o(i).cy
        END IF
    NEXT i
    lastfocus = f - 1
    '-------- end of generic display dialog box & objects --------

    '-------- custom display changes --------
    COLOR 0, 7: LOCATE p.y + 2, p.x + 2: PRINT messagestr$;
    '-------- end of custom display changes --------

    'update visual page and cursor position
    PCOPY 1, 0
    IF cx THEN SCREEN , , 0, 0: LOCATE cy, cx, 1: SCREEN , , 1, 0

    '-------- read input --------
    change = 0
    DO
        getxymouse
        mx = mousex: my = mousey: mb = mousebutton1
        IF mb <> 0 AND omb = 0 THEN mousedown = 1: change = 1
        IF mb = 0 AND omb <> 0 THEN mouseup = 1: change = 1
        IF mb THEN change = 1
        omb = mb
        k$ = INKEY$: IF LEN(k$) THEN change = 1
        DEF SEG = 0: alt = PEEK(&H417) AND 8: IF alt <> oldalt THEN change = 1
        oldalt = alt

        IF change = 0 THEN _LIMIT 16
    LOOP UNTIL change
    SCREEN , , 0, 0: LOCATE , , 0: SCREEN , , 1, 0
    IF alt THEN idehl = 1 ELSE idehl = 0
    'convert "alt+letter" scancode to letter's ASCII character
    altletter$ = ""
    IF alt THEN
        IF LEN(k$) = 2 THEN
            k = ASC(RIGHT$(k$, 1))
            FOR c = 65 TO 90
                IF k = idealtcode(c) THEN
                    altletter$ = CHR$(c)
                    EXIT FOR
                END IF
            NEXT
        END IF
    END IF
    '-------- end of read input --------

    '-------- generic input response --------
    info = 0
    IF k$ = "" THEN k$ = CHR$(255)
    IF k$ = CHR$(9) THEN focus = focus + 1
    IF k$ = CHR$(0) + CHR$(15) THEN focus = focus - 1
    IF focus < 1 THEN focus = lastfocus
    IF focus > lastfocus THEN focus = 1
    f = 1
    FOR i = 1 TO 100
        t = o(i).typ
        IF t THEN
            focusoffset = focus - f
            ideupdateobj o(i), focus, f, focusoffset, k$, altletter$, mb, mousedown, mouseup, mx, my, info
        END IF
    NEXT
    '-------- end of generic input response --------

    'specific post controls
    IF k$ = CHR$(27) or k$=chr$(13) or (focus = 1 AND info <> 0) then EXIT SUB
    'end of custom controls

    mousedown = 0
    mouseup = 0
LOOP
END SUB



FUNCTION ideyesnobox$ (titlestr$,messagestr$) 'returns "Y" or "N"
'-------- generic dialog box header --------
PCOPY 3, 0
PCOPY 0, 2
PCOPY 0, 1
SCREEN , , 1, 0
focus = 1
DIM p AS idedbptype
DIM o(1 TO 100) AS idedbotype
DIM oo AS idedbotype
DIM sep AS STRING * 1
sep = CHR$(0)
'-------- end of generic dialog box header --------

'-------- init --------
i = 0
w=len(messagestr$)+2
w2=len(titlestr$)+4
if w<w2 then w=w2
idepar p, w, 4, titlestr$

i = i + 1
o(i).typ = 3
o(i).y = 4
o(i).txt = idenewtxt("#Yes" + sep + "#No")
o(i).def = 1
'-------- end of init --------

'-------- generic init --------
FOR i = 1 TO 100: o(i).par = p: NEXT 'set parent info of objects
'-------- end of generic init --------

DO 'main loop

    '-------- generic display dialog box & objects --------
    idedrawpar p
    f = 1: cx = 0: cy = 0
    FOR i = 1 TO 100
        IF o(i).typ THEN
            'prepare object
            o(i).foc = focus - f 'focus offset
            o(i).cx = 0: o(i).cy = 0
            idedrawobj o(i), f 'display object
            IF o(i).cx THEN cx = o(i).cx: cy = o(i).cy
        END IF
    NEXT i
    lastfocus = f - 1
    '-------- end of generic display dialog box & objects --------

    '-------- custom display changes --------
    COLOR 0, 7: LOCATE p.y + 2, p.x + 2: PRINT messagestr$;
    '-------- end of custom display changes --------

    'update visual page and cursor position
    PCOPY 1, 0
    IF cx THEN SCREEN , , 0, 0: LOCATE cy, cx, 1: SCREEN , , 1, 0

    '-------- read input --------
    change = 0
    DO
        getxymouse
        mx = mousex: my = mousey: mb = mousebutton1
        IF mb <> 0 AND omb = 0 THEN mousedown = 1: change = 1
        IF mb = 0 AND omb <> 0 THEN mouseup = 1: change = 1
        IF mb THEN change = 1
        omb = mb
        k$ = INKEY$: IF LEN(k$) THEN change = 1
        'DEF SEG = 0: alt = PEEK(&H417) AND 8
        alt = 8
        IF alt <> oldalt THEN change = 1
        oldalt = alt

        IF change = 0 THEN _LIMIT 16
    LOOP UNTIL change
    SCREEN , , 0, 0: LOCATE , , 0: SCREEN , , 1, 0
    IF alt THEN idehl = 1 ELSE idehl = 0
    'convert "alt+letter" scancode to letter's ASCII character
    altletter$ = ""
    IF alt THEN
        IF LEN(k$) = 2 THEN
            k = ASC(RIGHT$(k$, 1))
            FOR c = 65 TO 90
                IF k = idealtcode(c) THEN
                    altletter$ = CHR$(c)
                    EXIT FOR
                END IF
            NEXT
        END IF
    END IF
    IF UCASE$(k$) = "Y" THEN altletter$ = "Y"
    IF UCASE$(k$) = "N" THEN altletter$ = "N"

    '-------- end of read input --------

    '-------- generic input response --------
    info = 0
    IF k$ = "" THEN k$ = CHR$(255)
    IF k$ = CHR$(9) THEN focus = focus + 1
    IF k$ = CHR$(0) + CHR$(15) THEN focus = focus - 1
    IF focus < 1 THEN focus = lastfocus
    IF focus > lastfocus THEN focus = 1
    f = 1
    FOR i = 1 TO 100
        t = o(i).typ
        IF t THEN
            focusoffset = focus - f
            ideupdateobj o(i), focus, f, focusoffset, k$, altletter$, mb, mousedown, mouseup, mx, my, info
        END IF
    NEXT
    '-------- end of generic input response --------

    IF k$ = CHR$(27) THEN
        ideyesnobox$ = "N"
        EXIT FUNCTION
    END IF

    IF info THEN
        IF info = 1 THEN ideyesnobox$ = "Y" ELSE ideyesnobox$ = "N"
        EXIT FUNCTION
    END IF

    'end of custom controls
    mousedown = 0
    mouseup = 0
LOOP

END FUNCTION 'yes/no box


FUNCTION idedisplaybox

'-------- generic dialog box header --------
PCOPY 0, 2
PCOPY 0, 1
SCREEN , , 1, 0
focus = 1
DIM p AS idedbptype
DIM o(1 TO 100) AS idedbotype
DIM oo AS idedbotype
DIM sep AS STRING * 1
sep = CHR$(0)
'-------- end of generic dialog box header --------

'-------- init --------
i = 0

'idepar p, 60, 16, "Display"
'note: manually set window position in case display to set too large by accident
p.x = (80 \ 2) - 60 \ 2
p.y = (25 \ 2) - 16 \ 2
p.w = 60
p.h = 16
p.nam = idenewtxt("Display")

a2$ = str2$(idewx)
i = i + 1
o(i).typ = 1
o(i).x = 16
o(i).y = 2
o(i).nam = idenewtxt("#Width")
o(i).txt = idenewtxt(a2$)
o(i).v1 = LEN(a2$)

a2$ = str2$(idewy)
i = i + 1
o(i).typ = 1
o(i).x = 15
o(i).y = 5
o(i).nam = idenewtxt("#Height")
o(i).txt = idenewtxt(a2$)
o(i).v1 = LEN(a2$)

i = i + 1
o(i).typ = 4 'check box
o(i).y = 8
o(i).nam = idenewtxt("Custom #Font:")
o(i).sel = idecustomfont

a2$ = idecustomfontfile$
i = i + 1
o(i).typ = 1
o(i).x = 10
o(i).y = 10
o(i).nam = idenewtxt("File #Name")
o(i).txt = idenewtxt(a2$)
o(i).v1 = LEN(a2$)

a2$ = str2$(idecustomfontheight)
i = i + 1
o(i).typ = 1
o(i).x = 10
o(i).y = 13
o(i).nam = idenewtxt("#Row Height (Pixels)")
o(i).txt = idenewtxt(a2$)
o(i).v1 = LEN(a2$)

i = i + 1
o(i).typ = 3
o(i).y = 16
o(i).txt = idenewtxt("OK" + sep + "#Cancel")
o(i).def = 1
'-------- end of init --------

'-------- generic init --------
FOR i = 1 TO 100: o(i).par = p: NEXT 'set parent info of objects
'-------- end of generic init --------

DO 'main loop


    '-------- generic display dialog box & objects --------
    idedrawpar p
    f = 1: cx = 0: cy = 0
    FOR i = 1 TO 100
        IF o(i).typ THEN

            'prepare object
            o(i).foc = focus - f 'focus offset
            o(i).cx = 0: o(i).cy = 0
            idedrawobj o(i), f 'display object
            IF o(i).cx THEN cx = o(i).cx: cy = o(i).cy
        END IF
    NEXT i
    lastfocus = f - 1
    '-------- end of generic display dialog box & objects --------

    '-------- custom display changes --------
    COLOR 0, 7: LOCATE p.y + 2, p.x + 2: PRINT "Window Size -";
    COLOR 0, 7: LOCATE p.y + 9, p.x + 29: PRINT " Monospace TTF Font ";
    '-------- end of custom display changes --------

    'update visual page and cursor position
    PCOPY 1, 0
    IF cx THEN SCREEN , , 0, 0: LOCATE cy, cx, 1: SCREEN , , 1, 0

    '-------- read input --------
    change = 0
    DO
        getxymouse
        mx = mousex: my = mousey: mb = mousebutton1
        IF mb <> 0 AND omb = 0 THEN mousedown = 1: change = 1
        IF mb = 0 AND omb <> 0 THEN mouseup = 1: change = 1
        IF mb THEN change = 1
        omb = mb
        k$ = INKEY$: IF LEN(k$) THEN change = 1
        DEF SEG = 0: alt = PEEK(&H417) AND 8: IF alt <> oldalt THEN change = 1
        oldalt = alt

        IF change = 0 THEN _LIMIT 16
    LOOP UNTIL change
    SCREEN , , 0, 0: LOCATE , , 0: SCREEN , , 1, 0
    IF alt THEN idehl = 1 ELSE idehl = 0
    'convert "alt+letter" scancode to letter's ASCII character
    altletter$ = ""
    IF alt THEN
        IF LEN(k$) = 2 THEN
            k = ASC(RIGHT$(k$, 1))
            FOR c = 65 TO 90
                IF k = idealtcode(c) THEN
                    altletter$ = CHR$(c)
                    EXIT FOR
                END IF
            NEXT
        END IF
    END IF
    '-------- end of read input --------

    '-------- generic input response --------
    info = 0
    IF k$ = "" THEN k$ = CHR$(255)
    IF k$ = CHR$(9) THEN focus = focus + 1
    IF k$ = CHR$(0) + CHR$(15) THEN focus = focus - 1
    IF focus < 1 THEN focus = lastfocus
    IF focus > lastfocus THEN focus = 1
    f = 1
    FOR i = 1 TO 100
        t = o(i).typ
        IF t THEN
            focusoffset = focus - f
            ideupdateobj o(i), focus, f, focusoffset, k$, altletter$, mb, mousedown, mouseup, mx, my, info
        END IF
    NEXT
    '-------- end of generic input response --------

    'specific post controls

    a$ = idetxt(o(1).txt)
    IF LEN(a$) > 3 THEN a$ = LEFT$(a$, 3) '3 character limit
    FOR i = 1 TO LEN(a$)
        a = ASC(a$, i)
        IF a < 48 OR a > 57 THEN a$ = "": EXIT FOR
        IF i = 2 AND ASC(a$, 1) = 48 THEN a$ = "0": EXIT FOR
    NEXT
    IF focus <> 1 THEN
        IF LEN(a$) THEN a = VAL(a$) ELSE a = 0
        IF a < 80 THEN a$ = "80"
    END IF
    idetxt(o(1).txt) = a$

    a$ = idetxt(o(2).txt)
    IF LEN(a$) > 3 THEN a$ = LEFT$(a$, 3) '3 character limit
    FOR i = 1 TO LEN(a$)
        a = ASC(a$, i)
        IF a < 48 OR a > 57 THEN a$ = "": EXIT FOR
        IF i = 2 AND ASC(a$, 1) = 48 THEN a$ = "0": EXIT FOR
    NEXT
    IF focus <> 2 THEN
        IF LEN(a$) THEN a = VAL(a$) ELSE a = 0
        IF a < 25 THEN a$ = "25"
    END IF
    idetxt(o(2).txt) = a$

    a$ = idetxt(o(4).txt)
    IF LEN(a$) > 1024 THEN a$ = LEFT$(a$, 1024)
    idetxt(o(4).txt) = a$

    a$ = idetxt(o(5).txt)
    IF LEN(a$) > 2 THEN a$ = LEFT$(a$, 2) '2 character limit
    FOR i = 1 TO LEN(a$)
        a = ASC(a$, i)
        IF a < 48 OR a > 57 THEN a$ = "": EXIT FOR
        IF i = 2 AND ASC(a$, 1) = 48 THEN a$ = "0": EXIT FOR
    NEXT
    IF focus <> 5 THEN
        IF LEN(a$) THEN a = VAL(a$) ELSE a = 0
        IF a < 16 THEN a$ = "16"
    END IF
    idetxt(o(5).txt) = a$



    IF k$ = CHR$(27) OR (focus = 7 AND info <> 0) THEN EXIT FUNCTION
    IF k$ = CHR$(13) OR (focus = 6 AND info <> 0) THEN

        x = 0 'change to custom font

        'get size in v%
        v$ = idetxt(o(5).txt): IF v$ = "" THEN v$ = "0"
        v% = VAL(v$)
        IF v% < 16 THEN v% = 16
        IF v% > 99 THEN v% = 99
        IF v% <> idecustomfontheight THEN x = 1

        IF o(3).sel <> idecustomfont THEN
            IF o(3).sel = 0 THEN
                _FONT 16
                _FREEFONT idecustomfonthandle
            ELSE
                x = 1
            END IF
        END IF

        v$ = idetxt(o(4).txt): IF v$ <> idecustomfontfile$ THEN x = 1

        IF o(3).sel = 1 AND x = 1 THEN
            oldhandle = idecustomfonthandle
            idecustomfonthandle = _LOADFONT(v$, v%, "MONOSPACE")
            IF idecustomfonthandle = -1 THEN
                'failed! - revert to default settings
                o(3).sel = 0: idetxt(o(4).txt) = "c:\windows\fonts\lucon.ttf": idetxt(o(5).txt) = "21": _FONT 16
            ELSE
                _FONT idecustomfonthandle
            END IF
            IF idecustomfont = 1 THEN _FREEFONT oldhandle
        END IF

        'save changes
        OPEN ".\internal\temp\options.bin" FOR BINARY AS #150

        SEEK #150, 7

        v$ = idetxt(o(1).txt): IF v$ = "" THEN v$ = "0"
        v% = VAL(v$)
        IF v% < 80 THEN v% = 80
        IF v% > 999 THEN v% = 999
        PUT #150, , v%
        IF v% <> idewx THEN idedisplaybox = 1
        idewx = v%

        v$ = idetxt(o(2).txt): IF v$ = "" THEN v$ = "0"
        v% = VAL(v$)
        IF v% < 25 THEN v% = 25
        IF v% > 999 THEN v% = 999
        PUT #150, , v%
        IF v% <> idewy THEN idedisplaybox = 1
        idewy = v%

        v% = o(3).sel
        IF v% <> 0 THEN v% = 1
        PUT #150, , v%
        idecustomfont = v%

        v$ = idetxt(o(4).txt)
        IF LEN(v$) > 1024 THEN v$ = LEFT$(v$, 1024)
        idecustomfontfile$ = v$
        v$ = v$ + SPACE$(1024 - LEN(v$))
        PUT #150, , v$

        v$ = idetxt(o(5).txt): IF v$ = "" THEN v$ = "0"
        v% = VAL(v$)
        IF v% < 16 THEN v% = 16
        IF v% > 99 THEN v% = 99
        PUT #150, , v%
        idecustomfontheight = v%

        CLOSE #150
        EXIT FUNCTION
    END IF

    'end of custom controls

    mousedown = 0
    mouseup = 0
LOOP
END FUNCTION


FUNCTION HashValue& (a$) 'returns the hash table value of a string
'[5(first)][5(second)][5(last)][5(2nd-last)][3(length AND 7)][1(first char is underscore)]
l = LEN(a$)
IF l = 0 THEN EXIT FUNCTION 'an (invalid) NULL string equates to 0
a = ASC(a$)
IF a <> 95 THEN 'does not begin with underscore
  SELECT CASE l
    CASE 1
      HashValue& = hash1char(a) + 1048576
      EXIT FUNCTION
    CASE 2
      HashValue& = hash2char(CVI(a$)) + 2097152
      EXIT FUNCTION
    CASE 3
      HashValue& = hash2char(CVI(a$)) + hash1char(ASC(a$, 3)) * 1024 + 3145728
      EXIT FUNCTION
    CASE ELSE
      HashValue& = hash2char(CVI(a$)) + hash2char(ASC(a$, l) + ASC(a$, l - 1) * 256) * 1024 + (l AND 7) * 1048576
      EXIT FUNCTION
  END SELECT
ELSE 'does begin with underscore
  SELECT CASE l
    CASE 1
      HashValue& = (1048576 + 8388608): EXIT FUNCTION 'note: underscore only is illegal in QB64 but supported by hash
    CASE 2
      HashValue& = hash1char(ASC(a$, 2)) + (2097152 + 8388608)
      EXIT FUNCTION
    CASE 3
      HashValue& = hash2char(ASC(a$, 2) + ASC(a$, 3) * 256) + (3145728 + 8388608)
      EXIT FUNCTION
    CASE 4
      HashValue& = hash2char((CVL(a$) AND &HFFFF00) \ 256) + hash1char(ASC(a$, 4)) * 1024 + (4194304 + 8388608)
      EXIT FUNCTION
    CASE ELSE
      HashValue& = hash2char((CVL(a$) AND &HFFFF00) \ 256) + hash2char(ASC(a$, l) + ASC(a$, l - 1) * 256) * 1024 + (l AND 7) * 1048576 + 8388608
      EXIT FUNCTION
  END SELECT
END IF
END FUNCTION

SUB HashAdd (a$, flags, reference)

'find the index to use
IF HashListFreeLast > 0 THEN
  'take from free list
  i = HashListFree(HashListFreeLast)
  HashListFreeLast = HashListFreeLast - 1
ELSE
  IF HashListNext > HashListSize THEN
    'double hash list size
    HashListSize = HashListSize * 2
    REDIM _PRESERVE HashList(1 TO HashListSize) AS HashListItem
    REDIM _PRESERVE HashListName(1 TO HashListSize) AS STRING * 256
  END IF
  i = HashListNext
  HashListNext = HashListNext + 1
END IF

'setup links to index
x = HashValue(a$)
i2 = HashTable(x)
IF i2 THEN
  i3 = HashList(i2).LastItem
  HashList(i2).LastItem = i
  HashList(i3).NextItem = i
  HashList(i).PrevItem = i3
ELSE
  HashTable(x) = i
  HashList(i).PrevItem = 0
  HashList(i).LastItem = i
END IF
HashList(i).NextItem = 0

'set common hashlist values
HashList(i).Flags = flags
HashList(i).Reference = reference
HashListName(i) = UCASE$(a$)

END SUB

FUNCTION HashFind (a$, searchflags, resultflags, resultreference)
'(0,1,2)z=hashfind[rev]("RUMI",Hashflag_label,resflag,resref)
'0=doesn't exist
'1=found, no more items to scan
'2=found, more items still to scan
i = HashTable(HashValue(a$))
IF i THEN
  ua$ = UCASE$(a$)+space$(256-len(a$))
  hashfind_next:
  f = HashList(i).Flags
  IF searchflags AND f THEN 'flags in common
    IF HashListName(i) = ua$ THEN
      resultflags = f
      resultreference = HashList(i).Reference
      i2 = HashList(i).NextItem
      IF i2 THEN
        HashFind = 2
        HashFind_NextListItem = i2
        HashFind_Reverse = 0
        HashFind_SearchFlags = searchflags
        HashFind_Name = ua$
        HashRemove_LastFound = i
        EXIT FUNCTION
      ELSE
        HashFind = 1
        HashRemove_LastFound = i
        EXIT FUNCTION
      END IF
    END IF
  END IF
  i = HashList(i).NextItem
  IF i THEN GOTO hashfind_next
END IF
END FUNCTION

FUNCTION HashFindRev (a$, searchflags, resultflags, resultreference)
'(0,1,2)z=hashfind[rev]("RUMI",Hashflag_label,resflag,resref)
'0=doesn't exist
'1=found, no more items to scan
'2=found, more items still to scan
i = HashTable(HashValue(a$))
IF i THEN
  i = HashList(i).LastItem
  ua$ = UCASE$(a$)+space$(256-len(a$))
  hashfindrev_next:
  f = HashList(i).Flags
  IF searchflags AND f THEN 'flags in common
    IF HashListName(i) = ua$ THEN
      resultflags = f
      resultreference = HashList(i).Reference
      i2 = HashList(i).PrevItem
      IF i2 THEN
        HashFindRev = 2
        HashFind_NextListItem = i2
        HashFind_Reverse = 1
        HashFind_SearchFlags = searchflags
        HashFind_Name = ua$
        HashRemove_LastFound = i
        EXIT FUNCTION
      ELSE
        HashFindRev = 1
        HashRemove_LastFound = i
        EXIT FUNCTION
      END IF
    END IF
  END IF
  i = HashList(i).PrevItem
  IF i THEN GOTO hashfindrev_next
END IF
END FUNCTION

FUNCTION HashFindCont (resultflags, resultreference)
'(0,1,2)z=hashfind[rev](resflag,resref)
'0=no more items exist
'1=found, no more items to scan
'2=found, more items still to scan
IF HashFind_Reverse THEN

  i = HashFind_NextListItem
  hashfindrevc_next:
  f = HashList(i).Flags
  IF HashFind_SearchFlags AND f THEN 'flags in common
    IF HashListName(i) = HashFind_Name THEN
      resultflags = f
      resultreference = HashList(i).Reference
      i2 = HashList(i).PrevItem
      IF i2 THEN
        HashFindCont = 2
        HashFind_NextListItem = i2
        HashRemove_LastFound = i
        EXIT FUNCTION
      ELSE
        HashFindCont = 1
        HashRemove_LastFound = i
        EXIT FUNCTION
      END IF
    END IF
  END IF
  i = HashList(i).PrevItem
  IF i THEN GOTO hashfindrevc_next
  EXIT FUNCTION

ELSE

  i = HashFind_NextListItem
  hashfindc_next:
  f = HashList(i).Flags
  IF HashFind_SearchFlags AND f THEN 'flags in common
    IF HashListName(i) = HashFind_Name THEN
      resultflags = f
      resultreference = HashList(i).Reference
      i2 = HashList(i).NextItem
      IF i2 THEN
        HashFindCont = 2
        HashFind_NextListItem = i2
        HashRemove_LastFound = i
        EXIT FUNCTION
      ELSE
        HashFindCont = 1
        HashRemove_LastFound = i
        EXIT FUNCTION
      END IF
    END IF
  END IF
  i = HashList(i).NextItem
  IF i THEN GOTO hashfindc_next
  EXIT FUNCTION

END IF
END FUNCTION

SUB HashRemove

i = HashRemove_LastFound

'add to free list
HashListFreeLast = HashListFreeLast + 1
IF HashListFreeLast > HashListFreeSize THEN
  HashListFreeSize = HashListFreeSize * 2
  REDIM _PRESERVE HashListFree(1 TO HashListFreeSize) AS LONG
END IF
HashListFree(HashListFreeLast) = i

'unlink
i1 = HashList(i).PrevItem
IF i1 THEN
  'not first item in list
  i2 = HashList(i).NextItem
  IF i2 THEN
    '(not first and) not last item
    HashList(i1).NextItem = i2
    HashList(i2).LastItem = i1
  ELSE
    'last item
    x = HashTable(HashValue(HashListName$(i)))
    HashList(x).LastItem = i1
    HashList(i1).NextItem = 0
  END IF
ELSE
  'first item in list
  x = HashTable(HashValue(HashListName$(i)))
  i2 = HashList(i).NextItem
  IF i2 THEN
    '(first item but) not last item
    HashTable(x) = i2
    HashList(i2).PrevItem = 0
    HashList(i2).LastItem = HashList(i).LastItem
  ELSE
    '(first and) last item
    HashTable(x) = 0
  END IF
END IF

END SUB

SUB HashDump 'used for debugging purposes
fh = FREEFILE
OPEN "hashdump.txt" FOR OUTPUT AS #fh
b$ = "12345678901234567890123456789012}"
FOR x = 0 TO 16777215
  IF HashTable(x) THEN

    PRINT #fh, "START HashTable("; x; "):"
    i = HashTable(x)

    'validate
    lasti = HashList(i).LastItem
    IF HashList(i).LastItem = 0 OR HashList(i).PrevItem <> 0 OR HashValue(HashListName(i)) <> x THEN GOTO corrupt

    PRINT #fh, "  HashList("; i; ").LastItem="; HashList(i).LastItem
    hashdumpnextitem:
    x$ = "  [" + STR$(i) + "]" + HashListName(i)

    f = HashList(i).Flags
    x$ = x$ + ",.Flags=" + STR$(f) + "{"
    FOR z = 1 TO 32
      ASC(b$, z) = (f AND 1) + 48
      f = f \ 2
    NEXT
    x$ = x$ + b$

    x$ = x$ + ",.Reference=" + STR$(HashList(i).Reference)

    PRINT #fh, x$

    'validate
    i1 = HashList(i).PrevItem
    i2 = HashList(i).NextItem
    IF i1 THEN
      IF HashList(i1).NextItem <> i THEN GOTO corrupt
    END IF
    IF i2 THEN
      IF HashList(i2).PrevItem <> i THEN GOTO corrupt
    END IF
    IF i2 = 0 THEN
      IF lasti <> i THEN GOTO corrupt
    END IF

    i = HashList(i).NextItem
    IF i THEN GOTO hashdumpnextitem

    PRINT #fh, "END HashTable("; x; ")"
  END IF
NEXT
CLOSE #fh

EXIT SUB
corrupt:
PRINT #fh, "HASH TABLE CORRUPT!" 'should never happen
CLOSE #fh

END SUB

SUB HashClear 'clear entire hash table

HashListSize = 65536
HashListNext = 1
HashListFreeSize = 1024
HashListFreeLast = 0
REDIM HashList(1 TO HashListSize) AS HashListItem
REDIM HashListName(1 TO HashListSize) AS STRING * 256
REDIM HashListFree(1 TO HashListFreeSize) AS LONG
REDIM HashTable(16777215) AS LONG '64MB lookup table with indexes to the hashlist

HashFind_NextListItem = 0
HashFind_Reverse = 0
HashFind_SearchFlags = 0
HashFind_Name = ""
HashRemove_LastFound = 0

END SUB

sub iderestrict417 (p417)
x=0
if p417 and 4 then x=x+1
if p417 and 8 then x=x+1
if x>1 then p417=p417 and 243
end sub






















































































'######## UPDATE.BAS ########

FUNCTION decompress_2_huff$ (a$)
IF ASC(a$) <> 2 THEN SCREEN 0,,0,0: PRINT "decompress_2_huff: invalid type": END

'get no. of branches and encoded bits
totalbits = ASC(a$, 5)
totalbits = totalbits * 256 + ASC(a$, 4)
totalbits = totalbits * 256 + ASC(a$, 3)
totalbits = totalbits * 256 + ASC(a$, 2)
totalbytes = (totalbits + 7) \ 8
nb = (LEN(a$) - totalbytes - 5) \ 3 'number of branches

'read branches
FOR i = 0 TO nb - 1
    v = ASC(a$, 6 + i * 3) + ASC(a$, 6 + i * 3 + 1) * 256 + ASC(a$, 6 + i * 3 + 2) * 65536
    huff_branch0(i) = v AND 4095
    huff_branch1(i) = v \ 4096
NEXT

'buffer for decompression
bufsiz = totalbits * 8
IF bufsiz > 1000000 THEN bufsiz = 1000000
b$ = SPACE$(bufsiz)

'decompress
byteoff = LEN(a$) - totalbytes + 1
bitmask = 1
x = 0
b = 0 'branch
byteval = ASC(a$, byteoff)
huffreadbits:
bit = byteval AND bitmask
totalbits = totalbits - 1

IF bit THEN
    b = huff_branch1(b)
ELSE
    b = huff_branch0(b)
END IF

IF huff_branch0(b) = 0 THEN
    x = x + 1: IF x > bufsiz THEN b$ = b$ + SPACE$(bufsiz): bufsiz = bufsiz * 2
    ASC(b$, x) = huff_branch1(b)
    IF totalbits = 0 THEN GOTO hufffinished
    b = 0
END IF

bitmask = bitmask * 2: IF bitmask = 256 THEN bitmask = 1: byteoff = byteoff + 1: byteval = ASC(a$, byteoff)
GOTO huffreadbits

hufffinished:
decompress_2_huff$ = LEFT$(b$, x)

END FUNCTION

FUNCTION compress_2_huff$ (a$)

'count weights
FOR i = 0 TO 255
    huff_count(i) = 0
NEXT
FOR i = 1 TO LEN(a$)
    v = ASC(a$, i)
    huff_count(v) = huff_count(v) + 1
NEXT

'setup initial branches
b = 0 'note: pos 0 reserved for initial branch
FOR i = 0 TO 255
    IF huff_count(i) THEN
        b = b + 1
        huff_branch(i) = b
        huff_weight(b) = huff_count(i)
        huff_bit0link(b) = 0 'it's a value
        huff_bit1link(b) = i 'the value
        huff_parent(b) = -1
    END IF
NEXT

IF b = 1 THEN 'create a fake branch to allow for 1 bit encoding of uniform data
    b = b + 1
    huff_weight(b) = 1
    huff_bit0link(b) = 0 'it's a value
    huff_bit1link(b) = 0 'the value
    huff_parent(b) = -1
END IF

'find 2 lowest weights
huff_buildbranches:
w1 = 2147483647
w2 = 2147483647
FOR i = 1 TO b
    w = huff_weight(i)
    IF w <> 2147483647 THEN
        'pump up (w1=lowest, w2=second lowest)
        IF w < w1 THEN
            w2 = w1: i2 = i1
            w1 = w: i1 = i
        ELSE
            IF w < w2 THEN w2 = w: i2 = i
        END IF
    END IF
NEXT

'form new branch
IF w1 <> 2147483647 AND w2 <> 2147483647 THEN 'combine branches
    b = b + 1
    huff_weight(b) = huff_weight(i1) + huff_weight(i2)
    huff_parent(b) = -1
    huff_bit0link(b) = i1: huff_bit1link(b) = i2
    huff_weight(i1) = 2147483647: huff_weight(i2) = 2147483647
    huff_parent(i1) = b: huff_parent(i2) = b
    huff_bit(i1) = 0: huff_bit(i2) = 1
    GOTO huff_buildbranches
END IF

'note: i1 contains root branch
'copy final branch links to position 0
huff_bit0link(0) = huff_bit0link(i1): huff_bit1link(0) = huff_bit1link(i1)
lastbranch = b - 1 '*for storage of key*

'build bit masks (clearing remainder of final byte of each to 0)
totalbits = 0
FOR i = 0 TO 255
    IF huff_count(i) THEN

        'calc number of bits
        nbits = 0
        b = huff_branch(i)
        huff_calcnbits:
        p = huff_parent(b)
        IF p <> -1 THEN nbits = nbits + 1: b = p: GOTO huff_calcnbits
        huff_mask_bits(i) = nbits
        totalbits = totalbits + nbits * huff_count(i)

        base = i * 256 'base offset

        'clear bytes
        bytes = ((nbits + 7) + 7) \ 8
        FOR x = 0 TO 7
            byteo = base + (x * 32)
            FOR x2 = 0 TO bytes - 1
                huff_mask(byteo + x2) = 0
            NEXT
        NEXT

        'create mask
        o1 = nbits
        b = huff_branch(i)

        huff_nextbranch:
        o1 = o1 - 1
        IF huff_parent(b) <> -1 THEN

            IF huff_bit(b) THEN
                bitval = huff_bitval(o1 AND 7)
                FOR o2 = 0 TO 7
                    o = o1 + o2
                    byteo = base + (o2 * 32) + (o \ 8)
                    huff_mask(byteo) = huff_mask(byteo) OR bitval
                    bitval = bitval + bitval: IF bitval = 256 THEN bitval = 1
                NEXT
            END IF 'bit set
            b = huff_parent(b)
            GOTO huff_nextbranch
        END IF

    END IF
NEXT

totalbytes = (totalbits + 7) \ 8
totalbytes = totalbytes + (lastbranch + 1) * 3 + 4 + 1
b$ = STRING$(totalbytes, 0)
ASC(b$, 1) = 2 'type

'create key
'[4]store number of bits
ASC(b$, 2) = totalbits AND 255: totalbits = totalbits \ 256
ASC(b$, 3) = totalbits AND 255: totalbits = totalbits \ 256
ASC(b$, 4) = totalbits AND 255: totalbits = totalbits \ 256
ASC(b$, 5) = totalbits

'[3*(lastbranch+1)]store branches
x = 5
FOR i = 0 TO lastbranch
    v = huff_bit0link(i) + huff_bit1link(i) * 4096
    x = x + 1: ASC(b$, x) = v AND 255
    x = x + 1: ASC(b$, x) = (v \ 256) AND 255
    x = x + 1: ASC(b$, x) = v \ 65536
NEXT

'store huffman encoded data (using masks to speed up process)
x = x + 1
bitpos = 0
FOR z = 1 TO LEN(a$)
    v = ASC(a$, z)
    nbits = huff_mask_bits(v)
    nbytes = (bitpos + nbits + 7) \ 8
    o = v * 256 + bitpos * 32
    FOR i = 0 TO nbytes - 1
        ASC(b$, x) = ASC(b$, x) OR huff_mask(o + i)
        x = x + 1
    NEXT
    bitpos = (bitpos + nbits) AND 7
    IF bitpos <> 0 THEN x = x - 1
NEXT

compress_2_huff$ = b$
END FUNCTION

FUNCTION decompress_1_rle$ (a$)
IF ASC(a$) <> 1 THEN SCREEN 0,,0,0: PRINT "decompress_1_rle: invalid type": END

'calculate size of final string required
i = 2
siz = 0
x = ASC(a$, i)
DO WHILE x
    IF x AND 128 THEN
        i = i + 1: x = ASC(a$, i)
        IF x AND 128 THEN
            i = i + 1: x = ASC(a$, i)
            IF x2 AND 128 THEN
                i = i + 1: x = ASC(a$, i)
            END IF
        END IF
    END IF
    i = i + 2 'skip value
    s = ASC(a$, i)
    IF s = 255 THEN
        i = i + 1: s = ASC(a$, i)
        i = i + 1: s2 = ASC(a$, i)
        IF s = 255 AND s2 = 255 THEN
            i = i + 1
            s = ASC(a$, i + 3)
            s = s * 256 + ASC(a$, i + 2)
            s = s * 256 + ASC(a$, i + 1)
            s = s * 256 + ASC(a$, i)
            i = i + 3
        ELSE
            s = s + s2 * 256
        END IF
    END IF
    siz = siz + s + 4
    i = i + 1: x = ASC(a$, i)
LOOP
i = i + 1 'i=beginning of uncompressed data
siz = siz + (LEN(a$) - i + 1)
b$ = SPACE$(siz)

'begin decompression
h = 1
p = 1
ins = i
n = LEN(a$)

unrle_getnext:
h = h + 1: x = ASC(a$, h)
IF x AND 128 THEN
    h = h + 1: x2 = ASC(a$, h): x = (x AND 127) + (x2 AND 127) * 128
    IF x2 AND 128 THEN
        h = h + 1: x2 = ASC(a$, h): x = x + (x2 AND 127) * 16384
        IF x2 AND 128 THEN
            h = h + 1: x2 = ASC(a$, h): x = x + (x2 AND 127) * 2097152
        END IF
    END IF
END IF
IF x = 0 THEN
    ins = 2147483647
ELSE
    ins = ins + x - 1
    h = h + 1: v = ASC(a$, h)
    h = h + 1
    s = ASC(a$, h)
    IF s = 255 THEN
        h = h + 1: s = ASC(a$, h)
        h = h + 1: s2 = ASC(a$, h)
        IF s = 255 AND s2 = 255 THEN
            h = h + 1
            s = ASC(a$, h + 3)
            s = s * 256 + ASC(a$, h + 2)
            s = s * 256 + ASC(a$, h + 1)
            s = s * 256 + ASC(a$, h)
            h = h + 3
        ELSE
            s = s + s2 * 256
        END IF
    END IF
    c = s + 4
END IF

n2 = ins - 1
IF n2 > n THEN n2 = n
FOR i = i TO n2
    ASC(b$, p) = ASC(a$, i): p = p + 1
NEXT
IF ins <> 2147483647 THEN
    FOR x = 1 TO c
        ASC(b$, p) = v: p = p + 1
    NEXT
    GOTO unrle_getnext
END IF

decompress_1_rle$ = b$

END FUNCTION

FUNCTION compress_1_rle$ (a$) 'IMPORTANT: the contents of a$ are corrupted in producing rle$
'[1-4:offset from previous position][1:val][[1]/{255}[2]/{65535}[4]]:repeats-4]
' ^top bit indicates also use bits of following byte (max offset=268435456)
'                                                 ^255 indicates larger format used
n = LEN(a$)
h$ = SPACE$(LEN(a$) + 2)
ASC(h$, 1) = 1 'method 1
hp = 2 'header position
i = 1 'source position
p = 1 'dest position
o = 1 'offset to reference position from
DO
    v = ASC(a$, i)
    FOR i2 = i + 1 TO n
        IF v <> ASC(a$, i2) THEN EXIT FOR
    NEXT
    reps = i2 - i

    x = p - o + 1 'x=relative offset to insert data+1

    IF x <= 127 THEN
        IF reps < 4 GOTO no_rle
        ASC(h$, hp) = x: hp = hp + 1
    ELSEIF x <= 16383 THEN
        IF reps < 5 GOTO no_rle
        ASC(h$, hp) = (x AND 127) + 128: x = x \ 128: hp = hp + 1
        ASC(h$, hp) = x: hp = hp + 1
    ELSEIF x <= 2097151 THEN
        IF reps < 6 GOTO no_rle
        ASC(h$, hp) = (x AND 127) + 128: x = x \ 128: hp = hp + 1
        ASC(h$, hp) = (x AND 127) + 128: x = x \ 128: hp = hp + 1
        ASC(h$, hp) = x: hp = hp + 1
    ELSE
        IF reps < 7 GOTO no_rle
        ASC(h$, hp) = (x AND 127) + 128: x = x \ 128: hp = hp + 1
        ASC(h$, hp) = (x AND 127) + 128: x = x \ 128: hp = hp + 1
        ASC(h$, hp) = (x AND 127) + 128: x = x \ 128: hp = hp + 1
        ASC(h$, hp) = x: hp = hp + 1
    END IF
    o = p

    'encode value
    ASC(h$, hp) = v: hp = hp + 1
    'encode reps-4
    reps = reps - 4
    IF reps >= 255 THEN
        ASC(h$, hp) = 255: hp = hp + 1
        IF reps >= 65535 THEN
            ASC(h$, hp) = 255: hp = hp + 1
            ASC(h$, hp) = 255: hp = hp + 1
            ASC(h$, hp) = reps AND 255: reps = reps \ 256: hp = hp + 1
            ASC(h$, hp) = reps AND 255: reps = reps \ 256: hp = hp + 1
            ASC(h$, hp) = reps AND 255: reps = reps \ 256: hp = hp + 1
            ASC(h$, hp) = reps: hp = hp + 1
        ELSE
            ASC(h$, hp) = reps AND 255: reps = reps \ 256: hp = hp + 1
            ASC(h$, hp) = reps: hp = hp + 1
        END IF
    ELSE
        ASC(h$, hp) = reps: hp = hp + 1
    END IF


    GOTO rle_applied

    no_rle: 'not enough repeats to encode
    IF i <> p THEN
        FOR i3 = i TO i2 - 1
            ASC(a$, p) = ASC(a$, i3)
            p = p + 1
        NEXT
    ELSE
        p = p + (i2 - i)
    END IF

    rle_applied:
    i = i2

LOOP UNTIL i > n

'finialize header
ASC(h$, hp) = 0: hp = hp + 1

compress_1_rle$ = LEFT$(h$, hp - 1) + LEFT$(a$, p - 1)

END FUNCTION

FUNCTION compress$ (a$)
a$ = CHR$(0) + a$
a$ = compress_1_rle$(a$)
a$ = compress_2_huff$(a$)
compress$ = a$
END FUNCTION

FUNCTION decompress$ (a$)
x = ASC(a$)
DO WHILE x
    IF x = 1 THEN a$ = decompress_1_rle$(a$)
    IF x = 2 THEN a$ = decompress_2_huff$(a$)
    x = ASC(a$)
LOOP
a$ = RIGHT$(a$, LEN(a$) - 1) 'remove NULL byte indicating compression complete
decompress$ = a$
END FUNCTION

FUNCTION download (url$, file$) 'note: set file$ to "" to use string data only

PRINT "Downloading " + CHR$(34) + url$ + CHR$(34)

url2$ = url$
x = INSTR(url2$, "/")
IF x THEN url2$ = LEFT$(url$, x - 1)
c = _OPENCLIENT("TCP/IP:80:" + url2$)
IF c = 0 THEN
    EXIT FUNCTION
END IF

e$ = CHR$(13) + CHR$(10)
url3$ = RIGHT$(url$, LEN(url$) - x + 1)
x$ = "GET " + url3$ + " HTTP/1.1" + e$
x$ = x$ + "Host: " + url2$ + e$ + e$
PUT #c, , x$

PRINT "[                                                  ]";
LOCATE CSRLIN, 2
dp = 0
dp2 = 0

lasttime!=TIMER
cancelmess=0

DO
    _DELAY 0.01
    GET #c, , a2$
    a$ = a$ + a2$

if len(a2$)=0 then
if TIMER>lasttime!+20 then
if cancelmess=0 then
cancelmess=1
cl=csrlin
cp=pos(0)
locate 25,1
print "Download may still be active! To abort this download press the ESC key.";
locate cl,cp
end if
end if
else
lasttime!=TIMER
end if

if cancelmess=1 then
if inkey$=chr$(27) then
print
close #c
EXIT FUNCTION
end if
end if

    IF l THEN 'length is known
        IF i3 <> 0 THEN
            dp = (LEN(a$) - i3) / l * 50
            IF dp > 50 THEN dp = 50
            IF dp < 0 THEN dp = 0
            DO WHILE dp2 < dp
                PRINT "þ";
                dp2 = dp2 + 1
            LOOP
        END IF
    END IF

    i = INSTR(a$, "Content-Length:")
    IF i THEN
        i2 = INSTR(i, a$, e$)
        IF i2 THEN
            l = VAL(MID$(a$, i + 15, i2 - i - 14))
            i3 = INSTR(i2, a$, e$ + e$)
            IF i3 THEN
                i3 = i3 + 4 'move i3 to start of data
                IF (LEN(a$) - i3 + 1) = l THEN
                    CLOSE c
                    Download_String$ = MID$(a$, i3, l)
                    IF file$ <> "" THEN
                        fh = FREEFILE
                        OPEN file$ FOR OUTPUT AS #fh: CLOSE #fh
                        OPEN file$ FOR BINARY AS #fh
                        PUT #fh, , d$
                        CLOSE #fh
                    END IF
                    download = -1
                    DO WHILE dp2 < 50
                        PRINT "þ";
                        dp2 = dp2 + 1
                    LOOP
                    PRINT
                    EXIT FUNCTION
                END IF 'availabledata=l
            END IF 'i3
        END IF 'i2
    END IF 'i
LOOP
END FUNCTION

FUNCTION chksum&& (f$)
DIM c AS _INTEGER64, x AS _INTEGER64, b AS _INTEGER64
OPEN f$ FOR BINARY ACCESS READ SHARED AS #123
a$ = SPACE$(LOF(123))
GET #123, , a$
CLOSE #123
c = LEN(a$)
b = 1
$CHECKING:OFF
FOR i = 1 TO LEN(a$)
    c = c + (b * (ASC(a$, i) + 1))
    b = b + b
    IF b = 281474976710656 THEN b = 1
NEXT
$CHECKING:ON
chksum&& = c
END FUNCTION

FUNCTION BeginDownload (url$)
FOR i = 1 TO DLs
    IF DL(i).State = 0 THEN EXIT FOR
NEXT
IF i > DLs THEN DLs = DLs + 1
IF i > Maxdls THEN screen 0,,0,0: PRINT "Too many active downloads!": END
url2$ = url$
x = INSTR(url2$, "/")
IF x THEN url2$ = LEFT$(url$, x - 1)
h = _OPENCLIENT("TCP/IP:80:" + url2$)
IF h = 0 THEN EXIT FUNCTION '0=failed
e$ = CHR$(13) + CHR$(10)
url3$ = RIGHT$(url$, LEN(url$) - x + 1)
x$ = "GET " + url3$ + " HTTP/1.1" + e$
x$ = x$ + "Host: " + url2$ + e$ + e$
PUT #h, , x$
DL(i).State = 1
DL(i).Handle = h
DL_Data(i) = ""
BeginDownload = i
END FUNCTION

SUB ContinueDownloads
e$ = CHR$(13) + CHR$(10)
FOR d = 1 TO DLs
    s = DL(d).State
    IF s > 0 THEN
        SELECT CASE s
            CASE 1
                GET #DL(d).Handle, , a2$
                DL_Data(d) = DL_Data(d) + a2$
                a$ = DL_Data(d)
                i = INSTR(a$, "Content-Length:")
                IF i THEN
                    i2 = INSTR(i, a$, e$)
                    IF i2 THEN
                        l = VAL(MID$(a$, i + 15, i2 - i - 14))
                        i3 = INSTR(i2, a$, e$ + e$)
                        IF i3 THEN
                            i3 = i3 + 4 'move i3 to start of data
                            IF (LEN(a$) - i3 + 1) >= l THEN
                                DL_Data(d) = MID$(a$, i3, l)
                                DL(d).State = 2 'finished!
                                CLOSE #DL(d).Handle                              
                            END IF 'availabledata=l
                        END IF 'i3
                    END IF 'i2
                END IF 'i                
            CASE ELSE
                '...
        END SELECT
    END IF
NEXT
END SUB

FUNCTION rippath$ (a$) 'doesn't include final \
FOR i = LEN(a$) TO 1 STEP -1
    IF ASC(a$, i) = 92 THEN rippath$ = LEFT$(a$, i - 1): EXIT FUNCTION
NEXT
END FUNCTION

SUB update (how)
'0=called by IDE via automatic checking
'1=called by IDE from File->Update menu option
'2=called by -c command line compilation via automatic checking (from compilation finished/compilation error)
'3=called by -c command line compilation via automatic checking (from syntax error)

on error goto update_error_handler

v$ = DL_Data(UpdateHandle): DL_Data(UpdateHandle) = "": DL(UpdateHandle).State = 0

'avoid update if multiple instances of QB64 are running
if tempfolderindex<>1 then goto pretendnoupdates
for i=2 to 4
MKDIR ".\internal\temp" + str2$(i)
t$ = ".\internal\temp" + str2$(i) + "\"
update_error=0
OPEN t$ + "temp.bin" FOR OUTPUT LOCK READ WRITE AS #1
if update_error then goto pretendnoupdates
close #1
next

MKDIR ".\internal\update"
MKDIR ".\internal\update\downloads"

'check current version against latest version
uf$ = ".\internal\update\"
OPEN uf$ + "update.txt" FOR BINARY AS #1
IF LOF(1) THEN
    CLOSE #1
    OPEN uf$ + "update.txt" FOR INPUT AS #1: LINE INPUT #1, a$: CLOSE #1
ELSE
    CLOSE #1
    a$ = "UNKNOWN"
END IF
IF a$ = v$ THEN 'latest version installed
pretendnoupdates:
if how=1 then
idemessagebox "Update","No new updates available."
PCOPY 3, 0: SCREEN , , 3, 0: idewait4mous: idewait4alt
end if
ON ERROR GOTO qberror
exit sub
end if

'...ask user if they would like to apply new updates...
if (how=0 and ideupdateauto=0) or how=1 then
what$=ideyesnobox$("Update Available","Download and apply new update?") 'returns "Y" or "N"
PCOPY 3, 0: SCREEN , , 3, 0: idewait4mous: idewait4alt
if what$="N" then
ON ERROR GOTO qberror
exit sub
end if
end if

if how>=2 and ideupdateauto=0 then
if compfailed then compfailed=0 'cancel wait before exit
print "Update available!"
print "Download and apply new update? (Y/N)"
do: _limit 100: k$=ucase$(inkey$): loop until k$="N" or k$="Y"
if k$="N" then
if how=3 then system
ON ERROR GOTO qberror
exit sub
end if
end if

if how=3 and ideupdateauto=1 then 'ensure user sees the error message printed above before continuing
cl=csrlin
locate 25,1: print "Press any key to continue";
do: _LIMIT 100: loop until inkey$<>""
locate 25,1: print "                         ";
locate cl,1
end if

if how<2 then
screen 0,,0,0
color 7,1
cls
end if

print "Updating QB64"

'load current chksums into arrays for faster referencing
OPEN uf$ + "chksums.txt" FOR BINARY AS #1
IF LOF(1) THEN
    CLOSE #1
    'enumerate entries
    n = 0
    OPEN uf$ + "chksums.txt" FOR INPUT AS #1
    DO UNTIL EOF(1)
        LINE INPUT #1, a$: IF LEN(a$) THEN n = n + 1
    LOOP
    CLOSE #1
    if n=0 then n=1
    REDIM _PRESERVE chksums_name(1 TO n) AS STRING
    REDIM _PRESERVE chksums_valstr(1 TO n) AS STRING
    'get entries
    n = 0
    OPEN uf$ + "chksums.txt" FOR INPUT AS #1
    DO UNTIL EOF(1)
        LINE INPUT #1, a$
        IF LEN(a$) THEN
            n = n + 1
            i = INSTR(a$, ",")
            a1$ = LEFT$(a$, i - 1): a2$ = RIGHT$(a$, LEN(a$) - i)
            chksums_name(n) = a1$: chksums_valstr(n) = a2$
        END IF
    LOOP
    CLOSE #1
ELSE
    n = 0
    CLOSE #1
END IF
nchksums = n

url$ = "www.qb64.net/" + v$ + "/"

dlretry2:

OK = download(url$ + "chksums.q", "")

IF NOT OK THEN 

if how<=1 then
PCOPY 3,0:what$=ideyesnobox("Download Failed","Retry?"):PCOPY 3, 0: SCREEN , , 3, 0: idewait4mous: idewait4alt
if what$="Y" then
screen 0,,0,0:color 7,1:cls: goto dlretry2
end if
ON ERROR GOTO qberror
exit sub
end if

print "Download Failed!": print "Retry? (Y/N)"
do: _limit 100: k$=ucase$(inkey$): loop until k$="N" or k$="Y"
if k$="N" then
if compfailed then print "C++ COMPILATION FAILED!" 'redisplay failed message
ON ERROR GOTO qberror
if how=3 then system
exit sub
end if
goto dlretry2

end if







a$ = decompress(Download_String)
OPEN uf$ + "chksums.tmp" FOR OUTPUT AS #1: PRINT #1, a$;: CLOSE #1
OPEN uf$ + "chksums.tmp" FOR INPUT AS #1

'seperate for testing, the same in practise
qf$ = ".\"
qf2$ = ".\"

chksums_updated = 0
files_updated = 0


OPEN "setup.bat" FOR OUTPUT AS #10
PRINT #10, "@ping 127.0.0.1 -n 4 -w 1000 >NUL" 'wait 2 seconds to ensure this program as ended

df$ = uf$ + "downloads\"

n = 0
DO UNTIL EOF(1)
    LINE INPUT #1, a$
    IF LEN(a$) THEN
        n = n + 1
        i = INSTR(a$, ",")
        a1$ = LEFT$(a$, i - 1): a2$ = RIGHT$(a$, LEN(a$) - i)
        IF a2$ <> "0" THEN
            FOR i = 1 TO nchksums
                IF a1$ = chksums_name(i) THEN
                    IF a2$ = chksums_valstr(i) THEN GOTO nochange

'same name, but differing checksum
'before overriding existing file, check if its content matches its existing chksum and warn if it doesn't
            update_error = 0
            OPEN qf$ + a1$ FOR BINARY AS #2
            IF update_error = 0 THEN
                IF LOF(2) THEN
                    CLOSE #2
                    'it exists, so check its chksum
                    c&& = chksum(qf$ + a1$): c$ = LTRIM$(RTRIM$(STR$(c&&)))
if c$<>chksums_valstr(i) then 'possible custom mod warning
chksums_updated = 1

'warning
if how<=1 then
PCOPY 3,0
idemessagebox "This file has been modified by you but will be overwritten!",a1$
PCOPY 3, 0: SCREEN , , 3, 0: idewait4mous: idewait4alt
screen 0,,0,0
color 7,1
cls
end if
if how>=2 then
print "This file has been modified by you but will be overwritten: "+chr$(34)+a1$+chr$(34)
print "Press any key to continue"
do: _limit 100: loop until inkey$<>""
end if

chksums_valstr(i)=c$
end if
                ELSE
                    CLOSE #2
                    KILL qf$ + a1$
                    chksums_valstr(i)="0" 'file no longer exists or is inaccessible
                    chksums_updated = 1
                END IF
            ELSE
            chksums_valstr(i)="0" 'file no longer exists or is inaccessible
            chksums_updated = 1
            END IF
goto foundchksum

                END IF
            NEXT

            chksums_updated = 1
            'chksum index not found, so check if file exists
            update_error = 0
            OPEN qf$ + a1$ FOR BINARY AS #2
            IF update_error = 0 THEN
                IF LOF(2) THEN
                    CLOSE #2
                    'it exists, so add a chksum for it
                    c&& = chksum(qf$ + a1$): c$ = LTRIM$(RTRIM$(STR$(c&&)))
                    nchksums = nchksums + 1
                    REDIM _PRESERVE chksums_name(1 TO nchksums) AS STRING
                    REDIM _PRESERVE chksums_valstr(1 TO nchksums) AS STRING

                    chksums_name(nchksums) = a1$
                    chksums_valstr(nchksums) = c$
                    i = nchksums
                ELSE
                    CLOSE #2
                    KILL qf$ + a1$
                    nchksums = nchksums + 1
                    REDIM _PRESERVE chksums_name(1 TO nchksums) AS STRING
                    REDIM _PRESERVE chksums_valstr(1 TO nchksums) AS STRING
                    i = nchksums
                    GOTO nochksum
                END IF
            ELSE
                'error
                nchksums = nchksums + 1
                REDIM _PRESERVE chksums_name(1 TO nchksums) AS STRING
                REDIM _PRESERVE chksums_valstr(1 TO nchksums) AS STRING
                i = nchksums
            END IF

            foundchksum:
            IF chksums_valstr(i) = a2$ THEN GOTO nochange
            nochksum:
            'set index i with new file's value and download
            chksums_name(i) = a1$
            chksums_valstr(i) = a2$

dlretry:

            PRINT "Getting file:" + a1$ + "(" + LTRIM$(STR$(n)) + ".q)"
            OK = download(url$ + LTRIM$(STR$(n)) + ".q", "")

            IF NOT OK THEN 

if how<=1 then
PCOPY 3,0
what$=ideyesnobox("Download Failed","Retry?")
PCOPY 3, 0: SCREEN , , 3, 0: idewait4mous: idewait4alt
if what$="Y" then
screen 0,,0,0
color 7,1
cls
goto dlretry
end if
ON ERROR GOTO qberror
if how=3 then system
exit sub
end if

print "Download Failed!": print "Retry? (Y/N)"
do: _limit 100: k$=ucase$(inkey$): loop until k$="N" or k$="Y"
if k$="N" then
if compfailed then print "C++ COMPILATION FAILED!" 'redisplay failed message
ON ERROR GOTO qberror
exit sub
end if
goto dlretry

end if


            files_updated = 1
            'put the file in our updates folder
            OPEN df$ + LTRIM$(STR$(n)) + ".bin" FOR BINARY AS #2
            x$ = decompress(Download_String)
            PUT #2, , x$
            CLOSE #2
            'add batch install lines
            'ensure folder exists
            p$ = rippath$(a1$)
            IF p$ <> "" THEN PRINT #10, "md " + CHR$(34) + qf2$ + p$ + CHR$(34)
            'move file (preserving case of filename)
            PRINT #10, "del " + CHR$(34) + qf2$ + a1$ + CHR$(34)
            PRINT #10, "copy " + CHR$(34) + df$ + LTRIM$(STR$(n)) + ".bin" + CHR$(34) + " " + CHR$(34) + qf2$ + a1$ + CHR$(34)
            PRINT #10, "del " + CHR$(34) + df$ + LTRIM$(STR$(n)) + ".bin" + CHR$(34)



            nochange:
        END IF '<>"0"
    END IF
LOOP
CLOSE #1


IF files_updated = 1 THEN

    'create new chksum file
    OPEN uf$ + "chksums.tmp" FOR OUTPUT AS #1
    FOR i = 1 TO nchksums
        PRINT #1, chksums_name(i) + "," + chksums_valstr(i)
    NEXT
    CLOSE #1

    'create new update file
    OPEN uf$ + "update.tmp" FOR OUTPUT AS #1
    print #1,v$;
    close #1

    PRINT #10, "copy " + uf$ + "chksums.tmp " + uf$ + "chksums.txt"
    PRINT #10, "del " + uf$ + "chksums.tmp"

    PRINT #10, "copy " + uf$ + "update.tmp " + uf$ + "update.txt"
    PRINT #10, "del " + uf$ + "update.tmp"

    if how<2 then PRINT #10, "start qb64.exe" 'attempt to relaunch qb64
    PRINT #10, "del setup.bat"
    CLOSE #10
    CLOSE

if how=2 then
if compfailed then
print "C++ COMPILATION FAILED!" 'redisplay failed message
locate 25,1: print "Press any key to continue";
do: _limit 100:loop until len(inkey$)
end if
end if

    RUN "setup.bat"
END IF

CLOSE #10

KILL "setup.bat"

IF chksums_updated = 1 THEN

    'create new chksum file
    OPEN uf$ + "chksums.txt" FOR OUTPUT AS #1
    FOR i = 1 TO nchksums
        PRINT #1, chksums_name(i) + "," + chksums_valstr(i)
    NEXT
    CLOSE #1

    'PRINT "Checksums were updated."

ELSE
    'PRINT "No changes necessary"
END IF

    'replace update (version) file
    OPEN uf$ + "update.txt" FOR OUTPUT AS #1
    print #1,v$;
    close #1

KILL uf$ + "chksums.tmp"

if how<=1 then
PCOPY 3,0
idemessagebox "Update","No changes required."
PCOPY 3, 0: SCREEN , , 3, 0: idewait4mous: idewait4alt
end if

if how=2 then
if compfailed then print "C++ COMPILATION FAILED!" 'redisplay failed message
end if

ON ERROR GOTO qberror

if how=3 then system
END SUB

function removecast$(a$)
removecast$=a$
if instr(a$,")") then
removecast$=right$(a$,len(a$)-instr(a$,")"))
end if
end function

function converttabs$ (a2$)
if ideautoindent then s=ideautoindentsize else s=4
a$=a2$
do while instr(a$,chr_tab)
x=instr(a$,chr_tab)
a$=LEFT$(a$, x - 1)+space$(s-((x-1) mod s))+right$(a$,len(a$)-x)
loop

'cull control characters
cullctrlchrs:
for x=1 to len(a$)
if control_chr(asc(a$,x)) then
a$=LEFT$(a$, x - 1)+right$(a$,len(a$)-x)
goto cullctrlchrs
end if
next

converttabs$=a$
end function
