From 498da3221e879bcd2d063065dd4d48a68827ddd7 Mon Sep 17 00:00:00 2001 From: "Kirill Lipatov (Leency)" Date: Tue, 15 Jun 2021 17:33:16 +0000 Subject: [PATCH] update Oberon07 and CEDIT by akron1 git-svn-id: svn://kolibrios.org@8859 a494cfbc-eb01-0410-851d-a64ba20cac60 --- programs/develop/cedit/CEDIT | Bin 28687 -> 28682 bytes programs/develop/cedit/SRC/CEdit.ob07 | 35 +- programs/develop/cedit/SRC/Icons.ob07 | 127 ++ programs/develop/oberon07/Compiler | Bin 305096 -> 302008 bytes programs/develop/oberon07/Compiler.exe | Bin 307200 -> 303616 bytes programs/develop/oberon07/LICENSE | 2 +- .../develop/oberon07/Lib/KolibriOS/RTL.ob07 | 520 ------ .../develop/oberon07/Lib/Linux32/API.ob07 | 123 -- .../develop/oberon07/Lib/Linux32/Args.ob07 | 70 - .../develop/oberon07/Lib/Linux32/File.ob07 | 132 -- .../develop/oberon07/Lib/Linux32/HOST.ob07 | 248 --- programs/develop/oberon07/Lib/Linux32/In.ob07 | 85 - .../develop/oberon07/Lib/Linux32/LINAPI.ob07 | 106 -- .../develop/oberon07/Lib/Linux32/Libdl.ob07 | 65 - .../develop/oberon07/Lib/Linux32/Math.ob07 | 450 ------ .../develop/oberon07/Lib/Linux32/Out.ob07 | 77 - .../develop/oberon07/Lib/Linux64/API.ob07 | 123 -- .../develop/oberon07/Lib/Linux64/Args.ob07 | 70 - .../develop/oberon07/Lib/Linux64/File.ob07 | 132 -- .../develop/oberon07/Lib/Linux64/HOST.ob07 | 254 --- programs/develop/oberon07/Lib/Linux64/In.ob07 | 85 - .../develop/oberon07/Lib/Linux64/LINAPI.ob07 | 101 -- .../develop/oberon07/Lib/Linux64/Libdl.ob07 | 65 - .../develop/oberon07/Lib/Linux64/Math.ob07 | 480 ------ .../develop/oberon07/Lib/Linux64/Out.ob07 | 87 - .../develop/oberon07/Lib/Linux64/RTL.ob07 | 503 ------ .../develop/oberon07/Lib/MSP430/MSP430.ob07 | 125 -- .../develop/oberon07/Lib/Windows32/API.ob07 | 132 -- .../develop/oberon07/Lib/Windows32/Args.ob07 | 101 -- .../oberon07/Lib/Windows32/Console.ob07 | 100 -- .../oberon07/Lib/Windows32/DateTime.ob07 | 197 --- .../develop/oberon07/Lib/Windows32/File.ob07 | 139 -- .../develop/oberon07/Lib/Windows32/HOST.ob07 | 333 ---- .../develop/oberon07/Lib/Windows32/In.ob07 | 80 - .../develop/oberon07/Lib/Windows32/Math.ob07 | 450 ------ .../develop/oberon07/Lib/Windows32/Out.ob07 | 77 - .../develop/oberon07/Lib/Windows32/RTL.ob07 | 520 ------ .../oberon07/Lib/Windows32/WINAPI.ob07 | 224 --- .../develop/oberon07/Lib/Windows64/API.ob07 | 132 -- .../develop/oberon07/Lib/Windows64/Args.ob07 | 101 -- .../oberon07/Lib/Windows64/Console.ob07 | 100 -- .../oberon07/Lib/Windows64/DateTime.ob07 | 197 --- .../develop/oberon07/Lib/Windows64/File.ob07 | 139 -- .../develop/oberon07/Lib/Windows64/HOST.ob07 | 339 ---- .../develop/oberon07/Lib/Windows64/In.ob07 | 80 - .../develop/oberon07/Lib/Windows64/Math.ob07 | 480 ------ .../develop/oberon07/Lib/Windows64/Out.ob07 | 86 - .../develop/oberon07/Lib/Windows64/RTL.ob07 | 503 ------ .../oberon07/Lib/Windows64/WINAPI.ob07 | 224 --- programs/develop/oberon07/README.md | 6 + .../develop/oberon07/Samples/Linux/HW.ob07 | 52 - .../Samples/Linux/X11/animation/_unix.ob07 | 74 - .../Linux/X11/animation/animation.ob07 | 89 - .../Samples/Linux/X11/animation/gr.ob07 | 292 ---- .../Samples/Linux/X11/animation/out.ob07 | 142 -- .../Samples/Linux/X11/animation/unix.ob07 | 74 - .../Samples/Linux/X11/filler/_unix.ob07 | 74 - .../Samples/Linux/X11/filler/filler.ob07 | 221 --- .../Samples/Linux/X11/filler/filler.txt | 15 - .../oberon07/Samples/Linux/X11/filler/gr.ob07 | 292 ---- .../Samples/Linux/X11/filler/out.ob07 | 142 -- .../Samples/Linux/X11/filler/unix.ob07 | 74 - .../oberon07/Samples/MSP430/Blink.ob07 | 43 - .../oberon07/Samples/MSP430/Button.ob07 | 103 -- .../oberon07/Samples/MSP430/Flash.ob07 | 157 -- .../oberon07/Samples/MSP430/Restart.ob07 | 106 -- .../oberon07/Samples/MSP430/TimerA.ob07 | 118 -- .../oberon07/Samples/MSP430/TwoTimers.ob07 | 143 -- .../oberon07/Samples/STM32CM3/Blink.ob07 | 57 - .../oberon07/Samples/STM32CM3/Button.ob07 | 114 -- .../oberon07/Samples/STM32CM3/LCD.ob07 | 366 ----- .../oberon07/Samples/STM32CM3/SysTick.ob07 | 79 - .../oberon07/Samples/STM32CM3/TIM67.ob07 | 143 -- .../Samples/Windows/Console/Doors.ob07 | 58 - .../Samples/Windows/Console/HeapSort.ob07 | 101 -- .../Samples/Windows/Console/Hello.ob07 | 13 - .../Samples/Windows/Console/HelloRus.ob07 | 26 - .../Samples/Windows/Console/MagicSquares.ob07 | 48 - .../Windows/Console/MultiplicationTables.ob07 | 52 - .../Windows/Console/SierpinskiCarpet.ob07 | 75 - .../Windows/Console/SierpinskiTriangle.ob07 | 44 - .../Samples/Windows/Console/Sieve.ob07 | 51 - .../Samples/Windows/Console/SpiralMatrix.ob07 | 56 - .../Samples/Windows/Console/TempConv.ob07 | 44 - .../oberon07/Samples/Windows/Console/exp.ob07 | 117 -- .../Samples/Windows/Console/fact.ob07 | 59 - .../Samples/Windows/Console/hailst.ob07 | 117 -- .../Samples/Windows/Console/postfix.ob07 | 123 -- .../Samples/Windows/Console/sequence012.ob07 | 79 - programs/develop/oberon07/SelfKolibriOS.cmd | 2 + programs/develop/oberon07/doc/CC.txt | 61 + .../develop/oberon07/{Docs => doc}/KOSLib.txt | 0 .../Oberon07.Report_2016_05_03.pdf | Bin .../develop/oberon07/{Docs => doc}/WinLib.txt | 0 .../develop/oberon07/{Docs => doc}/x86.txt | 91 +- .../develop/oberon07/{Docs => doc}/x86_64.txt | 92 +- .../oberon07/{Lib => lib}/KolibriOS/API.ob07 | 3 +- .../oberon07/{Lib => lib}/KolibriOS/Args.ob07 | 0 .../{Lib => lib}/KolibriOS/ColorDlg.ob07 | 0 .../{Lib => lib}/KolibriOS/Console.ob07 | 0 .../{Lib => lib}/KolibriOS/ConsoleLib.ob07 | 0 .../{Lib => lib}/KolibriOS/DateTime.ob07 | 0 .../{Lib => lib}/KolibriOS/Debug.ob07 | 0 .../oberon07/{Lib => lib}/KolibriOS/File.ob07 | 16 +- .../oberon07/{Lib => lib}/KolibriOS/HOST.ob07 | 19 +- .../oberon07/{Lib => lib}/KolibriOS/In.ob07 | 0 .../{Lib => lib}/KolibriOS/KOSAPI.ob07 | 0 .../oberon07/{Lib => lib}/KolibriOS/Math.ob07 | 0 .../{Lib => lib}/KolibriOS/NetDevices.ob07 | 0 .../{Lib => lib}/KolibriOS/OpenDlg.ob07 | 9 +- .../oberon07/{Lib => lib}/KolibriOS/Out.ob07 | 0 .../{Lib/Linux32 => lib/KolibriOS}/RTL.ob07 | 87 +- .../{Lib => lib}/KolibriOS/RasterWorks.ob07 | 0 .../oberon07/{Lib => lib}/KolibriOS/Read.ob07 | 0 .../{Lib => lib}/KolibriOS/UnixTime.ob07 | 0 .../{Lib => lib}/KolibriOS/Vector.ob07 | 0 .../{Lib => lib}/KolibriOS/Write.ob07 | 0 .../{Lib => lib}/KolibriOS/kfonts.ob07 | 0 .../{Lib => lib}/KolibriOS/libimg.ob07 | 0 .../oberon07/{Lib => lib}/Math/CMath.ob07 | 0 .../oberon07/{Lib => lib}/Math/MathBits.ob07 | 0 .../oberon07/{Lib => lib}/Math/MathRound.ob07 | 0 .../oberon07/{Lib => lib}/Math/MathStat.ob07 | 0 .../oberon07/{Lib => lib}/Math/Rand.ob07 | 0 .../oberon07/{Lib => lib}/Math/RandExt.ob07 | 0 .../oberon07/{Lib => lib}/RVM32I/FPU.ob07 | 0 .../oberon07/{Lib => lib}/RVM32I/HOST.ob07 | 0 .../oberon07/{Lib => lib}/RVM32I/Out.ob07 | 0 .../oberon07/{Lib => lib}/RVM32I/RTL.ob07 | 0 .../oberon07/{Lib => lib}/RVM32I/Trap.ob07 | 0 .../{Lib/STM32CM3 => lib/RVMxI/32}/FPU.ob07 | 165 +- .../develop/oberon07/lib/RVMxI/32/HOST.ob07 | 185 +++ .../develop/oberon07/lib/RVMxI/32/Out.ob07 | 273 ++++ .../{Lib/STM32CM3 => lib/RVMxI/32}/RTL.ob07 | 93 +- .../develop/oberon07/lib/RVMxI/32/Trap.ob07 | 133 ++ .../develop/oberon07/lib/RVMxI/64/HOST.ob07 | 201 +++ .../develop/oberon07/lib/RVMxI/64/Out.ob07 | 288 ++++ .../develop/oberon07/lib/RVMxI/64/RTL.ob07 | 432 +++++ .../develop/oberon07/lib/RVMxI/64/Trap.ob07 | 133 ++ .../KolibriOS/Dialogs.ob07 | 0 .../{Samples => samples}/KolibriOS/HW.ob07 | 0 .../KolibriOS/HW_con.ob07 | 0 .../oberon07/{Source => source}/AMD64.ob07 | 478 ++---- .../oberon07/{Source => source}/ARITH.ob07 | 25 +- .../oberon07/{Source => source}/AVLTREES.ob07 | 0 .../oberon07/{Source => source}/BIN.ob07 | 0 .../{Source => source}/CHUNKLISTS.ob07 | 83 +- .../{Source => source}/COLLECTIONS.ob07 | 0 .../oberon07/{Source => source}/CONSOLE.ob07 | 18 +- .../oberon07/{Source => source}/Compiler.ob07 | 58 +- .../oberon07/{Source => source}/ELF.ob07 | 39 +- .../oberon07/{Source => source}/ERRORS.ob07 | 5 +- .../oberon07/{Source => source}/FILES.ob07 | 13 +- .../oberon07/{Source => source}/HEX.ob07 | 0 .../oberon07/{Source => source}/IL.ob07 | 131 +- .../oberon07/{Source => source}/KOS.ob07 | 0 .../oberon07/{Source => source}/LISTS.ob07 | 31 +- .../oberon07/{Source => source}/MSCOFF.ob07 | 0 .../oberon07/{Source => source}/MSP430.ob07 | 202 ++- .../{Source => source}/MSP430RTL.ob07 | 102 +- .../oberon07/{Source => source}/PARS.ob07 | 183 ++- .../oberon07/{Source => source}/PATHS.ob07 | 50 +- .../oberon07/{Source => source}/PE32.ob07 | 0 .../oberon07/{Source => source}/PROG.ob07 | 226 ++- .../oberon07/{Source => source}/REG.ob07 | 179 +-- .../oberon07/{Source => source}/RVM32I.ob07 | 0 programs/develop/oberon07/source/RVMxI.ob07 | 1428 +++++++++++++++++ .../oberon07/{Source => source}/SCAN.ob07 | 360 +++-- .../{Source => source}/STATEMENTS.ob07 | 143 +- .../oberon07/{Source => source}/STRINGS.ob07 | 75 +- .../oberon07/{Source => source}/TARGETS.ob07 | 48 +- .../oberon07/{Source => source}/TEXTDRV.ob07 | 0 .../oberon07/{Source => source}/THUMB.ob07 | 321 ++-- .../oberon07/{Source => source}/UTILS.ob07 | 22 +- .../oberon07/{Source => source}/WRITER.ob07 | 7 +- .../oberon07/{Source => source}/X86.ob07 | 24 +- programs/develop/oberon07/tools/RVMxI.ob07 | 668 ++++++++ programs/develop/oberon07/tools/RVMxI.txt | 270 ++++ 178 files changed, 5878 insertions(+), 14432 deletions(-) create mode 100644 programs/develop/cedit/SRC/Icons.ob07 delete mode 100644 programs/develop/oberon07/Lib/KolibriOS/RTL.ob07 delete mode 100644 programs/develop/oberon07/Lib/Linux32/API.ob07 delete mode 100644 programs/develop/oberon07/Lib/Linux32/Args.ob07 delete mode 100644 programs/develop/oberon07/Lib/Linux32/File.ob07 delete mode 100644 programs/develop/oberon07/Lib/Linux32/HOST.ob07 delete mode 100644 programs/develop/oberon07/Lib/Linux32/In.ob07 delete mode 100644 programs/develop/oberon07/Lib/Linux32/LINAPI.ob07 delete mode 100644 programs/develop/oberon07/Lib/Linux32/Libdl.ob07 delete mode 100644 programs/develop/oberon07/Lib/Linux32/Math.ob07 delete mode 100644 programs/develop/oberon07/Lib/Linux32/Out.ob07 delete mode 100644 programs/develop/oberon07/Lib/Linux64/API.ob07 delete mode 100644 programs/develop/oberon07/Lib/Linux64/Args.ob07 delete mode 100644 programs/develop/oberon07/Lib/Linux64/File.ob07 delete mode 100644 programs/develop/oberon07/Lib/Linux64/HOST.ob07 delete mode 100644 programs/develop/oberon07/Lib/Linux64/In.ob07 delete mode 100644 programs/develop/oberon07/Lib/Linux64/LINAPI.ob07 delete mode 100644 programs/develop/oberon07/Lib/Linux64/Libdl.ob07 delete mode 100644 programs/develop/oberon07/Lib/Linux64/Math.ob07 delete mode 100644 programs/develop/oberon07/Lib/Linux64/Out.ob07 delete mode 100644 programs/develop/oberon07/Lib/Linux64/RTL.ob07 delete mode 100644 programs/develop/oberon07/Lib/MSP430/MSP430.ob07 delete mode 100644 programs/develop/oberon07/Lib/Windows32/API.ob07 delete mode 100644 programs/develop/oberon07/Lib/Windows32/Args.ob07 delete mode 100644 programs/develop/oberon07/Lib/Windows32/Console.ob07 delete mode 100644 programs/develop/oberon07/Lib/Windows32/DateTime.ob07 delete mode 100644 programs/develop/oberon07/Lib/Windows32/File.ob07 delete mode 100644 programs/develop/oberon07/Lib/Windows32/HOST.ob07 delete mode 100644 programs/develop/oberon07/Lib/Windows32/In.ob07 delete mode 100644 programs/develop/oberon07/Lib/Windows32/Math.ob07 delete mode 100644 programs/develop/oberon07/Lib/Windows32/Out.ob07 delete mode 100644 programs/develop/oberon07/Lib/Windows32/RTL.ob07 delete mode 100644 programs/develop/oberon07/Lib/Windows32/WINAPI.ob07 delete mode 100644 programs/develop/oberon07/Lib/Windows64/API.ob07 delete mode 100644 programs/develop/oberon07/Lib/Windows64/Args.ob07 delete mode 100644 programs/develop/oberon07/Lib/Windows64/Console.ob07 delete mode 100644 programs/develop/oberon07/Lib/Windows64/DateTime.ob07 delete mode 100644 programs/develop/oberon07/Lib/Windows64/File.ob07 delete mode 100644 programs/develop/oberon07/Lib/Windows64/HOST.ob07 delete mode 100644 programs/develop/oberon07/Lib/Windows64/In.ob07 delete mode 100644 programs/develop/oberon07/Lib/Windows64/Math.ob07 delete mode 100644 programs/develop/oberon07/Lib/Windows64/Out.ob07 delete mode 100644 programs/develop/oberon07/Lib/Windows64/RTL.ob07 delete mode 100644 programs/develop/oberon07/Lib/Windows64/WINAPI.ob07 create mode 100644 programs/develop/oberon07/README.md delete mode 100644 programs/develop/oberon07/Samples/Linux/HW.ob07 delete mode 100644 programs/develop/oberon07/Samples/Linux/X11/animation/_unix.ob07 delete mode 100644 programs/develop/oberon07/Samples/Linux/X11/animation/animation.ob07 delete mode 100644 programs/develop/oberon07/Samples/Linux/X11/animation/gr.ob07 delete mode 100644 programs/develop/oberon07/Samples/Linux/X11/animation/out.ob07 delete mode 100644 programs/develop/oberon07/Samples/Linux/X11/animation/unix.ob07 delete mode 100644 programs/develop/oberon07/Samples/Linux/X11/filler/_unix.ob07 delete mode 100644 programs/develop/oberon07/Samples/Linux/X11/filler/filler.ob07 delete mode 100644 programs/develop/oberon07/Samples/Linux/X11/filler/filler.txt delete mode 100644 programs/develop/oberon07/Samples/Linux/X11/filler/gr.ob07 delete mode 100644 programs/develop/oberon07/Samples/Linux/X11/filler/out.ob07 delete mode 100644 programs/develop/oberon07/Samples/Linux/X11/filler/unix.ob07 delete mode 100644 programs/develop/oberon07/Samples/MSP430/Blink.ob07 delete mode 100644 programs/develop/oberon07/Samples/MSP430/Button.ob07 delete mode 100644 programs/develop/oberon07/Samples/MSP430/Flash.ob07 delete mode 100644 programs/develop/oberon07/Samples/MSP430/Restart.ob07 delete mode 100644 programs/develop/oberon07/Samples/MSP430/TimerA.ob07 delete mode 100644 programs/develop/oberon07/Samples/MSP430/TwoTimers.ob07 delete mode 100644 programs/develop/oberon07/Samples/STM32CM3/Blink.ob07 delete mode 100644 programs/develop/oberon07/Samples/STM32CM3/Button.ob07 delete mode 100644 programs/develop/oberon07/Samples/STM32CM3/LCD.ob07 delete mode 100644 programs/develop/oberon07/Samples/STM32CM3/SysTick.ob07 delete mode 100644 programs/develop/oberon07/Samples/STM32CM3/TIM67.ob07 delete mode 100644 programs/develop/oberon07/Samples/Windows/Console/Doors.ob07 delete mode 100644 programs/develop/oberon07/Samples/Windows/Console/HeapSort.ob07 delete mode 100644 programs/develop/oberon07/Samples/Windows/Console/Hello.ob07 delete mode 100644 programs/develop/oberon07/Samples/Windows/Console/HelloRus.ob07 delete mode 100644 programs/develop/oberon07/Samples/Windows/Console/MagicSquares.ob07 delete mode 100644 programs/develop/oberon07/Samples/Windows/Console/MultiplicationTables.ob07 delete mode 100644 programs/develop/oberon07/Samples/Windows/Console/SierpinskiCarpet.ob07 delete mode 100644 programs/develop/oberon07/Samples/Windows/Console/SierpinskiTriangle.ob07 delete mode 100644 programs/develop/oberon07/Samples/Windows/Console/Sieve.ob07 delete mode 100644 programs/develop/oberon07/Samples/Windows/Console/SpiralMatrix.ob07 delete mode 100644 programs/develop/oberon07/Samples/Windows/Console/TempConv.ob07 delete mode 100644 programs/develop/oberon07/Samples/Windows/Console/exp.ob07 delete mode 100644 programs/develop/oberon07/Samples/Windows/Console/fact.ob07 delete mode 100644 programs/develop/oberon07/Samples/Windows/Console/hailst.ob07 delete mode 100644 programs/develop/oberon07/Samples/Windows/Console/postfix.ob07 delete mode 100644 programs/develop/oberon07/Samples/Windows/Console/sequence012.ob07 create mode 100644 programs/develop/oberon07/SelfKolibriOS.cmd create mode 100644 programs/develop/oberon07/doc/CC.txt rename programs/develop/oberon07/{Docs => doc}/KOSLib.txt (100%) rename programs/develop/oberon07/{Docs => doc}/Oberon07.Report_2016_05_03.pdf (100%) rename programs/develop/oberon07/{Docs => doc}/WinLib.txt (100%) rename programs/develop/oberon07/{Docs => doc}/x86.txt (83%) rename programs/develop/oberon07/{Docs => doc}/x86_64.txt (83%) rename programs/develop/oberon07/{Lib => lib}/KolibriOS/API.ob07 (94%) rename programs/develop/oberon07/{Lib => lib}/KolibriOS/Args.ob07 (100%) rename programs/develop/oberon07/{Lib => lib}/KolibriOS/ColorDlg.ob07 (100%) rename programs/develop/oberon07/{Lib => lib}/KolibriOS/Console.ob07 (100%) rename programs/develop/oberon07/{Lib => lib}/KolibriOS/ConsoleLib.ob07 (100%) rename programs/develop/oberon07/{Lib => lib}/KolibriOS/DateTime.ob07 (100%) rename programs/develop/oberon07/{Lib => lib}/KolibriOS/Debug.ob07 (100%) rename programs/develop/oberon07/{Lib => lib}/KolibriOS/File.ob07 (91%) rename programs/develop/oberon07/{Lib => lib}/KolibriOS/HOST.ob07 (92%) rename programs/develop/oberon07/{Lib => lib}/KolibriOS/In.ob07 (100%) rename programs/develop/oberon07/{Lib => lib}/KolibriOS/KOSAPI.ob07 (100%) rename programs/develop/oberon07/{Lib => lib}/KolibriOS/Math.ob07 (100%) rename programs/develop/oberon07/{Lib => lib}/KolibriOS/NetDevices.ob07 (100%) rename programs/develop/oberon07/{Lib => lib}/KolibriOS/OpenDlg.ob07 (93%) rename programs/develop/oberon07/{Lib => lib}/KolibriOS/Out.ob07 (100%) rename programs/develop/oberon07/{Lib/Linux32 => lib/KolibriOS}/RTL.ob07 (79%) rename programs/develop/oberon07/{Lib => lib}/KolibriOS/RasterWorks.ob07 (100%) rename programs/develop/oberon07/{Lib => lib}/KolibriOS/Read.ob07 (100%) rename programs/develop/oberon07/{Lib => lib}/KolibriOS/UnixTime.ob07 (100%) rename programs/develop/oberon07/{Lib => lib}/KolibriOS/Vector.ob07 (100%) rename programs/develop/oberon07/{Lib => lib}/KolibriOS/Write.ob07 (100%) rename programs/develop/oberon07/{Lib => lib}/KolibriOS/kfonts.ob07 (100%) rename programs/develop/oberon07/{Lib => lib}/KolibriOS/libimg.ob07 (100%) rename programs/develop/oberon07/{Lib => lib}/Math/CMath.ob07 (100%) rename programs/develop/oberon07/{Lib => lib}/Math/MathBits.ob07 (100%) rename programs/develop/oberon07/{Lib => lib}/Math/MathRound.ob07 (100%) rename programs/develop/oberon07/{Lib => lib}/Math/MathStat.ob07 (100%) rename programs/develop/oberon07/{Lib => lib}/Math/Rand.ob07 (100%) rename programs/develop/oberon07/{Lib => lib}/Math/RandExt.ob07 (100%) rename programs/develop/oberon07/{Lib => lib}/RVM32I/FPU.ob07 (100%) rename programs/develop/oberon07/{Lib => lib}/RVM32I/HOST.ob07 (100%) rename programs/develop/oberon07/{Lib => lib}/RVM32I/Out.ob07 (100%) rename programs/develop/oberon07/{Lib => lib}/RVM32I/RTL.ob07 (100%) rename programs/develop/oberon07/{Lib => lib}/RVM32I/Trap.ob07 (100%) rename programs/develop/oberon07/{Lib/STM32CM3 => lib/RVMxI/32}/FPU.ob07 (70%) create mode 100644 programs/develop/oberon07/lib/RVMxI/32/HOST.ob07 create mode 100644 programs/develop/oberon07/lib/RVMxI/32/Out.ob07 rename programs/develop/oberon07/{Lib/STM32CM3 => lib/RVMxI/32}/RTL.ob07 (79%) create mode 100644 programs/develop/oberon07/lib/RVMxI/32/Trap.ob07 create mode 100644 programs/develop/oberon07/lib/RVMxI/64/HOST.ob07 create mode 100644 programs/develop/oberon07/lib/RVMxI/64/Out.ob07 create mode 100644 programs/develop/oberon07/lib/RVMxI/64/RTL.ob07 create mode 100644 programs/develop/oberon07/lib/RVMxI/64/Trap.ob07 rename programs/develop/oberon07/{Samples => samples}/KolibriOS/Dialogs.ob07 (100%) rename programs/develop/oberon07/{Samples => samples}/KolibriOS/HW.ob07 (100%) rename programs/develop/oberon07/{Samples => samples}/KolibriOS/HW_con.ob07 (100%) rename programs/develop/oberon07/{Source => source}/AMD64.ob07 (79%) rename programs/develop/oberon07/{Source => source}/ARITH.ob07 (90%) rename programs/develop/oberon07/{Source => source}/AVLTREES.ob07 (100%) rename programs/develop/oberon07/{Source => source}/BIN.ob07 (100%) rename programs/develop/oberon07/{Source => source}/CHUNKLISTS.ob07 (70%) rename programs/develop/oberon07/{Source => source}/COLLECTIONS.ob07 (100%) rename programs/develop/oberon07/{Source => source}/CONSOLE.ob07 (77%) rename programs/develop/oberon07/{Source => source}/Compiler.ob07 (82%) rename programs/develop/oberon07/{Source => source}/ELF.ob07 (91%) rename programs/develop/oberon07/{Source => source}/ERRORS.ob07 (95%) rename programs/develop/oberon07/{Source => source}/FILES.ob07 (87%) rename programs/develop/oberon07/{Source => source}/HEX.ob07 (100%) rename programs/develop/oberon07/{Source => source}/IL.ob07 (91%) rename programs/develop/oberon07/{Source => source}/KOS.ob07 (100%) rename programs/develop/oberon07/{Source => source}/LISTS.ob07 (81%) rename programs/develop/oberon07/{Source => source}/MSCOFF.ob07 (100%) rename programs/develop/oberon07/{Source => source}/MSP430.ob07 (90%) rename programs/develop/oberon07/{Source => source}/MSP430RTL.ob07 (90%) rename programs/develop/oberon07/{Source => source}/PARS.ob07 (83%) rename programs/develop/oberon07/{Source => source}/PATHS.ob07 (65%) rename programs/develop/oberon07/{Source => source}/PE32.ob07 (100%) rename programs/develop/oberon07/{Source => source}/PROG.ob07 (80%) rename programs/develop/oberon07/{Source => source}/REG.ob07 (58%) rename programs/develop/oberon07/{Source => source}/RVM32I.ob07 (100%) create mode 100644 programs/develop/oberon07/source/RVMxI.ob07 rename programs/develop/oberon07/{Source => source}/SCAN.ob07 (65%) rename programs/develop/oberon07/{Source => source}/STATEMENTS.ob07 (93%) rename programs/develop/oberon07/{Source => source}/STRINGS.ob07 (77%) rename programs/develop/oberon07/{Source => source}/TARGETS.ob07 (81%) rename programs/develop/oberon07/{Source => source}/TEXTDRV.ob07 (100%) rename programs/develop/oberon07/{Source => source}/THUMB.ob07 (88%) rename programs/develop/oberon07/{Source => source}/UTILS.ob07 (85%) rename programs/develop/oberon07/{Source => source}/WRITER.ob07 (86%) rename programs/develop/oberon07/{Source => source}/X86.ob07 (95%) create mode 100644 programs/develop/oberon07/tools/RVMxI.ob07 create mode 100644 programs/develop/oberon07/tools/RVMxI.txt diff --git a/programs/develop/cedit/CEDIT b/programs/develop/cedit/CEDIT index 04e92a5b089bf4e04aca7a06a441c6b74b452030..3b4f16b51bd728bf5282de69eca6ced836daa757 100644 GIT binary patch literal 28682 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 literal 28687 zcmV(pK=8jyP(w?6bpZf@00001Mv*2LLXK;4&&M{gp_OHq*c7RAm|wFc7+kkYArTY- zc@JHo2Q<_BiUWHcmal#w0vbf>y`RjcsdtlqbxdRfl`BDa=}rQq*wVxlGwy05Wn3#o z6*6~Inr@^;k-ltJlk^*tOc?PETR?;Of}LrDzXcjbJf(jH0YDwpo9fDNzWW%}M4;d`8=g-W?8l+^O4?XEdzm=Q!v|Im*qC{=XcGxY zO7srW3q4>|HnSOzeNZs~p-IAPB9M$=P-ta#I-Fqr8N2>SH_=2A>T_ z)&;Ne!`1I7j6SK@qy$VxAegh;_})!>)-MqeR|adYpJ0NO*8YmY*+^@N={k4488Mi2 zgAujZK<+{$f{~pk3u(9(TQz$*$wA(AJyN|4_~MVc5Et1+{RqEOJ_BZ|wrxm$yH35+ z67-`!%4cv4P?PxDK?K%C_hwi4o#2I)Pg?DKn9F_}h+9 zg}{530_p7!KA)9~DX_d>83*1IqDu!0)}4!df+|t?aBj_M`a^wrUtO?Bs`!CNPXGA> zOZyUj8i&%*=gELUy)hTSs&_DEYxBja3Qt06z}n`@fM5-9@BT8oiv&AyO@c1hlSCJk zc+$t`t&zowP6iD$z>J1;N!H`SdK-YKAQ8h1(oH{O*R=|kBK^2W`>n|WLRq}om6wD8 zm>h9%0f9tY5`<`yXV@~1c~r}Zh;kw{iDjz+jGrp_;#Df9kU)41`if6$f$bVpp(Kz%E46KJX&gKei8lHw{K`K9n5HvI zyo3|$j%^B<{tPmjoC=Y!(1KwJ_)s>AWuicdf`vM9_!B3EmDqLDCx%$2-%Y6~=v71} zeHs;uRI41i+(*67D+m&{@jN`KzO&GEDBY-sOT|EbXY?yQcDhL(I5yYo{+n)&CQtq)WKPL3iKgTSr8>OS|M;73?49r2 zQ}&lb=Xg4K_QP>Um_ksHIVt$e-KTNz&iA0+%u8M}s1Sh#RdxUb79}K3)Vp}cH77s_ zk_H{^xl3?;;T{SuFVzw2qJ-g53q@$LoV$l5KH6ZJ#I{SOXeG+$OT~T9Ax@FPb-$B) zy&g-%ROAX1C67I~9meYP&AvS&Cx_0c!s%bM``#U%-YY>O1L`+y)))ll-U1Vxl0gVmisYG64M$NSZM?N@3nN%a83H{P1z3oDR&=D zu`u)Yf`iv9#U47b7ucBQTlje0hevM|3g7sc-Zp*U@Ki|5z#hW2O_ z_$nVaR!PS0d+b2P)Z?ge`k&_hetm7nTP5*9N3ET7E8WwK#?${(`}y<7=VP6KU9IMk zBwvN@4r;=S)Bj<%9kUa%xm(-`CH}f3gAxcO>vU1U_=_Jk>o-M|Dhb`gzwPK{SmjzH zlk7qg7F29XcvtPEm{AY+7Znt@hN2oEDp<@@1VVp(ltdn(m=8gOye z61D=G4;MzgS(}h`)lim%dEbq>dXR;qS56983=8IC8$zdG*5fzEMu$(>uz{J0d~PX| z{jF-0!tBi@Qp|Ak3v1E})rYc<_4{Sg4EFegC{h_aQ3U00T<4bG{V5DTo7&Atw$&Mu zLfK;08(fl%5CXLvr&Ecs4Rj@;mb0q&T^`(;d*Q%`wc*Ii5~V3F=EaxoRUOBJMAnyW zo%&$7cIvgo7KhaiO16J2*}2dJzv~I+h-Qou?o-2K9JvRi=ec#JmQoT+;4Xu#s!<{& zWEYJ0i@B*XdEyVk(t2KX+{$bMR(@cO)1r^1m?PDK!d9Fo+n6g$d%sH98kk3wBZ0U++9N$6}ZD&mNtKxkH5vL6y zEWGhmnDhllM;ei~Ox{`FtfUhk{k?gOLtBZ0cYf*W5|-k;P(5}TwyuOt;O;0=J>>!)Cduo%54loXixv|+{JuTH$FXxbEXoY@L(d(C8jG)Pgj>7O=fQ%&x z3qd2SyAKC3C%gib0hMf;R}aHvBX<*}EymJf$naTc|t4YzQP>6I-q_1fM>`bjgC z24Z9U4)b?nrXQ^G^LDYfK_ufWYWTkZ#a=0*<6#W}R>WwI{HJ78CYFK`EX52!A{doRh{D8D zy2}(8?{6gZ7~FQ%D0EF|@08-outx15qK(xUnDAtkPvp4e<3hu^njcvV@~B*K%DFj+ zx_|4^+eAZ6IAp>7;s4EA;V)hY0(VDM0l}dzml6KpefZ z>BUr$luBU3lS7RLRj)EfmcSWbu;&L;_xZ}rb3Gko5rxWIumhw`t$zJvTP$QCJdHp* ze#4tw3v-InpaQ0GO@WnZO&^xPxW^n>`Y(La{isaMG>v91)v0LtU@^l@?J>0uL9E&{ z?2H?g|Ea53CVX&*wzN2o*v-VvNAmpb^^;J>9b}ZZNO64!i)fTlicSqV8LH@Ytwv5G zY0{4bBf^!pyCd5!N{?$e?t$gyZ_wS~0G$x0#ML`^>_ymNXE`hN(I;~~%pGs?dvZ~Y z0VAfP846sG9fHu{zHiobY^z`e%DPYLA;1jy@2G#-mce)f+vr5Z8L|xjnzd~yjHZwM zQc#Ho_>a6W4GX?hvmnBZ3A+DyOcG;#Vl>i0*OEpOSI%)4_-Wj0y@O5;+1&0VW9;fhmAU-Tp&sBQLj(ngNtE_NNcb zPTc4xO?H}od*%MZPulkY3%?9ryZp!Q2eruvBVF}KEfQ5JsfFAyl?LX^!3sqJ|?x~Wy z6(!Q2nxiBnPR{7cA!38L?c2aqo#cE1Ww(kJ0OOzbg0f8~K!fcJbL4RCa;|3EipaFE$e@Y0U{m~zn!*%SbJb-D9raN;k}IUvBgyI}`|tYI z7QCa&?rLvQ8CV0xmg+~PNoL=MDK`V{nGbR$44!3vjOc`fzs_Qkp<{9ACmnEZ!7#-_xm{#^Q%0wvoe z)9#_Ps2N;f!al$?e4geuZyxb88kT7-aOE({WH*wEG9~f514}L69oeaXsS`s(yBJr= z7W}WVA0gFgq&?ore-JK?YiQ4uK2mwZ{4DVtb9pfL1vu7}iEHTEHUU*~AC!vPHUx(=C80C>A%6&b@#L)a?UV9prnVTtH~A^;;$D%Kha#l<4Mj8?7O} znKL5t%Ck{y;CqO5Dg8KGE~RL8;^?s_ue>(p1SLGsp&VW%r1F9*lI-xxRWmVM;Ik5& zwxp@81r@=}xf{l*=LycH8kTl)sPUwWM=C23oAd14A`%>Vy+x9F57;j_T!V?%#ci`*E6F>`k3tJ&$;-sim`1mM04X60_Qld$;kWiTzuOJ&3iPXtRI#$lhl`NjE&4I?+@y?s9 zDA(#Wg!~-#zrnTi#xsC%RkEwW+~8_o?u&o-@J`oXK)FU26l8 z^LZ2eK3Ovok#bRq$_2-UjpveoYPHc4XGjc;C?thafYnD7tb3>=h{GfPs-#r>&M$9s za77#t%}hs7nZT%xfcS7)Eqzc~xI0(Ti9v<^j$^pgG7Sis%qlbY;ED2`!Rra!q#jF$ zsP{M#rz;CTZ@kktclYjLvoJK;09vCkSx9L@kT%1y(Y~5KE|~-9Pr$I}&V?n@tEcrJO?a{7yFA7?r0Z>_|Fyg`!9<2!*HzQ(uaBMSVa;{n)JyQBRTPJY5=9 zs3l5_?(L`;ljkzXEmR0J4R zc~wix@mtQ+tBOC^)7FZ*!nbNLr0Rli2#`Ulw=fJ7zCWzKrTx@l&05O7%BzA;2&7Ku zE<$$o2^>Gs+QdT>nRLAd#`(|3>>g}+f!*E}X6)0?1L+{%Vuit&T#CZWymAXJqsQA49!U=SLNU=7>M&$zwtR(e)e9Z;nUKT%JbHwVbg8 zK?E>utA@g}#SguVgZm|3BRD1CB^@d8K(F<ZK|Sh7$`Kc|RpZ5TS$nDzgl}+*Z$dU>dT`QHe)UbQ|+VCm!C_Dr>{n;pByZ z_6r&H5P7!92bL3^*7416;}lY@idY7a{PJ81oktA}5dtrcq=tOLPNZX>%JYBktSRh> z>5Q}fc3Vx){!U_S+A|iYDg%jkXrxkKA;tp* zf@n5(j+d{RR};VK>qhXEAH`ds8iPQ32Zw{qk90Vw}y9XTSWwfx|a0Gm79hW^Cr7mgtV8>(fSZab)qM zJ_J+V!J1jqKt+v_C7R?Wg6;%bWg2Whjwbu%hW=I=ZBjr6f(1f`I$5P1s{se=b8Wv? zo+c^Ok09a+63}#2Dh~usf$2Y%i09)j-yi2-Xwaa&InuEP%nKI-^-R?6R5mzTK97{e z@nE*Lc2Ym4?fxW|7IQ}X+YJL$n&7sW>i}G$3?Dzhq4}DxG)caaUXG%$0652|h@3M7 z&RKcfEMZ{eT>XGm2SlH~sI@88>MvqTS6bO+%0Bj;2QRoc5c zrtJQVCn&`4mNnxC5 z)1KW_Ugno%@Uu`0-2h_6#a%flVbOnA*Tu%nB8CDJqdTC#*AyfV*W>n)_|Hc@#0+&> zj?=jDW=L7Cvqg+02Rh(QLk%TS6&3#`&ClQzPYX7JTJ(HzKYYV~uRqgpN_z3ywSHmR zO;c(7Jnr3TyU?t;)NKztZpQ5fQ$$5e(pKTjX;@d3+Bl0c%m9nWK|iY4l%TWAPd75( z>5Tm(L-o_H4Zldzr6J(a2&+Rr0nrAuBwPfL5yPAPv_;u>%7lUtuM4PK`r~1 zD}C*S;o{zkx_IX1#iZy^k@)ZwPN=srIw4*Ok~2cxhF<PLE3|6MvEVpl-qa0q7v=pOw6a|Kj}QrL+A3zF*4bv!>$=gBuH!oY_9sJyGPyE z!lxbB@N}w<@7gXDQ?wfLf21A4+hS7Di?P1kx$O-=1_>&io9CF|wz$9n&z*%~H$Xg5 z&osjS(Q>i{tw7^OS2>Umb};BJl7A6yT5!n%maL>`D~^*Yd#Qm;K1d@1Yh1h^XF5@6Fwi+Xzzu7}p;XyldKx5b_oqWX(6l+SaU&+jD5e z$hZs|(feh}fB5?$26^e~Q{a5qOryXs_m&I|FVAh)C{XO|K&HS2c&-zu&2}c`1SJ?* zl!0vcylR#m8sX0*yVY5%b5-X)6piYM_YzeRbzp^u8jmXT(Z-A;VoTt@G1A}Kb3+8l zilu}^N$_YU?5jXG=P#D(b)^U2z4&2Pzx?AziJq6fgA8JgU(W!HbKUnOU841!fMH+k zB|DY(D{Mmc!Do}9UIwgzV*2aGV^_duk)(0Y;6h*96S}C!)S4xY86BRwQ-y2W^>34p zR9N~)Bij^`zEQiO9UZh#dAe@ka{ZU#TDhUa%+f@kdE+?JYzVq90G-hf!m!c8C(bQd zsZET@lW-?_eY7st$W2~)i^kPLw1imYgHVB&;Dg$@-;}Qy(gvXWiBp6B_ZfNNg*q&s<$zY zBff|{%}%eVA$c+Hzn%!uETij{eOY^0~N!iu*J6| zY+hp)_XeuQSt^v!EpWbqRA3q-F#3tmDz*GbDqijb+0M5p$Cw8h@tG)$o@EYnMNW&k zj+9j&BiOhjBNgV)F=YFqtZEs2EuvhEM>Vp0gb@?A>Z$h$6NOcw6~mGR^H*(M1%Z}v zTWs`!hNAVmx4a$jj?<={(50^08a72RJT5=^wV-2=B9mwpBcE{%Q)_Ms*J?spdG3*wK=Vx=xDx7Y!-l^qiCLP_=AoHx(&o6v8VSOoFvm!|}s{OvE+l(Wn@34x2M? zP)|eOIHO_-h4l!jTQ7@GrM{?XD~Ub2CTg$KuVLl&#=RP)R6EB96LU&|tFs*#&9~nZutv zeE;Y6fzyB1LNfEE0uP82>}R0U-v0G;J1v_YJT1h~FG1NYo|G=B1*E26pX6Y{V)MIK znvil~Bc(4Ez}U}|(N+3naAyN{2^lW2l6l+Z*tX>fHh`IS`Kf0@MVCN+JVy6#0`WS? zM?a}Eq%XGE2$YD6Y_Ui5c0BDpterJ|$A>|(^<6Hp3*AzDwsU@n4kgVhXF;D3P*8a0 z--w6LXF_?S*!7R%J)sZ{ zrywTiow=tWsdK-roa_oqgE3f$jPV`0Vj>PgimWJJ7pCs^BD0w{k}$yk*~%mdqV?@X zIJ6;)(epQ&0veQINYcDCV!KDP-}zp1TKo2gUVB2oez`vkNyn;S&-R-_94lg!zP9?i zea--j9*{lU+pzUEaWZUs(71zRagnIrKa9~^<&y$vLpa<69W8IZw#NSmx#fme`GwUs z>Y%R921pNARwt2R*cQZ=bOIjcc+y(2TT2Kkn%=H<;%n;M5BCmbwLt1CS|tHAA^p(H z7MSFFSI@7DwmN4E!1I{LEHQ3@>!}GQ^wRK&yu{|rp2RFX(u)Xw>`)83S!F6&f8`iY z1&}BqQ(OOdG9+Du=pIsv*G%ui!BV~6#mc6o0m!A>3F>dEhu5mUf}$aWCHycx*`&x? ziYIl1gU4$%GA8yRN#`>wotw0!~_#M zF+n08Z!x)PO^?jv7ej~xz^xMgTVOJ4niE@OE0;O|^8R<~PA32@l^0CU9feGzP#Q}x zr*Vx+a%!nSNSR0C@g}fLrk(qCEaCT$jlh3;<=H|Z5Xzkd8vJERi z*4XV9uXMc|Yk1p(7KujT#UK+BR2UkyWP@WIe7Jd2@PZCaqs=t*LQQ(gQeJaZd~L%~ z$PlVEJRjM&bzMz}132S|8I~3oXWf|vruIMkSwJ_5{oReYMI-h80?qh5fB2nxfI7-GH2(;&+ z;heh4l+iI=hhh3}h+ z1-(1aMiN(APRXyi*M#L9i_)#TPzgDP?*tr7QX*RbaV0_>=S0J4iNr~=bVYGdL3>2} zkzc0JgV6pYS$A69j*Tv2@&d8jn#rF+0{{ruE_lkcaf3G5T6l&ir!wOQD8XDt=tIR8 z5{0Jl{0vbBG`&C{dYb9u@sKOL)R0M-fr=nFnmH8t>G*i|of+?Qv)ekzuoE6TnJU4E z2d%r|l}1_MFG@1eGd+^10nfYd7B!S&-FGecf0W`9-cE<;)1N%t(6Vt}6|hDHR|B_BGa54-KXsNwNXn^Fp@MMVM;3Y9Rf zS1=Uzs+`>+z76k`=!8IXcemoRtKh%{028@3b&nqj;`&hY^P=d4s|WLSL*6mW=&3|cl# z_60Y=y1EECUUod$FmHH#L`n!X0P&a>=+aZwYSy~7A%(16Jl-o_I=6|RU5VBkJRzTT zP}TIqx8ytX0q-7*a}4CvKY{5$O7i^S@UPm$R)7B>)N^Z*krJflIm)`UCT=EW?V865 zmR~v6k{AIpyFz22d)6Fvuby@o!Ik#MQq(?ATk0{787vr9K~xi9^vt>zyrB7u|V z2JvjwYoX;Z`dqPJDO@F0RbKDr6CuU7eHS;2K6 zpf9uSI4Vb)(?1jSh=<5(YV1CA#_c!Y^l?2yEVSuWMT$T0hJPT%GQP?(tg@?Q*TS$1 z-Ml+U5R#yIl zYM5yIh?SVuw}5Nt8?v)+7>PF|9f~#+thlQ7V;UmyTj0Yhf#KbJR)xL-fd+WEk~wfUF)t4) z70-o^og*!2yk!mw-Rm&$lqutz=)hGoieapi;50xdj{nNdnNS^%X3=yZlnjv;>Uf@# zYezL|^!yxek%y!E>JNW_G|#2UxC95AuhnV(63({Ob#fa4+hVJcO*ovJne{~|%)Y}r z=E0yRK_k%i$mJ%N!|PF28fAOcD#HgCGfo(t?o=GV)|kqJST@uIu`gp(726%fV7H~f zck{%*(wSPP8Ixg6zN)&siNGI$wLu$%`ArP4QaT%l%clI8csV%9H+ItVJ1GPc0E(sd z!S%)_#so6Rz%=dbU^AADQmZ?a_h&2D0^2d8YP8dA5|yN&P56&DpH{)< zl5*>kGeOk1|6z2kh(~Lt8QG(3oR(}Qh6Fm?yJpcjz zNEcwdXF>C%i~2FVJZ2+Tzk;=HE`xUSuQvi!m=$REPuM7HpF;p74uzL*dLwev)23`r@Bgl1N%SChWrC|R2cqxb%m8Vh!~T;_CRIV_4> z_(pIS0HG>|FbmT7L1~hip?R9)YE+SYta1Aw8(%@gQTA4Bo;KqPyg@#y4pd_e%ZRXz zLtBP+YpYZx0($-&NsM2Fx8WifRDj8GtTv`zIO+E@KIcG$Y0sv?=75k>j3jIi)Qi+1 z!@zHONV&-cBzxTHdjB)vjV=|33Ii*uwAwrgKnjQVLl0XP2%i zK7W!FWWN)Djtm(~I;36v4)0BV^pInQeA-8ATrg5LRolpDJ=!;dcENnu{;?~#w&8F% zSD|9yQd^Oznx1R?sz2WO%%|#bA0=MBKV@?6U}GfXc+quPK?-_|;}uoeu{reTTC9S$ zeu1->Q;)jTuMh1;io;$u>0(@PUJFC`-vx-37<{8)T5M=r(a^{jz`_$2MM*`gN;}01 zOv7A*Jv@xG=^H#GTy`|fJ!F~y4nztWEZFyt-%_6E@IeX#X*LAxj>$f~&z&dU z7aT$yjVS6z^BrBTk>b@QnB0n;Q&`K95T0Jg=)`g@n=8c^{0Q34<07nhh&^T7({+ke|1B-=X(TbwTyjw5RME7 z*95VB?0@?pGIxeolD{D+6q}zXAG8Cd2RUG~VjAz+E&1|z@GfLN8{bu;Jm0A1mNC=&u@2^J5%*ZQTibSZW9r^NULvpJF}F$?6-pU zOI7zDV5#_~cbiEHGSdM`bdpeqCX(i_i>hyBs?2+$q-Df7OfoDE%im|g_`C-`9)rq+jzCtyY2OaO1elAM5f$qhG z@yrKi15RPt=)$CN@1My)rIq3F8c8h2`-fEt>InoZ$)tp3I*pPVghnr~e{@PQx~EsY zz-l-{X9b$jv?53$xO`Z%6z-P9yU~W}?)Z=+{g_2Dy8v*{<^z~Io)0Y%t414}x-iTW z!c1d#E>I#{S)hUP(#s$j)6;Ng=v#Ql5b|urCe;F{)k>OhrMtQn8H!9hQ{c?|%-;PO zUkK_NtAwr*%v^tp{-_!6T>)B{it;#Oh4HHsgK4)$eMQ@=UNDHBX&A}3{-2(7;L2g3 zKMFt|zl&S>DrgpNBmz2DE0uRY9Su{qn$$~Y{MeIwQXZh8hWL|7;=NZ8N<8b%Rqzv* z0^@-uj4K)kPN;n-D>TLi36IJX2bZ9HEIG^E*fFZiISWa=-8SKnvf{wnMmLCt>6{~i z!q~GmnO&^(q))2Xw)Xn|tSM3)k-{Uq zgDopK(BG&k%+0$ss+Y$MrYRQ;z-!X+M5MUMTlS~7;w)u3Mo`D`>dK;g3iORG11eJ( z(*C)SyKQl|Cp!drBOfpvz9(EWXzH;2%~LM5pUV;=#{_*M$*sx(fCJb+g+wj!i2v_1 z1l#=_Doixko8y%`Cv6ox7t>>EohLyk?uHiX&gZwv4Ph`ed(TX3kqULe5a$c_hF?DF z34w3YaaJ-d89!Ftu|(5pGiQfS!(C}-*74L4^z7_($LAo{DT4DJ=S`W4>h>IFva3$W z-38e^B~<5#6%O}S>5_03KX?d(JdmmSmL?Fwla0ilqpi#}DH(3f{2uZmM)X=a>d{9j zqA_4B!~vR?JStMI`70|zs#O5G9cs6N=57@C0sZ&S#_k6$&m=+o9Ho3qV2!<13w-YQvj&pbiDR?zbJ|wv)7eFAWp%(l4mLHod9_WxE5vXFmYIHU zbp>M6?096-^K>gRX3@6y_+ikO@cRcQHOSYrhn3t1s|Sl#Zw}EmQ`CSS@y)f# zxj>i)$`?VPFrle% zmCI~g#u8&{&FxQ)+`sW;U9X@s-JsnB&+aJ2@dCU)i##tzX?R>~p1wq@u%(_&du)|U zSg*Hote}^=r)`oGdQTZ_ZlW}~9e)dn%K(|b9r#-KO*UL!{hMfQC8)Zq!-|p^5(vO8 zh*?;`w_J(Zj0GE+Z3>4iP*%k51j3WxWzwZwES*|FVAYzP+=No*zad%}E(Xc{!D|!9{SjcS1!o(J9HqZWIGaI9{&(WvVEDP+ zNp9}2O?e~chpw`|KI?C3uqG1=K$N5Ivw)T^&P|Ux<*PgL)UG%Fe4GoUda;ln7MaEV zS7qInrEn+V0c0c5H&|XtJ5`>kbwH)dzxP3WfEaZxD;idO&>nKYm;y(A`#>*}-sLgy*F-+VQ6 z(%FgtVyIoN`-#k7Q_(9&(#XfWV_E!B8?_3HKgKQaopi-!<4$J_PuF!B=)V;=g9Moio1x#5JO&V%J0!J~(Yre|;^0OA6a3z<);)YW)=3?;p!ijYXe{#K~l6O(bgVQ(a-AyV3T`pQumCK zI2s?$%xjKfhlbSODqstR46sd6>8#TEjf7FMrZDy@bo&8R@~LY~2$rv_VR9ncQUPwU zk)DB~@#3?v-572H@o0EMu=;;OUh27pnXeVJTf4hhBakGn5vUx3DRR*&pto=Li}*VeqPvWfK0oPuvsf>^jZOz`AMcg{vA8IJ`Ia zfTRBB=2OB&c$p@747+|>z}YSmz4t$l1pWuT1m9+f**dOBH5aUDW^MC8T1)3HiD@iL z1{JeJp%`V@6+v#mivPW@ugI3a>H^U3t=60C-1mNdzb#B%r>~vI%`PETWZwM~PPol6 z0%wDrTl#)TT)kUb8uPatUBp3L4mqlyfUt6`7EJaS<5lfmg6{;A@NWt563-qLS5^iM zCDN%=D>mo^S-K1e1>+e}VD%bUmmu4e#17$}CFshW5r9hEiws=iGigiW)Fr$8t38nE zE&ji`N08;;l$A59Oh6auq|BiPlhJ}BI(20OWRrB5d_L*@uL*&T{=8etj-R~xd5exn zxjrV+e(BD%e9UR+hXgT+-<{z;1XT4RoATZU-AvaMd&ODWkH4o?<#PT`dWS|DZ6 zSj)M`I`4Y#z(RlDo#&;Qc7{vVNnE{zNhrK02>jwMI`3vgN==)?4B}jcV~Y7G&Cn!6 zPmO!Y{=r))*Zol>A2171A{w3XK2E6cN7&LMBfnvtg#V-$D=lm;UOB7u%GtU{w{PzI zZEO&!sBZAfiq2XUEev%6Fm3l9QH!vv**yQlAx8CR9e=p7$ByaSAmrks^W3SzZLnQ4 zA;Mgj)Ma619-oK@!kFrbYw=q=nYLh$>)jCWF&KhXv&NG)+|3>H%=UWb7&D%*S-!rh z&AEw!wvJ@}DSjKAh2M#h$L^5XBN@axO%zS2R5jSZ$e@BEZ=H?~A6yj}1sn^!89K<( zn&DrzSFkmDIUd)nNOcEq%WiaVr(%j47Bz#15VW5p>aFTvYkG5V!-<#{QzA&vYDk3e z@p9pP?*XXnyMR@OaL`VD5Xrv0ZGMfnVPJPG!jTIj7UasTt86TrxKU50A4yl`F=pPl zY9h?geS!IX+xqyTCFIlSm zm~iV&TL}~Cp=4<%qER&}TNCr83bzT9+@tNy$j>05%+b=?V%u8c9{Ui=f?-Tv!8D#S zJIs0vBh;r0`)AeESOc8<;Lcpr``XW14z&E49xp}g=iWT!HYo`uT&Sc9z^e0Q$8IA? z7T`h;WjoQ*V~{1p#bSd}ml2jv9P<24MfKR{c^T8ISt?BE^o!lkpKrcvoPg0MyI(DE zQEJ2Cl7{MmUwh{E1VKe#B+IA>_WzAwqu11Q7e4+iwOfleG&fgDR`NV6;VU~71aoR) z2n#%j_^Vm|-C{|zYL^s>J2Qp`<59AvM)xHXk@RXKrSv7Ep*3YtB4`J-rY{>NKq=A? z6j1vOZD9k>yLb;#2kv`Or?%ISw1wcTP?jk2IQZG>edYP^LdtCM+o{^jafbIwe1zbl zO-I*fLu2p9g;Ub5*p6Ih3z3E5tkANL{O$MCdHDp9oU?7J!5gBh4d=9;+XBCundp`7@1^O#;ryJdqjvogS(Akl<=MC zHGC=~$;n=%sKmT;WJU-<{EuEe#)un-)qx$80jByIfx#Bx?d?&)-!Imtq+uGo*}yt?{jtb|BKx1giUJF zJn?3j|CKFra1nz#<#f@=AT@QYcMai~K^kBjr(3NLd{}NSFFmGQflP(Nu50~uq1B!s z{@KVi=k?zdx0s(f3n9pb5_}8EXy-g{RC3P%Da`)Eog(8_P~dQ4!`{WDI`#r>p)Ey! zypP^i9h<$?YE}X10SHh(psYeoCJWV!W>q<2_UbV+Q9p?%iih&E<@@jf9F&8J>2oBSR8B^}7FjiwZWu9^)x`F+pSRh>zBLZdO zfI_=!SSnKDoe;s1>R_Zp_wA4CHS$aVC5cNL-<=*NX`IIVdLJ|U!C|3z0c9PG`1n@0 zN}M&+*1Jvz*-IpvTJorJk&Lhp7^qpzpa}Ky_wNvbBA65308{^;7TB3#*&BaJ@7sQe zDD?Pg>%J2V7Beb>>4SHi(plf=9tS6OBnC_fs3RhC<^?AETP5mG>Yg5&o~|f}qgmQV z%)T1Nq$19A8SqCdX%(iPpo;xd3P=|kUbgW?QJ}zl)HP`$>?)w%x=-HY`ZAUFy>GZ^ zZ4y4=FrOP9X9e@wk)KwUz>SNZECWXn%Ad1-_Uy1;c36mMLYL#yS)ZQ1yd%(jz#etB zs4eV9uC45w>#30edqcS7IdTL|HU@5DXEUe$Y*$6|ZZp$V5-6_I2P`34GB}Bt$zfun|IgU0&V&zH_`ne^H2ijw!XsXJ9}eNuvS zv{=upIG{j*7IXBd{?YBWkm#|1Vv`!*CZ7YEkU9OKdZ0m+rcHInxzZfbhYgG)#X?U+ zap2uYH>dfWSKd2mcXUWXCnDPGSE7nbw;}!C}rg6s5OP3CpIZ*Sdj-oKCdnA#4oYC0h<4s>{wYI)$ z@v#D{`+TlP40ed2+__Vs#cw>qh9NpvgP@LX^Z0Gv!`MMzX}1&zoCkF7EDeIH(LNiE zS~HjAD<2`ENN)f)b1c`ZgWi>}@Pal%zrPGy9fMG;r0y$mjtXv@?K&2yR9HnNMfhqMUqjc=XnK~>pE~14u}S#d zMpO;D^bh7e8jdu~_ai&eb8>H|+s&Q994Ep6o=JthAbtZPE-2%FIs#qinNOvCyqXO- z3BFW~sS{SEpWT_6kft7#tydr6Ig88u-xsdrwqLzo4^takttUfI$gmjt5|~7w%%0g> zlpOD$iLKNv}%d(kQf&9vxs?i zX#&WUwEVTQ=9Uk=SD*{)jzZD=(n*E^xDh?VBvS`_7+C{Yw%-RKVV8dNVn3%wgM>fk z!xeP@H)MpbrmaV6qo9P0)%tX-wBQ&gEJMDBgH|=Y`3=d@yEB&GX11KR_AU-f6on7A zA7+_#!|ZEhyG0dP*^10iCGBO@0U{2^|4kCD8yKfPo^&U&hLRUtk^FiT^z=46iW((h zApHhSGSx_a)vgFqV!-jGafr%fP;w9htPEE>umOSFVr5QHl!FwF?OXfSUjX^xGT2Gimy2?wv#2M$7Qe ztMxDo8+lj+TRDsA=sNbzr=%2sZucudw^WSSSH~z(ojOU21p|R=rxmWFyVAkT5CWeY za(T5&nI+`D8-@n1;EkLaX)9y3uLQt2&eZ~ln7h@aE;hq%oQE1c;F=>QWZRp}{Hd$fr<;PMVes z(Ojc`&+m|Ce_;A(lK&r*3RF@Ju`V+aC#$#W&h;*ADQcFweeq|d5t5{YjU{n__*PT* zz8{~YX3DRt-~kkhp+Bs%qh^c?(?siV@ewyddNVa4?e5MGq+vQb30IQ|{jWuzwaw4P zqh$TTGp|-I@gnT%i0O9?Cvj3O-8TVrkVJWaN`8OriSFXKH%C*}xridp+b~cV3i}_q$#gWi8}k$E6SVIxgqs$(bLDgWgDT zx2;Np$#yH+V^`VQ?73yg{C*gs4DM75HN7mtjNJxXxd8=41W!Ei=2}?Xyr+SdXaGzHj*=djGSuC&x!o}0BUhOr=VpyyM22mT znfu5U42aOn4`y`i7Rcc`b*ZcC1XSH19gGfwtbIfQ$H^uV={Y1UW0y>x)&P8RYKuHO zw}Zoiix&%vjuPDp>41LsM>+pyowdHaE;o8ieqAZ=*I&m1XE6)pUkdWKX2>jiwz-^UcE3K`^6OI;5Hli__r9c>2_IYq=m zXtQK|g`Nb5Ky(L>`@wgp5tnhCg-@$d!L@B8_2+>QRk{e>@N0DBoGiwXE>t`?Wr;g$ ze}W@g;G_Lso_JD85R`W7Q8($+t*beXGq8f~Ar$Tc*P2JDnKlr{$kq4sG#EI?UCBS? zUrrVKmKet!vcqq>HDIn1%LK=eh~Qy{YC|FDh@!TzS+?rlGP_Yy+4#8lHKR236blpZ zs^z~b9(W8Rh|KM$uB5uSss`eK8ezlpMs&+wM%81cu*k6Pj23UbgFrh6zw``@Ywml&SqF zP=#PTQ26VeyI2onV1wg;&WT+4f|Y1ZeV&s!%O9FGS2f^6>7NZ_taLKdl% z71^=aJ11`Nle;%RtwSEHntfUdv4-KCjM@DPq=$y_EsceoR**N5X<&?-0;n~&7;PE z=-Ul}cm*f7+uNaX)O^W7h5~9pVo80LOJKVdl-@(>6mQ{5A?;_ZmTAAKum&@9>00K3 zKL9zLto;$bwClIvoeV`I=Z*Cg!E8vi%iExp{7~tP5z>PC*QW^`7rXyZD}+itu?C)N zNKo)C^hfj}fnv5}C|mpQ7GZ$CLZM9n2)>o%{dbAkTbwYFGG~b{Fp2>l#^>I`ucBQ# z|LQ%LsR?W+z++7$?RaPYXllsGM5PFrn@_9STV@sib=Rt>=st0`yJ*ga{{1kk&c%3O z3{_MT9&kAml_C6WnBAK^Cj+~J!;n)mLO>J?2s$Zx{ zSg*cX|A{zKRb7N-RQ8oeRLu8lW2iGyI!y118xP#>dJAtBZ`<_MxM%%5WU}x5 zb%Zlzu)+ACBm2%wM=%%NwM^tITW5$1Fx$4QQ|H0D2)3aW1#KdxM#+c1lHva{iSPT$aftC7opNqGFGwa=n!QnujHf$Pdw;~WU5 zfsV)q=lYz(5)D`vD%GoU+B}ct6v{(g&O*+S?&nJ)Q zOO2|lJ*VTWHzD19@SYZOhg3;qh$=T#W@$*~lNFzRzNWvr78xWQ4(&$T9b8h^f zk>G6F`lB>2MnP(Uj)Nsh>r0(U^b|^UZ%y&NOC@8nnlgOwypT*U+;t{@Q)rBfbqcmXhLwP3?SFq(*SiwU!3c9w*^n`3zs zHu)olEsdKd%YEo$eYTh&<;-q0$a#qRriPJZ*3mI*C~=;*)v0_;*O-*BGFyNH2H(cG)1AL7tV0IS6%6UB zM*?9a68e)1!3B3;Sjlsqd_3n`kpd2{tHTR5XNPam2*xLvj5C2&tqQg$t=a)-& z7)DG>tk5x@MBaM6$^kip=)OIY&+r;*wC)gb|0~ce6-%RxGC!q4FAu@K!8fn=`qo;5 zrZZ8!k62{j&!S2R;A=7RVqaE`b8%UOBBg3d&oXC)u!3f?Z;@G0LzlGe=eY`_;-^nO z&JAz5I{)?YjlmFr{k6d{#k~rvWB&F1wSsgGF%qro3M6noO!%h-;|9d z`C{tIi_8ujBN-U`pr1Dyv8L9RxIc+i@U7*|8Gy=oyO{DLYmV@}r_d-oi@z676to+G z++Ss@4?R(+VI^6|E`HJD;X}$E(1-6_upU`_36LX|aKAji3k9BN6r9O#mP4^Sg%Ujd zF#GGf7a7My=Mk*`$UVZX$@)&?LiNP}IdAAJK@6UGbQh~`{aPyvmt8^DqeBK4Rj+7o z>Kkm3!ffr_t%3*Cx~ni4D}0bQfP9fc6!9gD1bO~LJV;ppY@p76OcW12wV!^5#6L@L zvNbQg*$l^H5^rN609wKwy1R@@xqW(Z7vZO6UiRUkF% zS@90$QHv%zqS~UU97$U_miYKws13Ws=Et8oND#PppaBEV7 z=Uz3bCjsY^S#=PCiU_vOq&gM0In4|LEk*VP;w}98oWz1-9GcLaR58JQ^9vuZ8c*0w zRF-v~RRsG%MKFj9syUH}Le#Jy#17g^ zrnq(#kV9GDTvl~k-f!=(&zn`2K-EWReN+wZrEY2b+pIR@$|0D@hC!yGS(YLT38yAK zEUmr#N zUkgt@Loacf&-@ffO~w~&KocwvcO%Nt_YLWnN`v0lSHFUM(|@cMlaik+AHpfeFpMa+ ztFl`qz>EqL@h?CIM!Kznk*js)#*|t83A z^e_*(Bu5m?VSplFO2;I%h*^l06Odhq@btVgIxJylOalR^l0A*M-8q4WjH-t6d-m$1F(UZGqwK@)$1OFY(Kozte`KQ>8luG>d+SeIpH!-= zh^dSzWt?PCLemCy%6xPyM>jumr!_5HQnxQT;8$p31CS?TfdBqf9dKS1E=_%6JRR-z z2>Pu)k_HMBBwwJN!ONoB*uQo4p#4_9qp$o*$O{aEs4dQ-7|gY2iA|DlyNzqO#F7I7 zr}OR0>=8>ivNiVLGtW(5W z7mRp~e@6+;uGMk4bP~lESJ8^c;eSfWtp~ z39O_Jdkj#qn?jic-?C&VX7RY{H%jkR}p3+2ht~-@2gto z#U~12_c1;V?1^5C`HnmZ|E)E4;@wi#Ssojvx#W>^nbtHcFI6(A~e3fHz)_ z3_*Hn&U3oW$&!pXWrQSm;JTogZnj{H5Hdv;cyJDNc>QdYk!z+M)IF6Z4BrLTIhYDN z1QX6zO3rRd&;-3`uE`q^*||12m_oTEJlbajm;U>{;tV3YJ`|%AfpLqo?y%bW|Htvh z@i3Gf$B%vU-hxt4IwjBx%8%(H0I#>7Q15B*{MC-nX9U^9S6U5oT4@dyYOJkucAr&5 zvotqs*nuS4=$6p zSWGkZ)Es?oh)?otmLc9-xCEZf#@^-=h{Mj28Kz6BBVCWMDat)s z49=gYH{EYHpY@{1xl1KkU|)6QLA?NxV@Sq^4T$5LkPJcKbw`=Sx-sx0uI||4S7QA! zYe=g+rsU+*lh%k#8g!ZpP6_U!Sc2J7(?~I#6>w??p_-XHYgs`c@-1XRqpC;YyhMKY z12HJU4{BvzmhA=dHn%3vRrxIDu_aJ~98H>)ty7Vv8p1v$=iPCb3Mj$4^1}(G;w&D5 z&C@ZqWHd`qn(DL9N_X6JAUNs-mLlOL_s{Jt1IZ~Xav*bv{zNE=jm{pbJe#m;w*-b3 z^Cu0Vpb?a$;w+zKee&yGdQH9+2zRqSG+$s9uaDLnjgV}XT`DYVpP_rdio*eiD<(z{ z4h)b@tX-(Tzxvv!#P*7DcnTdhmto$Tuz|TZFFJo?QfW20|Fm@#5E=@}I@Ja{@f=XI z60f2a@Zn~m_wq5~OA8wo_I9UM2|EnjNc4uvDqVabcKspDHpMRnX-dI9+wgtLO?Jn$ z^Tp09@OAP3%mR=RrB{kBo0aw~LSF*W*-L>Bj7bWo+7jD0kiR+NR=hA^QRKkR&#mbp z)Q+Hjh8cH8j8h&{4Fzvx$EY{p%qUT%M=kXciVoa25ei$0rdZb(Op8W3A`!5Xe6JEGSUAU{DR(E& ziT2fTKWIMuY&tBUlf|LClKN*!dCpJjQj;lg0THlz|9b{F%Q_)!Bpnu%nyNcwTSPN4 zi^#tM4$umLFH=fu^XCf;W9>VOE)$2*xM?-JM}J}R>Czka54F&%W4Y6vYSYOMAdO^~ zjfpDp>|clPj-cZP-m~CCRYS%yIO(U9I4SDJ9#uOn=13zy-Azv<_XkV2f^(hn@`hY+?gej~P{_9FwKFKxSb~95wjPZsU(c&Kg{B5&rMxjYPvY zs>{mz!IjO5IZu{V=Dc*jxId8B;FEKv_KQV~RBECCwB4p&n|MX0gzrnP8AkFdX(1rI zETiQx#qvmc^;(lfB~i?fiNicBS>mLsrXo}$Hni0%{wJVE*Gqh)v(<$3zsHPazDFh8NF;~q-m~Ln+0c!tH*HU0FRyL5M=x*P z65q3QQs7vY5dlWczf>hcxYcTH3T11Wa!&M5!DhK{;}GkK8VY0*C55P;D`aky@E!9o zHOUK=B}j}qiybd0$Dv^QKlhRS`iRXMAT_}h z8`^PKLsx&&C!Yjtt4O)gf!#cWSvl>WDf_+apCG3puNYUd%mClpRvC_PN+`1ZP%KBa zwiySSWGWI-@8KPRIV=hKUdumzg6NAqg(Z+Xyt^)c*XuS!SM@;U(c|@UCl1@<8rn(p>(a7T0<;q-k|t zIZ#zZGtc%q`Te}a9DKvqLuFG-6*opdNuOzAux~m#A8OJuk)`~Q?{hmBUW!lO^+}n63jItvGw0>hW zRY^u`_Eq{N-tD2-$)t|Z0&v3BD4u>!TZ;tl@l%2^uBC5h4<~DNQg(r2C1YvKNsep$ zDP7Ic8QAnTw)pWV8y8pNb-D{t>W)SRZVG?xi6Y{4n{sacvZwO2k#ApzXZ?(IsnAAk z#0epo!^y57_wo*v8eUm~oxLu3!T7{S?w2)2c^$T-5O{V?P<6zEsO&*jxs)BzIXXRwU z{q*#4nJ?FDMjP^bT3I_5{q2xGd!EkDrpi=sz>}#H<33NljY2D4N1{@IW-A9t!uq$s zL|k>B{1|rUb>5%KXh-ECum$CB|8+lnG+8|;2M?k7v6JTi?YfJP)O8(nqD@f!nQ%o- z%Jb#a-3#zt+8SC=a~9l_lkHhLHvf=q$!_QM0<7Ujdk}t_Fe+#Tlq}f1-~JpSVSGA` z9w^`0;-JOjDsB**ki6GABoT@*0}HpWvzVcP^}#}U!Kpeo!P)5v`jsz*(@E$^~OVb;7QA_3BnT;%Zlr(`Za5|aS|3e@knUq^`K zJJmV`SmZCj(PP}aqD0K(mb9=6xY?4#%QOeA5&^zE{)pl!pP6COhUxCCqq3c@jo#&k zKnC%C5c!V%^Eq%pN+q{IG#sYZc>R2>JFZw3Dr)smT%efROJWEqtRI-|Wcs$4BBazD zTLB=u=n-_uk*hRbBC8Y;$EvS-h{!dh`;5YaZ0gdhYVv_LBhpzW6Vgi?*J!*k0Zvxl zB5RSsueUj87hPv8_AvxNGo>qk9LI+hE~&6t9f)JBy~k+e4L2!5<5K1t_$^wWleETZ4cNc*QI{8vfdAC2qZ2w*b8OO5i#vl!&M;+6hTEJJ+MT#*$G>4okx0H=wCu zgJB`aJM>2*Ym`*o?I`31mC&eIP22j|0gL+%QaX=kpuaqdsR1wB*`dX+9D|fTX6&#u z?u&(qpPI{jm<7fBL!4vRsyDI!>yOEupPPwdW0(<#T1$0qkfYaCy z3Gag1brU0l*X@u^`&Q9QhRBFG}Byi-E;Se3OLT;t0L>nW-Hh-k6>S z@{0;*X}xbdr8BI}hXETYJT@eRDJeswq88W#SV490L$Wr{{BA!h=6ti&Rk+{RHQUsl zVEX#HQ!7&gzf!(bn*B2;ozCPZBdI`Rn`MVxX*gE1AKrdafL$Henr#U=y8Me#ZFW1)vYM0b~)DT05jH8gpRDIypswF3y;OE5y-)#mSO+ zyU3g*Xmdzupt_iw951+$6*}0o^Xue4m~6gWA-#pj|7@;0niPoHZc7L}6Wt?TnKJ;H zTjBwOb2C)ZO9Rntlec$aD%%KXs#zgbCN!|W+GR+PG?z3?7_TDosN$6}#m%#ke+Lpr zDsX_NKu>~|7;fz{uLyJP9GJSP<`akh$|GB#<+=YXwu%mmcW^J1DyF7uG_i{4UHgtQ zmj4GNoP87tE(e6Anq$s0EYOo2ttg1?BX6ikRQu&kwG9@ALIBC7I#(A(0l&E9l-5(w zGb%U43_`_3z~>2ir@yWI#?h}^IMBB(jOaG;! zrYh%A68C8O)a?Eh#1iMj-Y33{&UBa;B=uxq_%|^O1DJ(@MOHY(uBQTyri+I0OM!lR z^vN{0kIg^&=>a`y?AI_D;gpQ%d5mnINL$uWMBif#V6xHgN<6my)R3~Lnmyz#TftW} zExz3Zv@uL!tX2O|W8Qb_3*sUJB}v8~iP1KppOfET&Vw0@JJVLJ8btyJpQ$roRok{Q zpC1Aeq@=(5HU9gv(dItflDMqluR3CI22gefB(ruzRdwe)+9c>lyOw0F|B81HnkzE{pTyE#HznmKzJIB6av^^*W9z2F z^{`8~A4FY#8EvI&tUmuzdNkiRH@2uOjj)6?j;k*%DvvSPlKxBscqY7O>_){Z&McFdcfc+1owq#c2ndsWj zCyzGk=Gp#rrTBX0o1W#+-&->k%QZ+^m@!2MFOvMB>3G5Cf^F|t(pi> zcM1uU^VRVFE~>L^FSlS46gy4Q+2LKE`h~lNPHYIekGf= zYm~8190DnANpeTI!#z6d%&D;7>!_~@dQ~RKV+^*%mEfb^tR$3WtxMY~nOGUw_KB9n zQ>Id3(%c~w3lqc`8Y>GQuhxD{Wlj3!MJ5Az2FVry(63K}5%&-nFPNB?1)rYEghdl_ z-Z^q2oWj}+pxqGepN`mTceQ2&2{JThj8~2TPr(;=U(t%Tx_q>rW7!uRMYjT)1|NsD zubrw19@A^#LO}BFJrD!kjo4~jS(q|wQ=c~R{%Z%$3sH3bg;8d$!(&lJ?w}>s- zUq@<+$UX7E=!p-mIhbrQ%;WjLRQVGU8y@&8XAFi#5!OeE+ebloXp=9k5uT}_+SWi- zMBtDk-Nu^t>Sx*L`(UEfD?QED3x$?Sno6-wh4CFw`(Mgj_I6(4rIGD@5%uX>r!Uld zHNDa@h*6yjZ5t^peB6&$VH`9;kf#YC{iZKd4$bQ7FoQWr9q>{QM7~he((FGyUqz(~ zEQ9ID7WB7yQIb&#cTYVzlqktB}BNCyS8`na(-O`xVmZq!<|Vhqao1E z$aB9o!XR$YLYb3`wrTria5f^X+OtOzcGN>?`)IXm^d437NQxr_7w8n|SSx>i!XH^( z!>13=J7yiiA|tNXB^8fJN*5${Z*e|{R~RP=1`~sa9OLLX=a4n~d+74Bhn+T=6m+Iz z5e>)eyqF;p8U(qr(LL*R7HxMc+y#>;tXJuMs^mAJU$87z z3|v~M5-Vk~L7d|E>&>zxgwBN!CuKegx|B zTD=3xw#we_3Wb3bpp;?pxC>iRe(|@ee17~9W-MYx_06bYh!+yBqi4Nw?lHDL2@qT( zM!I+Z*W^ks{*-GCAB_WpDtRP*!U+UlWKZz{cJ>ZIo?y!wB$l^>;&RC~dYUy}5YWY&FYd(0E`qMQrVL z_xqT6r-O*}k!rQU3}tIG=b6fQgxp9>ywdJL^H=kJQ-(qj5^UF?HWp@wcnI0IUZHn* zDFbw0^MMG)dkp$~b4{n4R|PRmiP6Sr9*})k>Ltjrr2xn3W0+Iwn>_ag_F(=*Adv#uC36!#^e<|^k7g){-jFP@wm0} z-B(4I^DC@B`U$?>@ui)NkKB@Kxl~PwcN=cQ40(M1wOOZ2ZEJ@7U+n1XtGqm2l$LU8 z3H_8_16a|)^cyB_`G6$)w-r@nJH>y0J&tT2B7`R(q)9wA$!BJU4d#NB#l`H974c7?)m5l$T6& zB#QP0@IZgkqw{`H`UcHOs4y8-)7_?lUKV$-gXO`8&*s`sW01pGE05UO@7*`pV9DL{E`>2Ld8mxb@8+EmHTTC8oAU)%fOqXcN zuIO1oV5ST?iwx+Xyc{j>Y!bSwG*E#(kC$0Qs2`l@G%K2>24u(uiK)uhx(Z^tULq@c z@Anh@vD%9Hy;;FQYoM9plA=)wCD$P-UL=HqCMTOohu_v13QviD|Mu#XNFy9vNuCz2 zp^!sI>R%q^rlDbXJ8|hXJlZG&$-$De1u=~#{hqcSI_z81a}UX9izD_>zJ>E3=>NBr zgoMRQ8zR!w=`7z-STZi&N12h)EY;>r(&s(NCwdPUa>s6`Orzu<{m|sOneamw@bO3Q zx|S_>Zy_e1Eppi3pf9^wb8xLhoCpS6DE$nBdxP|qCxqhy$W=Efu*ZgOj7Zk>UuR(M z_XZt0zfhfele@&x^;hafw+L~v`0Uclde*PS#Vs&*a0KqQbYW^;eAo&O6a^*_An&;x zkX^{#K7>TG*@ot%vcTGxX8K|8aLqbvxrSlls2`vGd#L+0xW2h+h~V~eKR$0~3Tp$B za`|G4U}QR9i&&hCuhPBM*!7=?mz{^Y{xGZgGWfY1VF;Iti__E82qyh3CXSD@2@N6 zgoW7XA^=`8lXpprAUMTTdF!C|qU9rhi(|82IxL(^*|;OhWM~m-Xdb8k*PtA<+bzwk z8}ey?0B>&ndz3DF@D`rckvtRJ5XE^zIJ4t}MJIz2-NT&8ZM$FHZE{Q7-ixnWeDpo%vU>iPvgPA%o_r!|rf>LJ zm7PsAFt5ZkLvrF)uv*#^4Wj^R=y@SU3KkPXPdS~y=dr2e{h|x9?&FIWk8lAiU59-m zhq}N+Y;cS^X^hQE=OZKtgRS*X$M%hm#xs&T=09KXJisn{slnj z%plYvzpVrnHPy1vT6f?ok}m`qc&T?RroCK{QuJv*<0~Y<%_kecZswZ=UY^WGL9n;?;(&?u zD?nSS9R3cvJ(#lt44uFc=+U6v^}t)J(xy9t`e{Rr6P=}q>2vwTDyI@5syHxYoQX!S zcgDNBe)~3Fw45!slE^29C@|0Xfkm5)T3z7Ukc+bnp8^*0-^N*}Z-XT__%7{#UhWjM z)gGxj)gfGU`LNBag=%pY9H34Xvi+`vY9U4g>lNNe$`Scp+#1&en7 zeyXt9Vd&CLhMB}P=UgXi!h4NbIqzPvxl(1vZBHtq%K#MkP=8IEOo~U0b1ft3K2Ti4;7KRi9IVoQ1Du&J yEJe+ufQ)3t`Tc51zR(InS)bTHlNgJ%NP1Rde}3jk*i000R~o6`CK diff --git a/programs/develop/cedit/SRC/CEdit.ob07 b/programs/develop/cedit/SRC/CEdit.ob07 index 68478635f6..6e007d379b 100644 --- a/programs/develop/cedit/SRC/CEdit.ob07 +++ b/programs/develop/cedit/SRC/CEdit.ob07 @@ -28,7 +28,7 @@ IMPORT RW, Ini, box_lib, Icons; CONST - header = "CEdit (14-jun-2021)"; + header = "CEdit (15-jun-2021)"; ShellFilter = ""; EditFilter = "SH|ASM|TXT|INC|OB07|C|CPP|H|PAS|PP|LUA|INI"; @@ -78,15 +78,16 @@ CONST btnTop = MainMenuHeight + 3; toolBtnSize = 24; toolbarDelim = 7; + iconPad = (toolBtnSize - Icons.SIZE) DIV 2; TOP = btnTop + toolBtnSize + 7; RIGHT = scrollWidth - 2; - BOTTOM = scrollWidth + 25; + BOTTOM = scrollWidth + 18; minWinWidth = 635; minWinHeight = 542; SEARCH_PADDING = 10; - searchLeft = 10; + searchLeft = 0; EditBox_Width = 180; EDITBOX_MAXCHARS = 500; @@ -270,8 +271,6 @@ END Replaced; PROCEDURE toolbarIcons; -CONST - iconPad = (toolBtnSize - Icons.SIZE) DIV 2; VAR x, color: INTEGER; BEGIN @@ -329,7 +328,7 @@ END toolbarIcons; PROCEDURE WriteModified (x, y: INTEGER); BEGIN modified := text.modified; - K.DrawRect(x, TOP + canvas.height + scrollWidth - 1, 9*fontWidth, BOTTOM - scrollWidth + 1, K.winColor); + K.DrawRect(x, TOP + canvas.height + scrollWidth - 1, 8*fontWidth, BOTTOM - scrollWidth + 1, K.winColor); IF modified THEN K.DrawText866(x, y, K.textColor, "modified") END @@ -353,7 +352,7 @@ BEGIN WritePos(y); IF modified # text.modified THEN - WriteModified(width - 9*fontWidth, y) + WriteModified(width - 8*fontWidth, y) END; T.getScroll(text, scrollX, scrollY); @@ -445,8 +444,6 @@ END SearchPanel; PROCEDURE draw_window; -CONST - iconPad = (toolBtnSize - Icons.SIZE) DIV 2; VAR width, height, x, y: INTEGER; @@ -527,13 +524,13 @@ BEGIN INC(x, toolBtnSize + 5 + toolbarDelim); drawToolbarBtn(btnBuild, x); - Icons.draw(icons, 54, x + iconPad, btnTop + iconPad); INC(x, toolBtnSize + 5); drawToolbarBtn(btnRun, x); - Icons.draw(icons, 53, x + iconPad, btnTop + iconPad); INC(x, toolBtnSize + 5); + toolbarIcons; + K.CreateButton(btnUp, LEFT + canvas.width - 1, TOP, scrollWidth - 1, scrollWidth, K.btnColor, 0X); K.DrawText69(LEFT + canvas.width - 1 + (scrollWidth - 6) DIV 2, TOP + (scrollWidth - 9) DIV 2, K.btnTextColor, 18X); K.CreateButton(btnDown, LEFT + canvas.width - 1, TOP + canvas.height - scrollWidth - 1, scrollWidth - 1, scrollWidth, K.btnColor, 0X); @@ -549,19 +546,19 @@ BEGIN y := (btnHeight - fontHeight) DIV 2 + btnTop; CASE text.enc OF - |E.UTF8: K.DrawText866(width - 6*fontWidth, y, K.textColor, "UTF-8") - |E.UTF8BOM: K.DrawText866(width - 10*fontWidth, y, K.textColor, "UTF-8-BOM") - |E.CP866: K.DrawText866(width - 6*fontWidth, y, K.textColor, "CP866") - |E.W1251: K.DrawText866(width - 13*fontWidth, y, K.textColor, "Windows-1251") + |E.UTF8: K.DrawText866(width - 5*fontWidth, y, K.textColor, "UTF-8") + |E.UTF8BOM: K.DrawText866(width - 9*fontWidth, y, K.textColor, "UTF-8-BOM") + |E.CP866: K.DrawText866(width - 5*fontWidth, y, K.textColor, "CP866") + |E.W1251: K.DrawText866(width - 12*fontWidth, y, K.textColor, "Windows-1251") END; IF search THEN SearchPanel(searchLeft, TOP) END; y := height - (BOTTOM - scrollWidth) + (BOTTOM - scrollWidth - 16) DIV 2; - K.DrawRect(LEFT + 16*fontWidth, TOP + canvas.height + scrollWidth - 1, width - LEFT - 25*fontWidth, BOTTOM - scrollWidth + 1, K.winColor); + K.DrawRect(LEFT + 16*fontWidth, TOP + canvas.height + scrollWidth - 1, width - LEFT - 24*fontWidth, BOTTOM - scrollWidth + 1, K.winColor); K.DrawText866(LEFT + 16*fontWidth, y, K.textColor, text.fileName); - WriteModified(width - 9*fontWidth, y); + WriteModified(width - 8*fontWidth, y); repaint END; K.EndDraw @@ -753,7 +750,7 @@ PROCEDURE Search; BEGIN search := ~search; IF search THEN - LEFT := searchLeft + EditBox_Width + SEARCH_PADDING*3; + LEFT := searchLeft + EditBox_Width + SEARCH_PADDING*2 + 5; IF T.search(text, searchText, cs, whole) THEN END ELSE LEFT := searchLeft; @@ -1245,7 +1242,7 @@ BEGIN winHeight := MAX(winHeight, minWinHeight); cliWidth := winWidth; cliHeight := winHeight; - LEFT := 10; + LEFT := searchLeft; canvas := G.CreateCanvas(winWidth - (LEFT + RIGHT + 10), winHeight - (TOP + BOTTOM + 4) - K.SkinHeight()); font1 := G.CreateFont(1, "", {}); font2 := G.CreateFont(2, "", {}); diff --git a/programs/develop/cedit/SRC/Icons.ob07 b/programs/develop/cedit/SRC/Icons.ob07 new file mode 100644 index 0000000000..5fd2f5b3d6 --- /dev/null +++ b/programs/develop/cedit/SRC/Icons.ob07 @@ -0,0 +1,127 @@ +(* + Copyright 2021 Anton Krotov + + This file is part of CEdit. + + CEdit is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + CEdit is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CEdit. If not, see . +*) + +MODULE Icons; + +IMPORT + LibImg, K := KolibriOS, SYSTEM; + +CONST + fileName = "/rd/1/Icons16.png"; + SIZE* = 18; + +VAR + source: INTEGER; + + +PROCEDURE copy (src, dst: INTEGER); +VAR + src_sizeX, src_sizeY, dst_sizeX, dst_sizeY, + src_data, dst_data: INTEGER; +BEGIN + LibImg.GetInf(src, src_sizeX, src_sizeY, src_data); + LibImg.GetInf(dst, dst_sizeX, dst_sizeY, dst_data); + ASSERT(src_sizeX = dst_sizeX); + ASSERT(src_sizeY = dst_sizeY); + SYSTEM.MOVE(src_data, dst_data, src_sizeX*src_sizeY*3) +END copy; + + +PROCEDURE load (): INTEGER; +VAR + y: INTEGER; +BEGIN + RETURN LibImg.LoadFromFile(fileName, SIZE, y) +END load; + + +PROCEDURE draw* (icons, n, x, y: INTEGER); +VAR + sizeX, sizeY, data: INTEGER; +BEGIN + LibImg.GetInf(icons, sizeX, sizeY, data); + K.DrawImage(data + SIZE*SIZE*3*n, SIZE, SIZE, x, y) +END draw; + + +PROCEDURE gray (icons: INTEGER); +VAR + sizeX, sizeY, data, x, y: INTEGER; + b, g, r, gr: BYTE; +BEGIN + LibImg.GetInf(icons, sizeX, sizeY, data); + FOR y := 0 TO sizeY - 1 DO + FOR x := 0 TO sizeX - 1 DO + SYSTEM.GET8(data, b); + SYSTEM.GET8(data + 1, g); + SYSTEM.GET8(data + 2, r); + gr := (r + g + b) DIV 3; + SYSTEM.PUT8(data, gr); + SYSTEM.PUT8(data + 1, gr); + SYSTEM.PUT8(data + 2, gr); + INC(data, 3); + END + END +END gray; + + +PROCEDURE iconsBackColor (icons: INTEGER); +VAR + sizeX, sizeY, data, x, y: INTEGER; + b, g, r: BYTE; +BEGIN + LibImg.GetInf(icons, sizeX, sizeY, data); + FOR y := 0 TO sizeY - 1 DO + FOR x := 0 TO sizeX - 1 DO + SYSTEM.GET8(data, b); + SYSTEM.GET8(data + 1, g); + SYSTEM.GET8(data + 2, r); + IF b + g + r = 765 THEN + b := K.toolbarColor MOD 256; + g := K.toolbarColor DIV 256 MOD 256; + r := K.toolbarColor DIV 65536 MOD 256 + END; + SYSTEM.PUT8(data, b); + SYSTEM.PUT8(data + 1, g); + SYSTEM.PUT8(data + 2, r); + INC(data, 3); + END + END +END iconsBackColor; + + +PROCEDURE get* (VAR icons, grayIcons: INTEGER); +BEGIN + IF source = 0 THEN + source := load(); + icons := load(); + grayIcons := load() + ELSE + copy(source, icons); + copy(source, grayIcons) + END; + gray(grayIcons); + iconsBackColor(icons); + iconsBackColor(grayIcons) +END get; + + +BEGIN + source := 0 +END Icons. \ No newline at end of file diff --git a/programs/develop/oberon07/Compiler b/programs/develop/oberon07/Compiler index b3bd70e60a8e1dc8025577757a02bd3795d68f8a..a36067d15dbebd73a52b2f7239f7628a6007c533 100644 GIT binary patch literal 302008 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

D_g(IG4t9?^|qA}WETUvUd8 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%0Ay9wAQ_)Iwq&W03hj5EW_kCkT#4wb6o`q%XP} z>=D9lqxQ6opb7f`brobPckq~3%I~&PYD!(%>ZL%|gDe+hkE=fjN~t6N($d8H13@e0 zsjmyNZvF*9O(yF(aR?c2>$bb>cTYZJCby64cEfH!Gk~ZT)8baakrr18!>n+sAk#sg z5vPmf#778|kZ~H)(n|e*oV^L0m*f8bKQqmz(&C;{Nu{QeiZ+xAqe4s+gA>WgcET8R zDh**YWeRDgPu62SvS-Uq))rCrL6IzFziz|Pv5s~A&)569@6S?kzQ6xG9&>-L`+D#1 zYrpPmnJCLfDAYt+4i>y|>Gpyb8(hBYs?fks2yL&BC2UKDaz)cfA-;#)bdaA$KP8CI<^jq|*T$D1m=tOoK@1X-0>Nl108 z=3fZ{yCZ_lOWZ&RyYh&<%STRFQJ52+bcoe7U!AE5->z=X%m42azGbu}BkN1bhL;`X z7O&*{ndv>YUe^ZXmrbvGn5(u6aXVj78wL$RwmXWMG@Eg5nxh$G82E4P7wDLa0#=31 zY-nIxRaFiyo-F_T(0{lqFgq2nOc`YWG+7TuseaA@+WIFnB1SM8&+AEv#hXq?(({h zK6{>w3bHo^1aG;-r&q}!kuQ^6nQNtVpO|2EabhMCvkDt@k%(AfD}$-%0dcg?I-IV> z-F+uio@L*b8{wf@-iF+Y&nvqqvVceq?$(FTLn}w~z5g<0817508&70Dmv6T$%X1ZR z*c-)X0!;7#ss<7-S4WH#YR8#- z$l??4Kif=eX!(}OmWn~I@#d}(WL4r>!iuNHSt=yfKY2V3oJ!nB4BzfFDa_kVg0C{{ zj1Rh7h#UrX4CjlE>{q(+0dqJtbyM_?Q&r!07Okf&=}KkL>b6&k?N>RD@nWOW9CbE;agPyLQjgu4SvPQ!%F(-HbyL`&w<)i#%w8sznqCde zY_eeQh|*Dom_C1%R_%%Dr55?6{Bdp^8O%|0WPo`BoDc)b@3Y87VsS_+^0K-c(gu!{ zRx=Pr{i<~>=IKMh^@(8M(*ehx4lh%aGB5GLlW{r~i^D#k#MA{TY6JDnpiZUJfe`7X z#M?LV1rr#|{ziVSAwB}E^Z-)gV2SyNIZxBXa)?E(AS!lwFz5cw=x3+s4-x&%S@afl zAyHgyx*QauLrn+rY;>Jka?pfk2 zYCEEQi_E8g<$ryBk22)pqWM-6qZw(j;`ul&47>qwDlP6)T5yrKmhuI2?zIY;Jo&~( z)zzbBeW_Z3J6!#h2ruIr_tgM;AF4LzvLb(8V*4lJR6JI)&xU!NiU+6U8tBvvxsk@f z>|d5kKHMfJlY4f}5uek1#8MOwD6VO&06>;=CP6x~>FMSZTd1 zuf(;a#d^Czgna*=Fq{wupR5MFnG5Ed~H1NrQQzege zPAW(1a8rS*hjg!#=CHiL_XGy1tkeEKn$`XTW?}R-1iG$fWoo##_z_yz zJNsr0k?_qI52>>=wjdfmKP7?hGAA01h3QD{PU^_Cr`4-f4~1oGaHs4X29lU!*)eYOS77`xl&G6MIFwX#PQj< zy=BsK@le>tWf~<}@3vRPQI(x-w@p~iT;)-Ks6%q3ii0Xg8mMbUpUN8ma4Ai-z zTV-MKZZFpLAi76I+sf@Mx(mJZd!WF7s(!zdAJ;Pt8jtzBtz~LR3hE|6np@GPat{)$ zG^db6UqHSH*FdYLvU)jzAgNBAA<%-je+uDYAuwq3_kRS*Yhw)B0XIe%%ufrWQN@iB zbIow=0fe228rYRpmKsY%YxX+DKM>AQ;3O*EuI%epC=)UsWISD}7R-HvEru*nAKOd4 zYsqh&7Qr@-7QvRP<#Nv{x>;#Lt?S#&g=SSh?$i|P_Ea*? z?q`rfl+&DU78l%Dh+NK!wMt)3Eh#Qqi1k7B-FhZ(R+~`CbMn2auRD*}`NaPDA-+1b0FCx*~sOV8yPL9D)?# zoSepK3{D2CM@7=Cl*OYt;r&dF(#ZM${rjBoa^+lA@WQC@JPD&FBN*T(&4iD38qRpjHoai>do+*iV|*? zmJg}T@~a)m5iD-)bz@1IuPvIio9WM7_)BumwEblZ^(VGoHes#b=nZV!tf z*{6r$xU&UrY+!ZzD&FOyB|z5Gauex0DRtMC>L?`l5l(X})Um2bv|8NU+~GHh&5>FU zFhLwX)f?if`r|o0s)^*>1cbiCO7+5S^03^XdJgP@YXSH00xvaztbvZa`Mgwphk6hj&kL%bBNQZ`;famc z)9DGH60GP_^K>T)WRSd71Ere8#(Ogzc8eTV83I|A=!Oja$raZqN`o@0zZql7@})`+ zNknlQP72&i&^4kgko2|M{ay+_Q*;gV#`uPr>(-Dpz?})MK8$E5bFR}If*t#={``z~ z#-D)Z_Ou*@Lh9VW#a*ZI>1y5o42IqPu6n0vB1D4%~EcTk=XyVGE2iy)9w; zWDvyb|J`S@Kan#$C#S@n?hBP>QR?e5 zLk##_4BWyH1K$>dWyp!XRJ113$t36AMnPG!&RW~F*bgN3v<%XeNv$(Xx(3zVV0E^X z?B1>ecs09T7i(|VWbneC^zn*|9PUs% zEt_)r^n{M0eVuo=jv&q*tS%c&>1i0%o+GQ32NVSUD(}Bl~v}17KFKOgr};vMHW}zO>y7ybibmy@z5g9$dM{f;fFwri(WAN)r2b- zyVr&5Q*;4_M-qQVReVsW&e&Z>^r8`6L6|y}ZiTx#O?b2s<_srxnJ4^$epEPFgxmoV zRIfDG-7ZgQ62rX$UvtVj_h?$^Y-q#1J<)`qx~IwNs&^y$SDI*MTHs+KYAmFp=S{@} zI!VQLN~Z6i@X2H;RZHa;d1D8tA_WGf6=)=0Pj(fr)$ppgH%Rs(McqBwe6)x&;`0W? z5udLQ>|dAp!`ez;x>^0W zNHJfL&~^OSd?ltOFa^93JM3nnb*_{OB>bVXnf7Bv&meg!&4s#VPsBCLWKTXE@>a5D zwMXV8ryIzjl>@xsUI>=$7m5rKzMl6fv>p!bTy;OIJuL@PO(zs2r}9*7vdKO6QIubD z)8cL+NVW2!`s_z|N=_!**C?y#m`UDwQfZKYMfZ^`L3I}c@1Pj@K}RU*lso)9hrteh zc3O_&zU0NOG#-45?{3+Z#?H^*AJ>RRsrEx}Q9YR9Tb%X}FYd=)>OCnLdk^ojtB3+w`%`v@LzM@p?IN3FFUt<^3FA*`Z))MTl?1FC2CWJ11I_|B4n8w1|5Co@%)8$M758Lpm;zcoAR zs+=X@3V`}JSH92|gCW$n#m894MvCRayDrVd-N&pKW29Bp!+7GM=x&eQc;iI%0`%o>k7rsaQ$0(z47-W2s-BCr zlT8(=CCkb$ry@Q~cp&%m4Pta2B-fL3d>%PbdE+%6;YYOoFyIpFSFIngO7E7BiU3RJ zguv}3oyK@7?ya8uJ9}lH_4?cwQS25`uozGjO-0esQ*b|W)^!7vhI1mSU#%ab%C#2> z5q_xwPjn^n84RRo8)?41paUY3)e%Xq`$4umE)vdi394I@_k-kMjY4nnk;ih~2qCT; z;ThH_GP(`o9E+Z!m~>Ux2np^mJq|Wmi%{zZQj83-&OM<3ImHTfs+(B%KG`Sg`A#8Y zhrLY5HC7okZX?+(Vj=EAT;#qnKZ*4SarE`i3fOGPe0~P=He&uVC-!42_eMNUi0kI` zp4NYVW9@r(Zm_tQ=BUuFBdDy>*sZ{>aE_>=`y+0nP;g+i<*ZMZrVzaM_W#1ndcxNc_ELa|YB^uf+0K@gizHmP;iW>p?nW$cRHz)o(#rUL{ z@qG%E4xfqfhl<13>fPpe4&1&v3QdCK=i8%fQ$!zLaYv=bFN@eMuXbaSF;sqOB|a%{ z5|E~cr!+lbeOlAcL3MMWbTcLF3YddiSy97igwBb1g?j_05YH5iplN}>TX$0e7s7E1 zf$@?4CGH!1k87~2#Fa~68wm^~u$vdisfgQ}h^9R4w5x9`&JB_QMO3Y>&7a8i^CCeq z=-ZS*NzdP0-xmJiD~$ia;1IqgHWTm=Pw}ayuCXNCUwpi$KP4Dm?+G?l99_A}#B3#cO>k&JrIle6n{ZC4f#uGWk;~1>*Mpx$ENQ;%Q=2H0W+{Nl%?j{*i4F3+3!BNu;muOfjBK#|bpI6q( z9WDG^;rr_b?gl@oPG2_wO>sn{+z8EfuDfVn&E3l<8n`mOIOcjrG5%$ybx;bB#@B;;fI> zdhSmHFdZw!y|=iZCSFzbrv}wyjrU=mcU%}h0ujEHy}0kRiBdfs=ezAizKbU>4XQ)N zIh7N=ahG~38FceImQJGD532Cz?Mxn5wd?BcAh|*B>9ROw3wax%Y$|zo0t%n>JLyaq})Sn>|`cK1Yl(Ky)C$jmx|B#}4`^s#dGT7qG<=QNrAzj2zH;^gSoMnnx{4oZ>~ zUnruZJ<*hk=eZHXdkYso?g z@OL$w(apn)8GzDF$)O5ilH^%_gX#@5a6xiM#+Dg5;&?AOBL^-(@{cHC4T7<=OXC)5 zNxpsBTBwEY>eGgAMpiCzx1y?>C@s!0EtZQ#OmFY7=jW=(FoW?EW&+W#3E*=H1^VhjYXQO9;YryP2#{Sv!=lx;G7yiCOHk# z@Fc{6r=rb15q`q`A+gIn{@9@UKFeiy^7Jx> zrD--2^fF%Z{)$Fv6|&>3T7Z)WlqKAKVmR3|oXBnPf1vQ8=4Z=y?kl>UIL94kJ-0<_ z7no0~0uxEy zWoZ&!1*Sao4sjVvOGd1Y^U#g*{dcdS)gKz!L{|}Zpwq;y*uOIT-rZj_7*wwT9wcAm zsfB6RnfA*p?n%XQwbu2-v4HJ0s+Tv=On#_?rA4=_ETp>0bGOmstQ+O&D+X5%BC?T7 zDso_SpJBJk=0xVZ^Ay>|YgEzFA`|XpMK&wFSz3=pYu5-t;r=KP-&ok!RC)P^z$<)LY;ZU#K$Zt^H_FI{(IG+%by1<5=0ZW($< zz$PhuP_bPwdyU(05A!fg{@3Y(*=vyFFPOc?E|^^r1GO090W=d6A?23mv4A5Y(7og9 z+(R31+}|xu^{=8z=t_|k{v*PS?h)()zU6Y~CFpij?7C99#?2;?>vp6X>0}tpHjxZnhm|T9nf?2R2*@!3N<>|_1 zrJ)jc_REn=ux7@g%3o_Z{YI{c71qtzwCW$hHPUpUG+nRUFHNT+NpzRKZkp!0F_JHJ z!@*uYS7Pt?htjMQb))BYg>WWDlqFEg87tHossn<-xlSVs_kh@JqV2$7?!bQET9LPT zlJq~vnD5i)D@#zbTu_r$vwZPfT(jiU@`cyF1h3mXuYl`jjn}1mPr0Ot@TP!gQA%Jo zjmi2?5Fr(3qhj4zGWWi_Z02r8Pmi#|BN!c*Nx3zzSaY^X?LXzGZWtC7qp(O%pt3L% zyT^*JtjMw~9XUcF1ZZlGu`nKP(X9mEyvJjp1vpvmtJiH3fU(60knT(rc{XB+wq zp*ON|h@s6E+F3%=IdIj-8`3dC%6AnJ&nv|}q6due&GpoDeW{*C zOI0n57%75$_qOk|xWDN&k7ISWm$1f0`k;|+vTsdaroP~uAORY)q!**StHR6q#h2RX zO(u3*4LsKku&&}dHyJ7JS_sv{3c)tJ?gbiNFUD2%O@ivqfVsEt7oZ8ZFBJR?j?{Zp zG#aW-hlcp!0_VFE46F&(YFT`kcttmN4mGv+NU437SH&-7dzO@D0HIQGyh>v`BfQe= z%`w7X$XLEaO^$5%UVWWwaFe>vT1S%SwnwNk`ADlkYF*t6@Onvt;5JBUhUziy@;SX;nNYRj^9zD`$g#x zX~#D|qf=k-by6dmd6*p04L7>XVW7&w5kRRrHhNvlTVNb{Mu}agCInVJ2-+q)?M$J%KRgZ z=_WVPGo1=k_lY@{2ac7y@J$j4v2WVqWZRQUyd+ywi=TccJ;SAps>s{i@pF%j6L06~ z7Dv30E?3N>Zj91q4Vn<^_S5j?bkM>XVo)^OEYit4ES~xmdvo0!F|mHjGPaS8e4vbd z&0MPJ4!b4(j&lo{F6_5b93OCJM}|$}m!j9!?IwQ}diBbK>gEh!gJj5)T-_Vql(iPF zh3tP!m_ITo#E^5?6?q!cn}8wRyNI1IKbFST!hFSJp3VFpA-*E(-7-cmar>EvC_jr# zJ(_NXn@Oaxxn68WijCIKA#ghLpT_2No(P^V%v=sOpCZhT!aP=(MHiZjTAPbrrj7R^ z9|g-N^0}m_#z2k>A}{`pb&XFeqBN(L1eri)biaWb2F9z(coKRX3eYesg_-Ma zF@erKsj?!93q;XV6sLNMvnu{w`2v{JBg_RJvxz%Wn7{J~wa=}%Xr@`zlW=8QbSMTN zj@!6hh0?)LW*JI8;UM`3VbHpIv}P_}Xx|ZuJ={96L8!@hdD?vKR~1u&dWGA3T>z-Wdq6BZb3?UX?owJ132O zuVLTsv6rDviLjfMo<~jyn=Ut^>omG4TBt(Yc$e0}yT}L{DiS7*U#-JX`^h z{}NwXnASNYK_q$2$ph;$2yROL!C&+dBxlrkEyYZ8n=?8FNjp#wj0ejIYxE}iEWB$x2kFzAJuICY^k$)#kysqEs* z+F8obD8(F)_Y~W(W1U`{X*!Mnzv}d?MkftpHq||blstDvT1rc#kX$TWV=CD_!<*Z4 z5y)}AW*IqC@O~NjszeWzjW(w5OfcGbj-z_9%0OEq>!Yw%cW)wGA8*uVzpi%6D8V`3 zfa0YHk6|_51x<=qEt@G*i*gt{%+RX>5zkFN+ORCTDCdM2i-1Y1NpxGop80vUQ)*Pz zm&5tb_bWhNfiVXJ{?_0I>}n@TPp|aFYt=|c(U5<&wsrkmxukJxXe#X>{Ug9~%X>52 zX&CA1){`0zWW)Ab%=Pss(WlbZ@jC9BjW&~?qFi~_(`4z~+84kV^-Ex$1b;H=5$M1Q zTa?~NK{}UfLy-N#3_FW}h*BT%!3A^IEX!}0SL;0LE8Z&hL1&zkcT`$5S>C8UNmvM+Y_6KV7d5IYpkPoYt<)fRX zrMtk&q_u79nWmL_z}v(3@39Z0>{$qlyq{6B@8298>yjQ9Dw*@6InTgw$;l&a+ zM(|yL=T&sbhA%RBU%{J|nz%zvoLP&33#36$MfsN7{PYuDH*c(g+W?OJ6u$L`xqq3t zKBI)HSp59D<-R_l|nIc<1I+Rg)_{->@JmiMa&Y@Drh9-F5gvnObPnoW2vsf<>IQme6zU7sHf4qJrugp z#qHWbRp%1wLy~LMxpt*9wU6umGOgm(2={ z0E??~4uE2DSDon8*X?~9X;hPV#a_2@JKg%56mawSCHh&5PPmp9y~$1U(f3+(zWY&Q z$$9WSec41z*u*|EW^11}n;)gZ!J>=KQ)hc0PdDA@*g|8kb4o4UR87q|8)5UiOQmhx zLUBzcORgt9&wzoe0>}u#r(!D)JJVnZcdEh2J4)gx-J?2J6P=$J-^2li-N=oAm`g~_ z&X1|@B)W&8Fmpb@&Gpz%8zkYH^QuN|s*k?gqVwJNH;Z1Qmz>B6+JTJ|UX~NyeZ)Iq z*12-RU{89Mkv4M6^{P#Mg&axUk7CRr+ufu_H`jUQ|NAjpI#{Bh#9h&jM6XGFeIC_+ z`VbrK;@f?DgS;h3RZf1qWlx}Y@t5{dYLv*`6^?eEEq#8oAC&{o;j32}7pN)FggD{GAM5CI=>5`3ex)kAavUWzJ zN^UmvML3W-b>z}Hf~0p?Ykyt=BSqbX8O!i-EnJup=jE2Qb89Rz-kUFF7;NhpuULA7 z+0os-W#o?Tsx2e8=i;_BxfkBtondi)Koha-;Ev8fj3PTZeWln;_%^QZmXS?e`z<4z zxJFw>?(EnUzd6sH+`C&wc5}LNAw#;n%n~vN#3f~ix;wWDq)ry_(rlnSS>SXZLk2rV z2JVE6NXttrR_Cf_)u94i8H9a9%M;d7DE%OeH5vV&Ko#x9%`0J8^N$Q88Bs7{?MD=x zYYr=wSnJ9BDn^&XDBhUbP)Wf|gQ@^U?S4J%HP#Pi&+2LYqiEo-RxmsaJUT;#w8fhu zJbD&67#?!_`Ds7ic}x zab05IVQzqc_XrqmTAjuiE=Yc2R*SxkYblgV3}rsiLG|{m>CV?Pf>zM!B zsNVapJSbWH&!Nu1Uw%7bYw0}!NVt#Jg>9mD5Emr7@vb?YUZh0W#RNTWg0>;d=fBPf z@?Wr~6<8ojsVAh^H$9~L2ZsMHVQwntSyvb@(_X-mob)p7R~R4$$%%ZN4j(hZhm24w zD1u}&mSswhaVS~h&XP8l35kOMSbR^m2$K3o^&G_tU>tzOZrMtYH ze89|ZStHH7eyTUwAk`J|I}za?MtYx-_J=4)4$}f6;px*{w0R%^RV35-bqjx?GujL1 zzFF>_o4I+Qzg+yw&q8-@M@e{NC)1xzx8F7ve{B^O@EL${{^$$KaFIu3H}RE(xT&2d z@NGG4*drKQFnJ*GojpGiw+_v|JS(g9x`+D7m+oRIsk;)Kj`?zd zIMgKepO%@|4;9W7aNunlWVc~*Jl}mN{*ByoCWcXRu6q!iu#Z%;UCxhmkgC6tNi~KB zewpCfL%?jpP5ZolOc+tbz;j}bgBJRX9 z9!DC$Or^J{ZRK-CBDlsAu+d6Y5o-mte$$xF1Z-K<&ZtvnF6-{J;?d=c@OTkM`>WdI ziF7K()RXF;kexL~(8RQ9H1_vrlDRdU$ z5E1Sn!ug(XhoJgAlQ=C~;^jtY5|tHP!;d_E;Sr7%qHS0Ws;h8cko;G?CfLi=uIotI zrReQ+UxQmJ(hgo`QBeH}iOILiTxyi%Kvbjn)N+rRsl2UoI(#ksyinp6S(YD67%HCT ztwd1GNPy~V?vC&|H{#=Krh`$!(j=~#{$W}f-?aq8`QlquzYq2s*J(W6pe!DZH|NnM z&Ev9k@FKArCU!+H=CEpKa*(`{?J&;$kY(5hX$ox^3|kt-Dky^L1da%jH(-p@T@L9A zwn_?RRn<*OD!TUtJA?Z35I7I!xv1g z6O7?_G3=OaOhMY12SqhpR8{qCrLD3Gc?0xzT|?TGCE}22${R#PN}MSkzo|itHj(aU zEzUF$+|A!-I%MkRT;`>@{GJYW62p7Mko~U}Gb$P6X*tOC@QOtK0&+OlW3bt^oKTSb zr``>7N*ePiVIJ=>kE^H+lJ`&`ECcQzR3B-bhQTR1-FqELm?XNMo{n8R+Yt(qEqNL( zn|sc)C064h2y;9d8!h*+tk4A!UJ>_Q+zV;s#uE0Pyor@1Rlvq&_$uOXb`Y1&pC$kJJl5Bmv*syfxR1vNax zW3{VTLkmyK>lqGCW9190hsR=TWh+8KvU!SM%QWVCg1)cS$W8kes&D*;G8TiqM<__H z)w>z_4&bO}-@y*<37_-0EHTrW5kc}}GGB&;tBgQZSy_9xJuhx|NvQEuEXO+6B%I|X z#D2LfP1V_b^k1lc;}IV1shU@;43ZyVF7AQ?Ixu>V(o+*CaviTiodaFSxD|9byO69lp!d=gM zILPzs98{lfh1fRCrSsd+ln!OX?T93Io2VM-B4B+N&RC(=50cBW)38yRYCm@*1a6Y3 zUi4IjLG`27#kgPZX<4s=YDGA3LEGFWA&jN>1BQ4N8^5uTb06OHP;YveAwd- ztLPCVtpT-CbW;k?-3&+9SE!eGRQ7*PGq#iTZs?O!=q&R3=xYdm;}IV13D``tzY!F9 zg1FW=)~Kwm>F4ed)eEBP>Z#a6^KwGzd#}&k)T!GTfz<>3-Fd?O!S6F;`^-nS&+I+D zr}OmB;6(XtcQ;BBCW>mQrz#^)M>UKN4U1A_4_7Fh>pcz|WiB?(v$8qgWCW)B0Qb#T zaMqO!;mMxrjEaSo$7Sd-1(<4Vu0C-qK#p|k=N=VhEstSjhKvp#4*5(F*m~Xs5GEaXHwLy#w9zpu3Ht z+1qHYCvAi39)yEr7saI0t|(16#MOvyk?0y3-3>-}3r%K_{8bBZ({zb6-Cl02=q8Kq zW!rrAgwZ`q1<7a-O*80T1uN2XPq(A!hKTM8qr1`QF0dZ_IXn%PZaK=f=S(L{uQ+d4 z8aJ!@2fEjRdDd=&7;BStxR){hH;gN8syxWqkwvMd2!_{XGwhdUIK<6JGn_Am^TjY^ z$mo~7bG(+#alFdYU|E`u$Y#9Oc$ubqxgKf8gTz={bi)P4_(^lYdB%8}7~A&UOpRTb z<${Vd<2~Igz#I_YGW76j)Ppa@S7O^%^sic z{~Us#4P{32wS?QONklW$jT6mV!my?L>V@2$stKRj9Di@uOZc}M{!=ES2|5SK-ada( z|IFQ-X0RQR6#mm_9x%NRyt%1GyJy=zc=9^*U;y$}F7Wa+B z>4+_#(?IQ&jT)vj+a%PtKy^o;o}H`|E>goAZRNV$x?|Nm!^;$HTe-Asudic1M%F z`HfJb4^iya(rj!iS1DfCiPsOzf1w+@wmu?MImlefgXGgTZr|qY?+z8UpAwm*R6R}% zjuC@LJOegoEhNOz5qh_bbpv24P|PSt*LpFV?4Yq2@gvtjG~LB>Y2c%IEz ziE1WZR#m8;akFA$Yu(R4BF*k5)~yuFr98q8p5({7F;N+kcS}o_6C=svCHY{XkCfzvG^+4qe|)tyuNU#O z)rf~P3?*Fou?gUTo39qxE?&xN%4|dVYD?=#vBS$*%~h+&laN=}JbEcJ;lg(x5VZZ# zZuO^xp5qaA_8M?FKr_=IKh~g<&Z#QO=@}Zdkp_z(!_HWPE-;NWn32*z$E&3@aJ-M=qZ+^{V^D4IzD45}|893*G*)N1*Eo-Pa$d3)@G8y*eUJd1AO*4It%-{oE70x-~q){t|D; zdUQ15ZS|h+(d;2TSBYynf&WFEeIX(Z%f`4ff!YXQwfnC;bb;8eQ@vkwuUW8yFo%sQ z#tO%?Ah@$UPqL>K%l+XQIctpT7;~(3H;Ln};&_p9Tx=XC8^C-@Fsg`U9k7(^>xL!NrY}q_Vx)J7N9-d0mr0K6*6C_tzg|Nw$LRsP#;(-juOGTfO zBFRWeZNbe*$!~ad%|H%MHlZ~p;4l+9N-^g0LqKpjVwvhRx&G#IC4jpJ=eXy^X&H~O zqj9>`I3|}_bT8A}oB83FLhxp#cPoSZ{2{h3!#>b=465%nOYhLT`D_vD_#!>Rbs!vG zB~Wx8QKccDn?gQ6g-rPu-%>+<+Wd8dA&>URap@?7!dF0L`?x0|acf04!04Vex(4+-kE{OxZMGAYHqk+KR#5$#4Xr|YSFSA(@*ZhO z{kzT$#Sk;e=ZoVqIW2~hC0wn0mU#Cp@8J%fDO(p3rb+{!LA+0LjaFP)hBQ^UUkg@M ze+D0c85HsSQpgGR%;ZXs z2i}L`EpIV99hVx#6P`lbxTVDsPtnA^jymBTLXLLzY2_kQLTJP{;5D$qpR52CKAWX@ z7x}q*&0{WUfyhr4c~w0}UreI^7bM3>R-XHpi1XN3b2><_gS09#K@Xd`Jx!2S#)Esh z$8GF}3HLwmf!oS(A2i%wZARz^o<0}-1On~Dh@-LwAbZSb4cpZMrL*56GkBfb69Mix zV5$Xs>*a8J+2rn%XeG!>P{ZpbqpF_$OVfX+con1D>mXuBzPl9!cLZ-?xyL$3v-)}P zg!(RH=iG7Ll6+S#?45*tkjG~K(jJ63I$ZBo@$?6b9p{eCvg7m`MC0Y{V5K5-9$4;{ z^^q1kitj7Dh2QW!7hT!V^qzg$UCR?qx`595`GosUW{NI+UYOCIuQ`1736e*9-0y&L zYQAe)R)|Kf#GQ0Typ&}y7~!IKeS%*CPik>DQ@k57+o!}0CmGw@Es4ev4w6SG#!UO0 z^v!XX^CKG`vtQ?iiGj{TIZDbUhz)xgmpkB6@lcQ)sN$0A#z**p$8YU+7XDh)3G1oR zi;M0NeywbjL-7fsqhJUwd`4C~I7I`A$$H=&QM3V>23eijv z&6P&;y3uIE97jhe#w`c_dur%tXPf-@ z9VP9uA>RfCpnlc#+n`ncPVTN!Ei9a}PJM}gOP#wtr;&VmF-{A3;?MP9;FET4F^aee zyoED8=7HR?)B%ho9%FlFM`P_RjN?4UK|%Gw#*1}};x*r6ws$9qS1Vx-^q7ZKbmH2G zJa>l2*uf1K#y4ml>Qp~0JUFQS!zz_}&uc%A+0nHV=JUeT)(9|1b99DbzUDF8d&~~* zE6jA)3-eizxeGU3_)z~KxzJ;ODQ~G4Q{{Fkao38rQCTP3qwkIv?S-N!y4rGtEkFJZ@+Aci}b{Za?8x)fWfV9SpOL-Yt){ z16-_TVJ826xx^l>@@;5-;k~%%DxN|0r+TIj=ye-GD5bnrk`)b)IUO2}IXGn3;CBoU66L0d|Bu`&xM`P7>!XxKba2J=V zz$t636W0jGgaZku^Y~NL8evOCWo(^0dt6+58Tgkq>4kXVR0LDk-dMtzVxAVvu|e)x zFtf3pF?Z=@o&bIiz_8|UgB6r60~IX@Tk4Xcr0UU z5HXuF7n5rh^{9rIv>9keJO=Wu9(m&T5;#D-v}*hRpM`B7y|MK*VKytpw|B7h$ ztq?8#Uqnkik!Ift+yxN_?$0un>KdV7re3fAv86Fb{x1>NZG~v(zaolUOgiM2?-jcZ zAF{0eyl^LRV@no^)s%{8>xm`gtvdHFSXYKGlC@&i)c607tmVM_#bL9=-k%)(m+5xi zR*2gDFQSnVQP)iWG%KA?MhbHyJ1}6IKhI;0w$9-Saac-MPo987(?93%P-fow$N$PZ zSBNLR*-T@7vy7LPOJ0*dmq*Fo8i!lNK})|Qjhk8R9u?Bzg@2Kd+)}@ljGpaL^)bTx ze@$_35gmh?SuA#lZ10&(dap>QdD7t&`=N*YkDTyER8ltMqd{fZC(Y;QgZ~GgiJ1v= z(_bY_e66_c2GE>Pxbhd7I9C>N3~cYv0|}ug<9(V~%FD zz?Oz-^m1GuHYa!`-xP!9Ft9BRrng0X^)q&HA0+h#En1GYZk;kxtq469jYPCjDZSG^ zx*dKK_x=^{_NLt|rmNy76pS9aE~uG>42Z0a8#VXkF+<;CzlPRFhF2qHbnZI#Dp{B9 z*e$R&3Ttu(R#koF4E08`nHk!s478$U5LPrQZeWk#^6+$}>0Gu3qI7i2qxo?MWfHUb z8_D^;UTNw5=%Y6&`Xh_>Rp`vWDjxdK=^Z}G*km~TDfVi3mfwlxb+Al3+@j8x6kWhs zDu26Ml()C$Y&z{+^Qk@2sXoJ(jQXewa_RE^A?|&|DtJ6frFffCfqPwPN|n+{dFV$8 zP?NE(-WIBMNeYpmMPSap?#V?@_Vr)6m7|5^_K70eXHb1IIHEc}5_gfxJLy;? zeZ03i0SbrwnDUm6q{4u$9}yAEY3t?3Qrmi|!JOZ5vJARien-OTX$hSr;q4#11XwpI zKXfzT6CS9ld&Wrb`CT_dx!R))D3K6V(Y71f-wUm%OCq_ars=v!?s1uN58ezoA}x2@ zNUmCh$TLRYIaBU$vE1y;E_=6$@}3(q8({U*@s<2`LHy6Pr?5#c)EJ{fsq|eM0CBcVeAD4 zyPd^BEli625Rvbg!JZ*zo#iiI7LK_<i%_?^#%<7bx_ie?@4~k@hRUBhu1@meD)= zP@x5e_J63+cQj(FGIpYh*RQ*Gti8?4BtKO*@xv61*rYKbM%wzXxyMJnGvU6LB%xHjB ze%iZxwcI0WRLGS7heoBe32Ex9Yt)rERh&l*^_Ar83(-q^mcJch5#=4hDD-JRL%!J# zfvmZ4XJT#|G*h5@7RA!q4ENX;^_f;HPcCG8?+AtoZi8-BNiI_IZYt~OE{39v6*9ft)W+UPqrfQJ!QI18 zcr71GSDC zC%Xxr+e8l+sH__%OY-rGQEn0?Nw2(v4K@8c~X}^EDzv#PsH)J&8$7_ zf9UtvIkL8cdxk@KNZ1|RKXGa}L6vAmPS{(@YGJob?-wciTah=tvte4fEETuXwPXu6 znE%!gwvDt}t40!1j_j~BSRRp%jYw0i+JE+o>$%63mtSQCjn#8jzgg5`EviY^U;Dv1 zlK9K-NW7JqR4Lm#Qud%o;$e}*!6q^4f~f#Uxp48>Da{{(58wYa{B|djY~f+>6sC2x z3f+Tj;gvD!7)Hf^sg!La&HPY(8xDxu-tD9`FHB?Uyy5UaT5deKuyn52A0(Bvw9phu zwInNr_`Fs;dUh?#)r*T{8E{c1umzhvmdM?ASiiT>9X`-B4CZ_p6;SK{#gR%L$&1X{ zz@#4L1hX}$^m?eD(6~Hu)$kIa^d(kHsR1T;rWO2jYzMQcy?cqes%~1EN6T_eF;I=f zJhUe<{ECIbswN*4_JJTohP@)->i{FGo0$_gC^a&i$iXt4;A1QzC+7Wz>Gu$=bbmf7 zpO)@kan4EN6yJ!i2AzM^ft|)VbJTN-e}(7K5zlXBv^=DbGiiPG(J1Va*0)Kyx{r}D z2F&w7bz4{MkK^&INk%LXU{G5G?c-adbXwc@rMm%jp^{wG}H43ucuC*kzU)< zh;uLts;2t9sX)5(Tj&qhNDZVqokfXsT}g=S=>YPR<-GsOtcAA1dbmzPsK>K5PoXA) zu=Y@sZNC%RxgO11KT`dVe!KZXJOs?Bv;4g<5A&GABZd)^9|Rhh25qYQH%*ZE+{__i zS$z+i$6%O78sl+*d1P0haPI91JQNbWy z-8Z)@<+Q}z1fpBcLnqwTy%%Z=hM@b2&^j#b-JU+I9-59u(!GS!PT~r5W4N{VRO{$*zq?6Vl{U;XNZfN<^u~ z4z8ZgY?c=w?*%#8pszeImBo8xxZ#QmX6qP&vI%fepY9$&I?)_|?|;d&(8(z|fs0<&KM-r=%%X(p+hsz7qF0P{PGj*O5AfZk?7Zk`jC* zDRh%mAkj8!?zqHt&eHTCDR8b=zzvDpx<^QRsgw3uvG8<@0#Ux6D9Us~1ta?s_uSi= zPS9F~uyeL;GjLX@F`5*7LW!rWrmYxhmmea!&soEYs3>1q)LTBvOP{zI{$pF>-|C}O zZI=%8%}YOteVjJ1#Qn_qfo>ZTTu~iWeN#@{8;bpoN2rmRK>v)Dyevz}5-F*r-DxE) zs$Zs(C#ID&V5=?h|6o}TETrVidw3;xmDrz6$-haRi98hbY^-D-#U9F|u9>BQ+jcD( z;dVNcaqdzyQz82-J_*{H4AJW~$JfaE7LiegH zB*#uq`|Tu=zRTiV`5D=F?CzbUu5lq9-Bj23t-*2E_#Yy92$FF!!0IK7xPY;2ElBd2$7a~sti0jOQuB~ z5XmG_w%N@m$_2_pn1o~Rp$xLXlE_Ay5}&XRmmxFC)Q9F+K52AL1W?DoA8nKG_t)o3XWDz z=aYxk2w+OQFeB>RD9X;Joc1v}V$*-&Xtn4?^v>9WPX^JdBSez+GNy6)X=P*MnmN@d zO_v1SW<_N^lbnEZi{FS#Q`~Z$E2M-qB7dv`LYi`|byS;^T8H%asnx=l*&Ai5rkkTWVU{?aDmq`{+C=F4 zXRxU6=UH&mY2pCja>-`%5pBwvLtyD+8!OzeB#pafQ`7}Xb!REm@%J|H3w#cqFC9Ml zP&&+fpbrkPQf#qW;@waif0ct|2n+`J`LHyDTgBiO&tOT4fyG{F45FUR5cdYJY=!2` zqo_R_0+*=Sxm{c)8h#1q=aP;b?I$-)>m0YrL$+v@p9OEiiUHPLS5_TUKv%VH59R-g z6KoqZA7Mt+9Zy7)im)=8_#Rz%C=tyn_O0B%a8P zF33X=UiAfx!WyMJR5+iCl* zjmvVi=4&+dW!)~W39HelLf5%(RDaq+#S_2LQYGQ^B2G&d8@{5Fd2~Bdos&TRL75Da z4Wxl>?Ax}&aXGLi$!ZcsyEf0!I;y_zCwVC<^kum~I!Mn*>jJkk0!&4^>r__r zcd?o#n6tmHeWMEEQziF`^_EFyDw9;zcM9g{bMBUTu_HBY!=U?M}4!c~5R%^0K*o zrulp*kOd{~w14<-D&(zgM+8^0zU|{&vL4?-Eja3pkJZfSbl|&kfOoX&;G%(0O;?!P7MR5B)B)xRJ54e#Fzmt)b?{4Non-bfi zIImM3IH;^QE`0d?t+}wjzEaIglz`!V^pm)E6?gTxA{X}W7rW5F+X9vgPk?2X3!CCw z?m*U^lJiD-7Y^_)-1#JCJ^somhn2Wi*!tI=JG{i*Dfjju|NVu7;q|UmVc-h^ zD=pTn-z+UE)+sGQUAP#h#ox+?NG+A>VJB%>C(WE?@MBNZoYXVIwfE^Kq*JTqmbo)= zp~|2;@e3tIln`4(n`vl2_@wxHXP*=w=+_;vk)-GwSW<9+)#-nz9@6D0oBR08EFUk| z*Y0_V%iux5$typyY?!ymH*-zB-`dM>6W$hT{AtRfbUUs(N4QgG+U^P$9d10dHn?G# zKF5@}Cs&!fsN&-}hYsS^DvOsz{jrwRoLnk(H$(muNLsKVzhTIQu81l+9K5Yr&9Qx- zX+%tmd*j$-G$4;A6ps&4)gk$P>_6I@0&5W7md>lE`@>5 znu~lIZ`SHRs4A06FuQu)PE@{G60pSe7E^ci3mI8zdmz-12OUR-Db+G}cgSbtie{x3 zDg4XlsC$rCm$SsKql5&>>S$1!*_7xer?k57{Sd4Bv(jUWl9acFy4D^QW--yiiPB4? z#WZQLyoEW96OisB#4Zy)d{GXL-pS|6gY@hAsF_K7Qoi37HtLW+4|C-%8(W-A^6)Z^ zl{t2tIvs<$-G%i_Cf3DUVCB}eh#cy+dtTkJLU(tBG(d7S`ah#1CL^eeBGOrFnDXJ= zx0LAyxKC(}eR{4_Vr=1{k6_v`=&bHkHBY~dNx@^Lrc~~W%7sAFNo~G+k7^{H0OMKv zU=yNV2bHzla_-F78fBP8SqP=hWZfEO|18WOwW6SAPA_yx_0RN0D!lDY#n{Zsly1Hg z;U~^U*IYGS*nS04L`&7TmriNNV_i3Accj>jg`IqM|0hb@#3`^8a!nLlx#tXVJ;k`%LX{bJm@Bq2NMgQlIbUrK*cz8f;!>FA z(s|*ZbD0Mh=~TC?w5pg`c@i3@6`CqmYhSl?EG(Wor#+^z6aep6yk6Oo>mL+Bo0r2q zy;b#nx%e%PBpGs;{U#kNf>b2^a;`frog%JRz%|x>p7CKh!X>n3en_OvdEv3(Xu?Dd z+`pp+?%idkF%^r?$Xy#Al@dyGwTdO~f^n+JH4Wh!HjsAMV05E;}GQTd_%=&v+U`* zr$zaUx8G|Lb_XXqM;WhOFy{@@D|UQlTF;lq!&fb>wMONyGT+}k$C-GDN!nUG8)X~D zO{eVWXK0Qz6;uEpVO&DRbsqp$e%deNy}ktovET?@ahb%6e)467hdu!L@v6x%X@GhhNo~_`OrC z?{z|X4U|lM-|rghYv88?jhQzmP7H3kBaVg8#0;a4X;GRK3!jE2(`Av(vO~qfoD4j;1-bmgKr=GW_x7RFeNy zO>yEgmWeFMS!Qna+NU-Vn^?mU7v7h5iQ(;Hn31p#7sie<@a2Hzs83%bT2)V5DPA$O za`5K$$xaoYrK*lpebQ^o`os=|*dMmOq`NN|n^H21P>TvU(O19jN>=HF7oZ=~ItJC> z;Itt5552FNQvj)IvEq3a1S7BV6m-jMMOM{i72^$vD{-SaiCK7YWn{(pHAelu82=`p zZBdL9s+t>2QeDkvQcld4a;{1Foa(0^ zZ|fc=9~U>&D5CCj@0*Qs-4?zHsjwp7gvG`sD-rhN%SlFEI^Gmm_2gFEGipQZp1}-N z!`Uh$RrQ>JKG_n!Oz&GrZz<_DbJj7IqXJ}VEuN?Oi9tu%t|DLxz~C^;O??g>X&NM+ zK3TU@wC$@OzNMe0a!t5Sl5;CcD!Z4_1BFGr7|%;$*Y*(_yyn29ZV;$>6+J+m6rpl} zoCdijlzR*eb?pD8Ke^$DZbX>8UlaH~vE8DEDmZlksbdDi_6Z8^RFc8j@5G5Zn2F*f<+InJJLM$7{c(PYyW#P;*Lxxmsh z^I<1uaFis?O0_mI{QL7{oHFxu#H>r~c&=qW6n~3jYjJd=aWtPfVp$zcge#AczDE5L z_ok3Yoq9W`t;Ai#nA$k{+!!*dlG0obvaKD`)Ku@;F4d8C87_Sv6-(Tx$IJ^e+x)2) z{O2p{o4zv%#bY}%GEn|_Iyt8+JyKBCG{^uKK1#0IlV<`nFZsHcXHE z4_&Pp+ECgap**lJo!mEuoP<%FgnXopj;>XoHQT6f)agu5-8V6#rXiH1eR#Y7i&1%h zV$|P`!6BM8PtutL=8}lJO2{N z8s#}IgJZ*^dKS;~?5*JHz?kq(h#Dqyp%dmSR6%m=_r4fUVg1&gpSo zV2CBA2kNaNKTz$p7KyqW<2q=)(yh!Tky$@1$V%5xBRP_$6L*9V3X+4j%=$fR&SEq&vh^IQ#Vme5004n)yOHPr-|so zKWD0sSK&z!)2A8cl|C%bPZ8hL+}pqGUb949kZtmDnuyifx9X)#R8~%sx*3gNKIUfR z#7?-Cqi{W|YqD8+L&Z!t7r{nj>x>GkH}mUtx@$Xdofzd5blDiw8Wk{lG$g;6TZ6wMDF@9_2G_`nJ@k8I!vKZX~Ro(Vm z!8@Dj<+|3=sfjmrTEf+6Vsl<%XWE;L_A|T|jc_Gb)O<=GD@YDu=3z5e?!6()l}Ey| z#4Wo&%M0aOQ)3}&AoAsw*&=uLBDq+qHK8EcLho6r$6M6#y9!vi;u-0bF+i}`M~H2x zm61ORj^q1_i%RO^b||-%fx&f}28;&=bu)zSI}d)9yK1BopDH&>?!jKJCU-Jo2TCqW zSBAfflXV(G#KW(0&){*Bcr-Tb0j{U8Ta=w)wV)fh*cyjxTV#8t1xY|+a6!Xhz9j_7 zZ#B%y@{C*jK~`cMM;72RG1$ow&s(>v$!q5JeX^OGqEYYTHa~pp8B{MI#B|e^at_Rv zbGXTQ`93e_0Q#`BaIc!2HO;e($dsc+rP#yO5j*3vAi3eEEi%`K?_-Z{j)|IWiiP@} z@zT#@kmy|;w-t}cs}DRSM*cX2a@#eNZcH8*LK1}db5nL*62^-GN)7QO5W@?V!j_P+ zlqHt_X(`*3`-OO^iuDO0^!5nDeeU@GO1l#HsH&^~0t}nzL|Zg&Fe;dU1VcyyA_4&d zK?50C6h*|43?xI6iOCF$f}ju;A%go}amS^KRMcu!P%G4Gr7jh%wyEnKQ#D!_T=V_^ z=iawX5^R4Tt(o`EJ@?#m&pG$pbJr)JgF7v_&M87doD z=P&f>-awcVf<$VCFq8 zD)fiUNkX`quDr6TW(I2%jTYFP{_cBBgT0VmK>=ey9q{X@K${F5q15kz~-{su70}Imj1|Z`{J|M~Sq-=Xo+8>A61w7AY z>6gz2CJtmXJChkWE_}ztf?|Bw3K%^N@eQ~#CkYe_4G48H)!vR--+CV#Qo4Erzb<|Y z@!xn{OxyS&0X-`qt9WfuE09~I=n#v>rWOB)>WQbIhWz_5n!pEyA$J^^#GZsFF+x>0 z?QiSh3y}qAx}A`K=CByEEj~U5dHn-36m5k0B?)8;Qy!-*(Efn7?QS`^U2gUD9#Hr2 zv!BDyHzfDTV=_<2e2f(LV8E5G#>ldQ)EFbRZ;AIP@E~sNHFJa!KPW0oD?b{cuDTby zg!#E_Z9X3wa23F)gJUs{nz|r*NS>|fj`Q@5xIC8Vzr2Ag-j|4;&?o+uv~5}gXJR*_ zV4r=WK(SBmHA+_#X#{A=epP->-vYOYwNmb`vt@q>nSJmBER(Lx+u|&h&5EA+15#i2TOp=r2U=(vP zSKtX>663qJT0D6u98U_H+f#rTi<%AN#n1<5+Vs&y3DxIAE5QvPXi{to2;x0ddBJFM zdV8wL{WV|M^z$8R65PODRfaEk7Y~I3Qb_NB!k?K#g7(LR0(Wq_0vX9{Z~d;FK%@+( z*FAw)ztdP5Al5UnzhMFiR*T&uVC;qEJY8Pz<(CCFoMb!dofd|!o?^$5;QU`Iwvbq( zO|fXEJh+Y0JD4s^6+92k0kiw^GlLrj!X+7QF{j{RVj{`EyS1ab8*?cl#*-RjsVQR| z%sshS)5nYeHYho8*lA%N&BN8H%(YsV>1}49Ya~0J7-j9b!fG;(z@@J|Ale|Ds4H)m$ry1fMZjku zu!8v*2sDx9Dx2jHT#o6#XOnyvqM3d2Ku@q*sW|`GLcy%!ya)7a_U}sW=aJ&uzbnuO z1v-74EcbaY%?jg_@{oqx-@s+VC4^9Lygv%YlARsoR*<;}2yrd4iP3yh;A}{cV0oOf;_%V?s`dNqduDvhteXn{&un>#seeZI|Aa&>nWF^b| z;vuQ*M(WC(*yOP7+n!|H>DQMZ0*d;i+p*hGI8OWFzt)y!&u(wiAIYepYvOeB(^eN& zv$=WGJqv1-v7TioShlN-cpp}%t9t$!4w;dEFD{=9SKbNM)E2;!rbVF&G*TS&YbMva zPGU3V+uKInY%5gTHcrk1NKjSmb@k(6)tA z)Kaoohw-FLY0kizFDhM@R$}lyvVqp4it9*YflEW`{D-GOW0B^LD=qXG-EaL2m!dF_GO=|ZSUPgY{SQC&wk^@}SmH1>4b`M_dH=)S$_J4{ ztpTBEcW@2shBZbp1xRZwq(J&a+ceU@okipqt5JC>2#%U6y zw4zc-+{VNc$vw6c^;Fk+D2*p2IXJ68T!Cn_{9+|?|7b6jNoM&Wq)%|G{9%0Ywf(0_ z_`L_*<{*^z00~wOYNQBCXbF3?j*no`ZBzFMP2CclVGllVXb*e5(dZ>#le`_tjtlKe zp(py;dx`8#0DEm)WEO-*D*};(!IB`+=6#r1p+{WAs=zR0X?hM|pl7nYMq1zAFI6?` zf`?D0NeNa7HWHu)WaWVVgUg9kL> z>v4bZa4y^2b)ztg_j7Wg88lzcZ{hV+yi(}As7~)Y`<9g6-z@vi#(6-yH7KMHN%U36 z{vM8Obks1@6xf6#4rV(#=)MHHVKr12iwZyaG*n^imWtQ}(@i=dzte!)Soi{z1f!%% zgO_iiRGI>3?(NX?4v2Qww=a1_k%r+z@@UZDqC}buA-#6rmC0Ro5#zK83aIrSDOLN~ zJij8kG0!U+!Q>Ip9{|$sH{)@5`vcWW6be0rsE8GP>^qY6GSG*_E;7XY25)Te0AidY z81~H25y3UfVW-hSq~KUgEEpPgD_Ih()WSzlhLW5 zO9%IRm{M4+yB@=9ug4ktO=@j2Si&QBi|jgaBV=_YD2W){h9|E(Eoj_IR>2(bZn*9z z^%t6U{rd+S|AaP3)?!Rxg!?#0Q$Ep3#!Sr&cku1g{|47AX-6Q$l0UjjYNH2pM@FZC ze_afHdBBPAYp?6b0SuzcZEDPcVfcN()t^DUrD7Mw>m(i2+*#$Wq~@y(KPHkq)5D9t zG$%?ILO;?t5@j$16gQeh>>*xkdn9u2wd6C9@wL-}(%jf3xW=5VX9Eh8RCY8Vcdq-% zA4l>p-$`??tb7G3Q!imMuZ7XAlM`225bGXbVb~y%v~w@S-bc_rIwCxjS>lE;_Z_MR z5Kdl>rzp1ywy$X}bBvclBy#QLXyln|q^3i^>ZqpiF&&nlM`~Z)AsRPLTR{H;h;_Y- zEH$J1h)(x%)0V@UGi*Bvr!tX2SfX!ej(2~o!d=$!MR6vnRO+vjvXIn@q`fqDjDBHK9n1iLBqEia=Gu7YYi!Z3I76+j zWLLeTIRKtpaXPNs1wBBk8yLcgY7`36d6moB7+8Kkv)lmfCz5xHe-* zJFtk(Q&(&S*ob3au@{F}tMS@2m2Rp#gY^DjYVe)iOoYYaCMa=W*CTY3u;-Wy`1eA-5GtmfI za6v}85C~V7Y!rXfM;Wv#GhIHsO70uD>CyH77*!G!X>_%4RDz zy6slpK3W9U>`mqNJ_LDCR&0w0M9)#TgNnKZQx+|QY&({%%Q^5VC_0CO#%P%ugEDdX z-8rhBW<#f;Pq*85a&yP?Sl-8ko%-G|T3=aU9xN zSXE|{=@*ehZduY*>MURgPY(^7GON64_ zJN4k@owRXim2EIjZ(nIjb-+#fw))T;k z*-b!qmZq-^qwXp?$M|8P4*PZuMrC+D{f>ZWD2G8bq#ipG`e(P^16c0lTa#7nqa<7A~Ruv zUUY)mi|ZMrjR>ypS2I}94>y22%rqYZvF&rQzCW>F2DZI}T!&;la?&NvIcGj~jrTK8 z0r`{*Vcp`r4XnFd!Q)z?J=!^jr0YpKFb<0drj45AyEETo<7Iu))wAF0vAWr3Oi^a7 zLp*spBOT2_k=#@7l+hG;^_*Tvvx)L649xb$WyltCvz0nbo|HJ1#W_ty>Q!n-*plRT z2nUX)x&vn_UyEWP>siQ?dWc0y9Hljb`q|%j7z$fW-r!$T&qi&FI>2x0fSFvxyRICXdC$bVFP>Hs>IwWA8<^KO*QXN+V@p%$!2PuR)ps^7H z7(qG@86eVwz$Iu0y6{(3Z9)u22akGCb^Q~kQ=?B@s%z$v#nT7F6U*s{1EFprT>~WQ zVAr*}bZL${UiI&fN!|)aW(qho*x1Ooc76TZ;{AL(8F0F>Em}-eNF}5mM>%2j{3W)~ z#ec;QQV;yr=Z9L36`lBvH#`zJ5@nx7NhYt6JrYNw8rUOoIZ1ll)Xp6Tf<^lhACC-n za>@lC!GId5cw=BOQoIQi+qN)zP;YVSgwqxuBf&+hBU&72u48FM-BLEuB;XJ!+>yGP ztef*in|n2zJsv)y6waCoNS@u#?8!4vS1` zJyUyN31|R@&q*$AllBBd+p}>rO%4Xp;=aS^Pd4;wg8Pdinb3@cXpwpwBhnUlhmaa( z$kE7hmBcf{f@lllr%dqfwi3-wT!T@j-qxkel$GlJ_8K48DdPmqkq z(k_6sJeC&IuL-fH>-=e#nzUcCraD|33UTX-(_O-X4>6>UisBXqC|=9A=t$js>?yYb zozre=DqBVBRXH^=@*eTETAbdpk9LzC1$`5>w<=!mR# z{1QU897@$k)tBg3B!twYjdi|kQeS6kk7$*;7=%SeM)g~?lbH})e>0wf8~9aMIr=p+ zxc*(3!OHhMhAKpHhz92y zi|C3+V$#$&4=$^8sK7DDQGrK-R!eqtYG+s(z(U!W_Sr+-&E5dredDp6_@U~3NU3E#D8nO7yn=vztzS!69708k0(Mg3W94yXzN*AdIZgoK4i%SS{a`3=~f0tHjx8t zBEdE9QrQDYNh=_$<jhJyaq(YF9_$W$z;X1%{%vk?#DJZz+K$w+_HkxSTfMzR_-<54A^1_W;*nyuk1*tO}x7^4y8ZiJ|e^bGx!( zCoMQcU9{^szk4`|5`vlzGHis^aT=0XN_~~IOCDvC&tUTWcFAFrJc`LnP4W>A@dXCr zwu4^^FoNg%%nV~7c694RW~ezL*0=yDenhOZ1h)QE=>t!}U)PLx;bXjL@3=K{zSzcE zjESHI3>Vv*_#>RLQCFRZ(Rn(_GX%LSxPhZF6U~a`ZGsUJ{QS~=5G<6*)A1z8uZ@5p z_B8XW7r_m8@tu0Ksa2BNZTq5jEM_&6OEev9IW8AEbMY5C#`5d(O)Ec=N^!$I@2Nks z7)FK>nEr&IBuUJ%_*gW-Y3AKI_m=gpy{=MAPI`co+0JlUKK87lq=C;7nXT4ur`OyHzyx|$1bmdM4)p?DEb* zdC>r9G060lYNZdu5-wq z1zwVWhpcJgKa(*ISl2O|#|LD~iwOCkbOsW}$vWYK>dOs_s@rvtMoF=2&k1(72%_H! zc9d&-U)r;5c{s@U>$8#{!j;~XMuS`(FH8dW+ zFgYuYPQu(C9cA5qN?3i)`gFh?l3qtr@;dNB!DZRZU7W(4M{sW)(2)pKOc?z0HJu3V zjt+BekA>Cs%+djGi}3jh@Fp5FLDhD0g}xxT{sBA%H{6ZCo}j9-G1Y6HrXi_u)v1ep z-itGjj_1OJ_j1v-Z7S#jU|{k^)n0HH7z@*&Oh4$!$LI zoHa1gU6^eF3F)d3UHt{=h^{KpfZDe4Z*+{h1odu9>{hQJ4KY(ae$)`mW~kc)8GUbJ zH=?U^h$eZ|UBt9hF@BiwTKrZr3Q=E64kx<8eA+r}{KcMVeC?!VGK6^y?x_Ic%9Z#Q zY?4oa4OspWZin8v114*=)B!M1?x5be15VeHJE)IaUb=EBFfb8o$sN?kF5f9xIN+5D ziXqE+2esaVDp$Z2${o}@cc8blSed2fBk&BXJ0*LT z`ZJ3nvljw@CejL8U^JJscu@p-+hS|zVc*1>Q_?@Bq*11%d+Fy` z(jjh1;CdI{k~cy@ENPM{=|~bk!MtDZ&?TE1M^^}&L3(>u<>ze zP9Zg7Wh%-*4Y9v@98zuVP(HO$>J60xSEW)hnSza_2IVtD?zVg7S=b3@0aysP%Gd~Mn@;i10ua?_JpcsPa0MOxOQW$P zT++}aRupdAHV%d1tr9=Et zgB9^Bli12a=X-}80!jl2m9xLRehvJ-pZ7`NCixQQ9qiKXGkrsZ%#@p=XBTr`(2RCo ze8nzy3X8q>Ja4fAx(pysvHjW=`^se~b{2|dA@2~I8dF{aeZhvlnxe;Cuu5<6%X%z7 z3Z-z5sR+)fQh&)(#xs(DHZ?k4LBM?iCh?TJuS*(zmSgJ zyagvH+?u7MX5!_U`~|}b$213HVUUV?0D&O+{iEhgUnh5?F^!m=U)^nz-F{=S!D$y~ zU~&bWmz3*vMC8|WzbZ?wqbB;um}OU3t*^qw!!d>tF>46eEos_vv7tl``7G2gp5)zz zwNx*`?*Q8k5iR*YYf;;$5eJjXMz$TAB^BpX@Uxq4-3*oKP_5GUYtYX>Z zEcoNXy3y9N^~_s>Qp~A9eE+XfhWK<@h-8Jl+0JBalMI>lCrR~(KheYdz6DhZu}Uq7 z(^;h~n|a!$Q>A-sgS%g_SWdY|6h%+$1;uATcSqO zE=7$FH8pBkW|VX{#wJdU-msy(Wd=}x?^64iZuV>Hnd&r>?uj8Cs_9}@>hXlPQll4g zP;9rM?up|%62@BQTjk5wP4fL$HiLr?|GhTM>`jyOb)6bcoZDz&uj9hl__Eo2P@!{U zIueUOEoMgDm&FX%g_z&|J~;%cIV{aD)d{vs)Lku#*XDmU<#SFPa$V>7NS8oQ29%qT zw;}>gzUayUEv$QDtV_>pd)JcOfvMyK`a^>zR}OOC%a``YDv|B;ZP94nt|zhQC0mX< zliBd0Ok3alM3|G!%fgM!b-BqkfVuqr{MC&B&1XZrm8~8Q44)eps#p{=kP(1%-uyd? zRuTt;s^cdsD&Qw8*r8(_A6y^CQ*gt{_$w0&Ll_XRgoBe?Ht~&x97!L{^ghUe8x;Te z6|Pi!olL%unvh91CjP621RJxVW1<{D^Y)?qNDaVAHTE_rp>`-HQ?T)4XqHrd(s|-; z!276y_yb;9D6|E(%b-Zida;Y|^m)NGm(X%-{Ob)0*1T;+rs-v-DJBImtCKm7^FSe0 zVNyB?cGKOA4#{|G7ZY3~hudH<|9c>MJDXt4!&ZXdE0S;(QRDYN@OIEJw zmtF|`P9o8%L`U6C*a_^DiS4)0FE2uaGFKk-wW`6pMQ?0?XC*edI97?4nOPrc^G7mAK`%6*#U_Vbl1 zpthK=+^f*c{8E_6Viy`??RTye5?u4V*K~T?P#*ba)BoQ!xrdFk#;eKx5HUlp3lJkw zizjjwaP{`VVO2xD6nf3nX&B5fl|hxGN8q27qDO!R1C+edG_M0R`#Nm18#V5OGoI&j zY6hbSH<)_HsJUI(HsY7UwsZATrW>}sF%J_mj&s_Hx8zRtx|lJ_I)939$9gePVHHZN>26S z;~VHiNC@qe6N4`-M=X{??ki$XHspRoa#eCjuszS;67xuxXZMicjdQ_s3f;ZL{(OR93&^rK;^L{8w&i^?Dxib>fsv z^N`G=au=hl=p5myEpaJ+ujiI$eb|QLsAfN-*3Y2@+sAS3cwH*8%CX{17Q4F^W znaroZ`SSu2KlI6MF!47L-;wPxxVqsS6pQ7h0%T2^uY8*s+#$>m^JTzh^h;?6kTd2a zb6|&hKl+rdsBK5Wy80okdYvWpMfymm6*6`zy56bF@hqyF6g3WuQq5^JQJ*`oPR^3sc!@Gys5oGpsxJq~) zw#$^dNb*RX+*w`jKLe!4LGnH+j3nWo7YboB=nzngfPChA2?#hfNMn1=qHH<*zlaK2 zCsiI7!eghS{9*h+7n+9{0G^s1b&Mq=36!dL@IxZW=P(b$(?WP&Lv~Q@BU18Jqa|2*(zc#8LtTL{#42p(TqKY@+)5j^vEB*;>ij*E&>e)$Wi$W@!^qQp-KG!xLa z-44}|o9SF;vUDbMvTro+B-#tEP8DJ7Q8z3BM@}(|nd2`JDaPbDF}UWHp8>GBKF7sg zM(j;K>{0vx0M37(p2Gk6L``T^mw$mS1eBKv?^XMQ7eohhR1F@YqeGU~Jxey$@wA6BHuQ=o4Gim#uX%6tQ;-gZ0A zvgw)IS;$Qv7z>fz(y);3s2Dy+i=rX2RT4HC3z_nnVpQ%z;XVu#*oSU9A9kbM{kH$>vfZy94#zQ306(rm}IRg5i zoC3ho9Ggm0k(2Y2$L*Y3nDb9Sb8`ylKAltF1=>`UVVAkZ$@wsIZt&$4P@P+*LYYp^ z#ZJzx%sI=KQ$Pi7nQ$y}99m&K1*@!;jc^{jAYnD zhTiy;;ikUI)IK_u)`GmP+F88DlrPJm@zvY2(3wjL-KW!}`l1>ghhOiC6TwhI*OjZ& zePK=@9LL&K(c|bcv3O&DL}zOm`l52cB?N!m7k_u1Aua0huzF-aX`fq?yb_xf_fo&? zZ_3yax1)L%sDfvb>k(}H5yb(g*z-825~$36!`nPB6? zDWv|r%}46b$d^Lu0Yi$B0-{(%Eb72$&M@N^9s?ho51f=qW=a zWoAm%SchV3FGH~z43OfdusqS>E96KIu)&{ap*_ACZj$3U8ize;c>WX=pCfo+&xv5lhcHII;Sm8>s5`Ij;fO2dkH@}si_g#j00 zZUMcfL6XbOgVtr5(iZP{MfaM)HL?R8UxL8#zzi6uiFI-FKJLFHJsrb~OTOZFwrNRn z9gkpOwJ39t8&rnm@N;W0Jmz61`I&7y}(kTmFr|gDJ672pS@7##)=mlS$w~{vy%^3y_ z4K`lL+T5sNcG71uxZjJQ#Pl(;VXS8$&ODceL70V+Qn|h0Sm!DCq;^O5n@&| z?5}6uG!;?hes&@|0!*v8lFB3T59f#|dUC{-uHL-!2WeM>HLr2T=5iOfE07V)^$>Ew zLIDl2H&m@ZqHaw^o9MPS<4>UKTlg^C2;yK|fWzIU4Mi)2Dx=BGVf9Ukxb#iZsyx@0 z>Kic}Bcs^2{v=|TzEIo3$ze(eoX9OfYMfd{-w zD#_l^FkdwOSem1A*4J13kMcRX; zJ$BK2fNfksoc<|AXFEkpavxvO0{ZlHsSu0a?G(LR&6*>&0M8cay4jwJx}HV+ff=-5 zC02cr!H#es$@d~zYPYs%JGk7Aq~MxAL1E?voZdh(I9;y=$@F{Mr_VC!unThwvt%0s zFdRDF6b=nYk1)kyKrpgw281U8^)j>y&zy3?v$#4)vjt9WBquGW`789@{dR>Uc@L89 z3MB`#_3G^LBV0PSkj@>XL(`Cg1+-p3A_SE78)B^hh_`S2{R{}$QSc@v%_p|UWa}J8 zB)JsHuH6VI#}I2?$QFg>)eMiim!Ao1RpU9m;MDYX7LdjQ>@Q2uYE8SngNYx^@|XVQ zeYO}R`L9TJOBc{qfUqu&7M;!yA~|Kd(;p- zrVgrT4=-zbFzjt5y`mKMW;pCga;}d(0sTtYV{7u#`Dv!Vn)~_be1c@RnnLH#0I`}q z)Ljv;&VEO>9@L5IB;dFuJ;J1`Bq^khMv^@s^o-7VC%1YNJ54c$+;k`0=^0oQQ{S-& zbS0`)KeVck^@F0vyorVk0hv7q(Q2pSW=Vk6i zGWX34g6vuFehKVAPFH^^VsGTj`r}>>t-r3IMy2u6EAiXn+5hD7a&pZg|}uXHt3NN1?4X~%H9_}qw6ABY5+ z)sw&hpP+ORDV+m4IPNy9S$B5LWFig4r8tj12rzYn6^xeYUiAy;C4kT>LxpFStW8G& zT%C+lpiP1Qe69y*&GFn`t>H*VE%nTj~=YPJBN91Vcy5NE`xpi>FS@TF@MW--HZkZ!67~E3-#$0c#0#8 zUNNg#IUl~^T`(iQ;dTAcs_((R8?6F!<&K-{&)OV}+N6G(MiPE1Wx}OHSffjXp0Ynp z!x+X9{+dEi#aRh9WE0#RMZ!-Zzt|yXUhJXb=|nE`AsOnxl#W7e}!*?6#RTOGuK?+%pAgLeBCn^RfNrw8%@25>2m#I$&O!=<>ydJmVm zGt|M%)gyX{+C^QX`JawoS70Mq=K5)!mAU8a4$IsDuuJ14(kLd4by&MXyX##kpnQNB zN6bZ_F4y%cY77!Vh{xj$9#LLKYwbvsU%#wHskc5Dl(6~^q;bk&tTZXpcTOZ5JEoEi zyVJ-IHeRG#SBmNm)8%o=2#k2<0`JCX$5!1sy`;oRH`|K78Y2~8KHL`mEj;4d#t>ej z^R>3u$(z?mpG6J~Ym1mqZgB~g12wL`<7 zaaM;$I2z!#Z6f^@>Uh4$N>L_Rlf{^W4Qn@^MAll>T*v~e5zojN(pim=O(%xu3(3d@ zr?@8Mj+oODScytkU78VWECB1g!D%eE&B#6fLp}gBY@jm$MR=304knbh_Yn6Ko&U2B z0pp!lgcWGm9tJS_gCeW6S1bf}o%n)|ez_yTwO0ttRpOs4ex`)e-qrSD|= z3ry#s!f<5;rj*s|x7Y!jB>xV{P^p=87SPq2Vg^q)b5qjOCyQG*h3+EJa|Ok--B+M< zbWtIUoZRc;$abTTtv`{%@jeQ1-FBo_FETmZmyEg!^!v#oYBDv*#}q$XpL_?YKJ^In z1ws)8gQ*rC_0;zRT;GF|MQhKHl~~3?fj=D3ODxM3ILdvUlrI2{XgW}KpNMr5c9&Bz zH5}~;$O|^)L_+$Ij13t?2zKKIw%U+G2tiLAxYLFN2*E9|fg5bdf6z>$2LN(~4fz)# zxXLTA#)iB?2#!Yvme`P|2!ZPl)YuSwYp)GAJ~su*Y{(6S1OS<7LvTMGzk1UYD7GO9 zLNLo37;8hy388ojYzWp(Am_k}YkTv=1SYULS+o(0U5(`Efyn+7R!>B92a#YeK)$pg z79m{$Q8wf=xa}z7^uRkdlF&F_cg7dxc`jW!Jgux(Ln0t_s(Az?x?0I9JdV+g?=6M^|QgcAf&oR1HjW9hOfk}rip_@1?M5O5*2JM7g2oP1Agv>JI9_Z@8hB>fr z_p|Zx9oT;y*r5*WV+Z!(RW`ln99Wuzx6^^WVer-!jRY4T^pgNwlxtaq)5Fp3>UAKhe`0n7&{mD6cI(%qenkg#Tpz5dH1%z^0RZuP z=By+PoZ2c6l}j%|CT+cf6EDnqoD(z zy#gJ{+Qz-#Lf%b*uEQYzXt%a)^1e=k#pm_gA718&2~^su>xW1=@I3-O08m6li1{aV zkg-2AzCT_vZgMgT^bJ6fu}O*vtGUCmk?kWIzYRGB5ODQ1m}5QmUZa0+cvk=3M7Y!= zLv6%)Y_}dK=5$t%0c2;UX2-3EKqqN-P>%^6)MFqs9s#jt}?qoV@-i0OvU<}if!MaEB5R+cE#|)m-F3S>^hF#8!+tL_nT z{jo4pEH6iG74ly5ySQ{@m8G0;HDLuB=W;n>!L| zW$-#(mY=$^G$rxXo(K>pBC+f8cUSgJNnCv#G@D6(g(6cE-yVaUy(=eDVm-z|)a<-- z@EnxJcz8ZdV1T;r3f#k!*79kzOG`4^wdKQTx0ZiJ11;}HySKa*?a}f^v}em-qrF;Q zj`nW(Q*^(UKN<(v!*+m-H=FvNpRIjKn!5B-Ivoj2vx*rQV2zi%PVk)z>G+x&6|GEL z21f8@TzJty^o_K}lBOds$pdrv#3I+?F#A6v3}^G$Itjz#=NGqOmLiqRVVX>{wqQ>g z>O(!X9!H?r$Yh8sZFzt9CA1Pl21((%6z2@-!?6#Nd;&Q;(T!hzOFjx_+A;e6@b-)z zU>H5QLq^Ztglc%HcbD(Vp>vc1!9xh%TU*WOOYm{qF&&j#*Fm}0UZw?9)?vBd-HOyE zsV97wS3u9}X>lAH^@$<9V=+90jW6xQ@DaL_RDJc>Cp*zj*~#yi9oh2am7CT|s3UgH zGVJv5n9tI+BAwuxY-~H~P(pA1CPg#7MDKgqdF^c618V>|yY40Ht|4T~h2PU;>w82? zlMJu;i4LZvdY$=_Gqu@(5q{GL(obu0_FZqU+?Z zFwjWua3$n=r*7;=Q@qomXsYZf8agzs7x6h)R^Nnj^2k0U>g|inuTh7b;X2IO_DXV`7 z;{L&_kdkahz&d5e`#q+ny$uSXDLbDF0nByk8LID^AKI|^JP5l?Kj~Jo7V|?*fh2lI zgt6*=c12BrcM)Ttbdda>B(EmPCL#G=5BbK=_E0#APaSLQEt0v5s^u$qLM1NX`1eKw zKaFsFsJG=kq+;$zK0ly}xl-;{i#sWBO2;f6?ZJLdctLi`yDeO-sAb2WFW6OMT^R^t ziC}D1cSmziknoA-S<-aP?$2S&c29NXD%PxV_s4eEjvL7?xdEdJQ{~SQ5^@&(UO0Co z9jL38HIUFQ>MBByQ&N+rz~2S8t6D+mIQ1d>1B_V(+FiwT)@S7PSapuPO2Mw7d^!Mh zVgFu3S-KizsDGYiQNPwyZWSsgs>ATAEDd`>V7*j#{kmOV55g$vU5?_L0y_k70M>|K z(txK8pr@=$0^>;m>>u4v-KQ}g6Tp7aK8iC6z<5{y2SF12ng9S>4UH~pi3U7m0A1Ar z4R}BR{J!lh4d7gGIJ#f7x5A zdy7E1Rl`aJR-o=8Y@LRkE3h%@3c{9X*i8Z(t5y(Ju3;|-tVC52R;pn?8`vzuPQ)M7 z@7U|4CcizF63AAg1ha8B)|0efpsl{?efg*N#j#>_TCO&EWOU7I$}!r!x}$~Y=rm0o zdZCyXPQ$$dsLJ@7Jxgl`Xc9(Z@&Qwg05DU zW-rrW-ILY_X)QR5s2SAw57JONvMe_rOLHwN4VS7CqAknE+KcCrHQsL=s^#z)Pi@<% zYr9D1W5eMuI{^Noinze#-*6z$T*V!qeee7OIyj!HXxt7tLVW|-V$cq^-i4?uf7=ng zEOh`Lk#f~wru0%9u?rOzLi}*FLgg*zspU@yYzn0HCr%et?Z-(64lbw+tA3i)sY0rU zDgs(te%&8onfGb}V@%3$Ai_EH0+%wGr~ZXr7k~t!8z}j|{>Q$P|2q5CscyRcjviS4 z(Q$P2533FGFKB*k{M2`o?EKhx_U|E1ihi)+slO>`R%-hH`u^Y2>kJQ}qx?(##Vnxw z>+ILYH)zh!{?3zru=SM!{(rxw$|;qgoqn=ONd28^;Hkeho}J&OYroGlfX;qxJUd_N zuWg4mUSW8ORb4f|d}u>#Xn_@3S{1kI67dGBrmVU;R&Fh*k3_8LGfS+phK5Leyed{3 zT2NM1ov4pk)25V!DkAlf1^BPFJYvl+s|Zz8Ev{;a)k|7keXKlE0nAW2Xj$=Pb&=4* zL|J`BC{kY!oT}Q2$kI?O5f8-{gzC#`7e)YDTvlCG5t>jqqsS_&uP<8`Lb+87YilC4 zag%LA@pONt)7wGDpE0w@kJGy*R*|TVj0#!3tE+1HTU_GT;^C{$Sm zab#JetU)1baany;+5GBADAURe)kYRa>O+Z!NCmK#l-1W()h+~L9i@n;vQR_3o(~Xn zA_Cb0vY={dq#`83wj#9^)scpV(4^Aoq3T$y4n#y(A3#!1j1FKEc z%gr{L=&kgi>dBH>G;N~ybx7ur5NT3!qfYXq*c4Ea z1+heJg;kTNj#t%HFGKrU0CTMfxl%&i%M#V0jCw zV@oXj0Vx<+U5sYxz^SK5Z7i`6GWMg?M;2B!z&ILC3^kxq)m00Yd3p7^h)~YZp}G0_ za8!0xLRDIOWwjv`M^>!V3{wkd&nTK{iF2X{o4+h{UZg%|O*zf)B{EAVY3&U0)DQZI zlvkJ4`?Vn6%rPfdCju9(Rnb{G4L~K`!C6&TXq;N( zIJGj3b}Z43?&>4~J?RoSB8?=f_Tg)OE6~f-vTbTVD1OeZVNIeT9;z%utFMNOuMXuH zY7U0Ky?UyarCaPEm`HJvx8Y_^^qNfOtZC@MJks%L#O;MGr$p)2*>|H4f!`N%*Y&cy zB>L%!P^=b)~{@etj z8d#0jk9#PyD{RjMc_?!TveWRiT{m~CuPeyUAD+)nf^KC_Z44zZtep#8i3bo1Dq}N= zXshcCQCx)=t&^5#+B~&{EYph$OFV9+A(V-DXC$Y+q5Yb6p{~JE{1uT%9l{)R7Zr9a;pixH0DD|?vIB}rW*`J$N6W`4aO+E| z;&4xK0PtqXUxSGE)GWS!o2Ay2)h>F_fh?+x zEkWSS7yb!RTyDq`l9*#uDCB8d5_1o=1XITZ46hw4MF49_pkgs@{6$wiE4E+Tc$nyT*$<95hJ0@4SXa$7#axF=%}lKR7`Y z3^i`tnz%3+$M-Cr^OKJuZ9j@fRFBbjXRzv*w(C_DRQ#9y4mt z+!cBZV9iH-P;1R!W|hNkEwK@H=2k__ic|xFKUE7Dyjly&_zp!`0GRj)S*xHb1oAr0 zvTCcUt=Iw!NVdavOw2SK{M1Ft;`oUt>T9idC58m?m=&*2M8vs6rEw5}xU40Wh!?HX z5uX=LwXa&qXb)(=h~!Eom5@ zYYmMojcEA7M3sK1z?f+$|182t1gWRQIQFP2ok4&k#^y(fT9D_VRgkAahD<>oF)`#x zEFGRpDkb{S1~tSi3}*COL7syEDw3xl4~Y%&8n9b490QuE!*eH09d6Yx2BgZGej47V zSVQMS!r{W1#WSoaC02NP>14}9D-FxgOlx2fIxL&N4C5<~1gwTg+?pSYRY%HdA>*=Y zYl(pM7}G+$Wkr^jSJRR6ziO*CvIJ_cTV|EbZ@@^j9#rbBYAB_;0jjL1fG*)hpwRhM z7`j#i0f`Ial^C7WVkEm11EBInP+Hw0MyJ4AP#tHP^)RD`I*#-P7?#T_z#W>3)xak@ z{i+HJcFq4ra%9Z^MuM4&2+V0QhpY>%C4!8EVFgTvK7oyA{Ka!QhP?QhP&j=ee#TFk zW=$`eY!w&Hwq_R3nmXRf{vZBfKvo~Cp{rn9##@#(a1eoI0>o_b4Ct#u2HfTsx-6G> z`3tVZWGtU49lCqr~JHvkp(A=7@nImB4KP(g4R2= zXxglznK{GY5+;;Rnq&<{j}W(tW`|3s!(9}WOtOxL*bDNGudc|JMwq>HWI=X89w!}g zCCy3Epo(glvZ$zTSXM)gRa9&E?2!dl;na!Hzji*H#W8LuWd2zg3dJ${8#%%c;SC!S%RxP}R0+~~ct8{&(sY(xuIHX0WG z#PFv!R$d7xT7s3$cpg7>RpnMT1_x+>2q~Z=x3V)mwdP$)NN*vRbMoZOrtp~BiYa-IU2#THw$8p;-8j>;i0x~2@Hcinr9aeCU& zoLC+Ec7!AlDT9E9xt8vQLnqmNOF}m|-e9=WUl@ZVeWSs2_1YqM^{D$g(Bq zBO5HR3WE)eb|;jy0Q3+y1i@EG)D5H3zFxw|5M0arST%FQ{zI_GXsmuHI@egeWT)Uv z7vYUDvm6=GJcMP2p8J$LrU@u@BXn&XgBZ!5Vn7mwXj-vfqE-6e(Sp;oj<-Vaw$K22 z)rLqpf22UmZiT56>H2+@4Q|u_R+?Y4w$y6gg9fj4>;n1sv-4}`_x}zUr{7b5Te(96 V|7>{kbNan`g8sGt+IX$c{2zh`{`8wAy-c==;8J?>f^>w1@v%@2&OTqgR`IYJatB z*REZ=b`7Ua-Qmk(1+iGHI93tMWqb_pSbXtQ>%_W=CspJZ>U;ueAUAAX;mkkR<-Xzhg6+<`fus&e+)47KH`Bh%GIS#j226SQdkL`hQO{J{QJBcKm|;_TT#6{zH*q z3FJRpF<}&bwrmB1|E%sEy9|8)@BTNo;rK-jDD>JTs0l@8-Tg|bG*z+K(PNK0rr{Vo zUNs2+xfFoG_!D$Tr< z>X~^VRhD@swMFKs*@=}OCRT1rG=I=ppJ@KHG*yvHSLV_c5UaJ<@I>pZ;iWTL_Z?m_ zqjkpc%G`kK@9!N;G(TBAZ~mH!SYBS_tVosS#*ez8I4^T_8A zG&kUBFJEHk)$`ZbtZU=X*$$Fe8($ave9HUTT3eYI!%m!NFaHC%t}F=Eu{t;4D4%V6 z`FRTHrb1Py5CzH&80z7D83L6BsDgYHl(@DwOQTIdq|8={=4?UZxz4IvnF0zuqI)$T znzMzC?>6n2XpI+B95nHeTpFC&6iEEyI!R2Iq>}Eaf5KSSXO2gnqV#+apH*Ts$M5|d zr?}Z4CC9E{n`RN0b(f*h&v1sjRx=c4D0eoo^3(ZiDy7xtKjFU9i)xJ@wv6^xXi7`} z3wvv=t$-{`tA3bsXreV;m1td3nOND8=x~d^O5Da@&F_|cb?cEwdBxHgYpWBjb(M*U z>z4LRwAW^zj>R%VbLnx=lBHE7oclWJ%{8d20tyn&Lst4~kzO=9F3hSZv2q>Q+N?(- z>-;r}l~meM?wJ{_XoC9E#L9|9^XgJ0q&sJ~*~G{-iARvcf6EdVKAU(s%l|gJlM~3|dTYGwx=2)rM6iO9jrT4qpl-8Ralv@SzL`0*| zC_1-#*@Rd_{Jn4RD>1sZ(h~$cz=stxg-~zd3C)1@c<*ceCNA-kXhU3$XnA(!3n-V(z=#s(yxn7D^;~> z&{A~kPxGukVc*uC_E!2`?{R$s6#(O%biaqJ?o=}zX&>=uG98HNY6SY34&=(igMT^jO46`7M^ zE=~*jPz?F9e7ItDqIpvRN-=!8vcP?SMEa{&nzr#kSLTB*QBYxesRy|>50W{JeyZ{J zO@lnd_4$YyKomFb86a-RM~ng@p7uFhmrpNC?hRM!wtWw^qR$)gSlW+&z9BZl(RJSt zCqi7mA*fw#i1y+HTjGS)*a_%0&cn6Z78670B^WhrTXci||3-5h%jWoTbN9^=w#2Ae zi`S9Pn4LCp{lc>3x#aUZ@R?E20o%{PGv#2fXyZt`Np4pBDX&arKF z7U<3y1#6VuO=P!~vZJOLAyjExx3+`INyXm#0YX$|&Y%x*T9zU$(cTi{Akki4wWv5Y zvp&_=e2&1^J%uy|K(90n4lunHQ(>MZCZU)jr{xzBPT6yWQ!jHXQQIo2xbc2xRU2KC zU*emJ>t`B?`%c|f+-dnJf_g?#eaxXmy`rcdQMn%SIPF5r{fa4ZTCR<7xwHcD85zjQPIw{(pXS566zsz* zBV~ygyZ$RNw)FX0F)|#$E761;u_FTc^8~XJn(``a>Y%UrPcUx66vAvPB%MF$keG_) z($xr{&HsD}#j4+_WC+b5x877SwY~h3%b-}shw&Bs1;1IAEWnJ@EoE~A?lvnyfh*{sL2bYzKwmlCZ5p20E=e#rpR>82QbVPJ4;`Gc+5 zUVZ}+s3z^JI_A#CBpSVBdINh&kr|G-;{RYy9ZV26-k3KFMu-?pBw1tpAMRGYc5!NP z=34mcdM|yZKReD1_=m>|3PhD{Mmv<1q|S4XV(mDN&5KZT;=xN&jqY9^05YK3YOWAS zG*XxKf=!+NspW9s9S1*C)ih9lqS4AF10zo~&Lj`9ZJOz1v zg$=<3Ky#;XoL~g}9e$Kryt!KA?yBWuoE(~0wIWom$n54x0QICprQF+| zUpsbUcTo4Gyr9AtJ8czERnvjtn#R$9aq}WGstV)23a51`fOAzgO;t{@{5qRDU2Y z)Hlk&p%`(5 z=)=e}aov(7;6o7xYn_nUv$sDm^F@+b?X7iMDRMMT&!vr-%vz|0)1FbqZ5u|42EiD8 zEF4w;nT#fbkr!2G#dgkCvjQeW_v@H!Yd zMENaeKwn)&`I@2}+^s0N0e5)(?I?oP2x=W!XxH5|gN_oR(IQU>SU?J^2$(eG#xHn= zy|SCSZ>6Q8scB4hXbBj>-M@CVtvBahTYlz6GPGxeb=hMY;V|{*;-%t1vB4o@PK z9X#690Csp67}n4=ONNVbz8Ky}>e+68aCQ6XOb2{p_2w*^C4BT~*rpEGYu8B8GSL$J z`w04B>%>FaNe%fT+PKA2W5~p+U{|u@JloTN#&AqVX=~Xs{8{DwgsRzJTVwE6?X~^c z+3jz{H4KKtk9obw>$vLAkiqD{_oY)o#eQ1)rPHT)xVe~B)VRVVIcFz)CRk`28eEK0BIR z1$9@dEOqFs-Uvm$r*j@;os7Ah*LK9lsW0yzzoshan{QIbA zUVY0&4y~{0!K^BWOjNTK4P5M{Z>wrRCzfAR8p@LG=Wku3z9tOtod&0m)V>*?H)XfI#q({HzQ zjt=OZ+drcBTMuGI zqJR?yFqi3qt~*EBl((&cSTAovGKbiKDEwVm68z?tzC^> z;~18er}B)#8Si01a$6K8ZX1|##S92xW&q>9$9^2{Bye=&kgtM$cP0LSCZU(dN~5-t z)CBiXIzq}jM(}x?0Z)KC7*Ju|Zw8d4rn>z+7LlERizI7wC!i!%>;7G4kI|_X(_cWk zHZJ65IJ>`=4X1(%z#eawDAIQhJfY48E#z^!3H zl)7ZR$B-76z&<97u_QIy-Hqbf5Y>4I28kuNo{~2g%RC-slGb&awK$)KhMVdUTUIxA z&wZY|5uWrXxR+-BY}b91pIvj~LS>$zKZ;q=6mxjO^xb-d1uHiW;8fq>Q9#_(EXhi)aJS8>`lu@$_? zQ>KeH|F1)ibxkuuEH)~O3(10kk0(Lkk3=(NNkQ}n!dDLD+nBinyr@Umk!rjw z*-BoY=sY`bBgl?QKR;L7MaC(FJwH2Fg8^D@N2R-;wpsGHV8%BwI^*+3U60XEBiSdr zn?mjvWysF?u!}nX%VyivE((~_>D#f{nRy|y5-i4i^1ai30g4C}EIqU=N&n?O7M@Pm(91%XzFRqYby>v}(A1iNiJP0P+snG(ALjwcP$>uql`nN>>EEwSb>L#$E>iB0FI7Z-1 z1Z_utuGj~ojxVFPRPZ;7_;xV$uQ$ig$s+5De#Ccm4oh?&NOxGpIg}-3Ws?NMz;Z2BejA9bB5UyqTjUYc)^iZXG+f3Y5;6KzV z-$ny}#l2~F5;sA0?5j6_q$5O~Y9$|r+3xMHfEf#dj9u)H=9amH{{oQ>C(sZflS+Qff70UMC;bxVCna)tc8{ zPWwkF7T`^2K(0wU?SIt-uUgj3wxV>OaU;+M5;S#gGlw)_p@Rrr6N0waZPdd|8#BY$ zux+E6uQ}V~tQy8&s1ZZF_3i*Z)pS6{#@7-x@8ECKp-LUI8V^{7=|LQdG(1|SCbwj) zHTFD-w*xbGkB}J6nRG*HSdC<({>Zt)_lR=tFGj4k!8##{_NP)tDDkx>Atj4 zEbRsCyn6a!X_OZw{(JI{C5P5L4#=J1(M;{m>oGjQsu3DYAow(bg8_Y$o}&@cJ|G>? z-fJpPF6C-Bxjoshf>xGuORz;5-fgt8Cs}SmmhHv$C$N7>26ok827u1$#ppqp<|*F# z{pn=1hI`7ssWhAcURXWbR9ufAdH5N`UmoCT_}Ep+N*2yGwAW*qPRE@rd0=hQR34Vt zxkG+`yBZ@= z^I)jzP;)+@f997KP;ZXFiZ_}lo4LKa0ol~2cr4f~mMwZL;if9hDICH>tLY3MaA0JK zgE~Gxn{_Ni_rO2oyAOZ7*a77Ggj{4sGTB>`66vuP(jSTDWyzpRSIDqjGVE+#k__&t z2$Yd}t)!NkZ{PUOH3@CVv^i`D2;Dhtt_n|^$HApm2h-*%nKs+-h|v3FiyzZxi~yWM z-w{lqQA7pZ{89D?77oU`b5Vob{T1jw;ncm6h(iz+IL4AksV4r6Qqvzx128lXXE51`A=<#6H6UD4$J1|{m?HQS}1M9NsYk2!~x(p(UmLonA)X1lZL1nlOh zoeYoTbY;&EMCYsD6hOMJcaO_|QrO7mhVOg|mmL-L7 zD{)`WSrm*B`r=VpN?^5S)?yX zP1JQtbV1BYg5*8iFQ`f9p(&+-Tzj~$GjVyxba2U=O4QdnE4a!cH|gqVd4tKWe8oCGwE9?z; z+(ODwsex$HcR-eYE9p6|6nagMgb-&s8uuNctC@vp5@9?cG_P;@65YXkcL*(N8MfRz zNxx9&QOmG&Ig)sy&=bDZS(=0+(}kw)DJ0Wx$#*BA9gv^zZqnp*QhWlNJ6{(Jirufc zgcqOE9i1-0eOc%;@_BPf#C=$394K@^t>jpQd0`>fQ0z3KOrxMSLYH@l*~wJ(`4wizN}C0!91|`L=wUM3fZ8KNs=CsYVU1o*&25qZMC~(-`JyAj)L@8idlG@%qM4mm@Il|rFquagp zlGF%ySEl*%C}|*_-0k323LK|IWwN(}TdGjJ8^xF@1Rd#q#-Jg@MFbe-zADM916QD{ z0RDspQts;B6A3`ZyEn-*Y7tD4ofU7w3{Yq`2xca@iv-vcON?opaPq1-(LI{!zAaa% zHYT~#m`t~7Rd=ZH6G``Uck~MNgQY#)O39$7qkZ-@Zh;4ttTnoIiz!7=q&T&b)D-ts z#uMF1Ij?4b{1=#B!b@B_8OWr_W*$C8>kllOxYF-J|4r3L45^WN0`| z7;t@4T62~=i6Fnps95mVS^ZEY*@mtH2}O}~s9PK%(FSa;Ij+l~LK$YZkke2V=0~Qn zTHf9Xq_7Qgockb&ezlHwZ`Eg8trOfUBF{${woLDQ-eZ zFsyqjXj*_c{p1?7bw_wzZ7}riVn* zeuR9S%W@A$!z0^vR4I9ab^&QJKMneg@O|7u0_14!cNg|4| zBt-&>hGASm4K#5RIg|)Y6`y%kD%)L`ElbM4`Bw%R+MGCFCu8LrO|nJH?Ee8tVl2bb zM0>j9iY2FEHU)~1A?-rJ+J2p@tHh2gvjnxqqwwyHp$(@+DluTytrjV4k*isaDP)tc z&kj;XkP>NXTvSjRbGP442Ei?+a1h+W9E{QSzgX_3aILWnmzH~^50k$I>6uud;~N_l zO;}$cK@hbjop~F0JZDdZC<`w}RSCF}R0z;Ccc2G??ebJ&2v;d1k$s24t_?zT`a@hY5jnD* z=l!69@hG9dY5Np9Z)!kv@vGky$8zKF<4XC#Y5A2b+TXTx*8z%5@y4f`h9r61jxXTh zcxn{IuotKvPRnKZmE=);#mUI;bIUAY4KX2WkMD^BS+f(IIq^#mLC8ZjX>Ch!u>AyQ zr*(^qoL{bHudWUe856}cZ$2&^seDiew9H}dTO2=R+TNw-Kra-&pz+`)JCv z3$SxwA3ZZsr01Jeo~W!s`BoHPMDBpd$Q9JLBz2N|Y_}!bz5H=rfA|+$Q6;G*?v`Za z@BhAq2l`)8y}aii<8zD5_1ojcyod*qT66J^8ZC9#b5OCnS-Ox%m;V@2@e*$@>_OrB z47|#yuG%CXLqqdlQ)1*xxaFgMCc5^Xe;{~b2j1!>3_H&-Kde@AO_cBCbjnF7R*jQT zcO0?;!c->|5!IM{e9 z`puilsVph9Cv?>7PUEbgzq1_Z%x(gU3%)ww3@b?ZOU<5s!`M?J*tyP%t)T~0r#tM_ z2sY`g;0EqbU+T*3aj<&s(O=h4kaVUv2e_2upkAM)efK8C0 z6E)4r(cVpH5gg>@O0qZi1qsVTx;ovN7|E+rFngK*D|Tgu#!JgVq_QzTj%5boK{id% z@S6flF>X78TE6Od40h}6Sd^zGR>~a|61zD&S6o7OxGy=7*y=TB7e$XD=6P8zQB5E2ZFOL~x7nb_cgl*2b_U3GZ5M_GfL; z2ez~6J#6|;Ha#q9#sjghF>_fSi24t8AUeS+ad@K}r!;Mi5@dvdBde?Y(wPefzyzFr zKOL< z6d+i>qi>LNW*j|`=X<<#-wh@@7;xT>(yBfkk{Siqv;oYCHK{A3PgA zCxYiqTvu3IyAjOzcfI`eeVo(sJkx_7zg~|peu7k&YXQEG`sOuhX=eo^#ndR4^2rQT z+vzm?1%4Z-UFd){p6*+(*qIe&6ZyMxSXQ(>zh}<&U$m4ExbwU zHw~8vbW^{7P?o*{bH9E<*o@OgKUqH%QDBQ03>DY1HOnub&elGx11%1>hWbTo-5a$| zjV7A5P=_oq+o;a&;ZPbHs;I55N|7U2hX;qD&?Rak{>!$X;C6}Nj!zd`#e3eyV&!C3 zj|g^5cRU66cKF~>c654=t}@Djt%oAGF+u!8@6U6Dc{cD&x796!A97C)Sk;@pf3-G# z6*IKQPr|JQ-L&r(%(zRC(QjWNYz2bXz6em(p$;1{maOYGK)L1tf^C4Z(FQ2EM~nf= z#z<4srn)LyGXHIigyAdi_I$jOT}t9>NZB~NY>hH zw@DvO=PP6Bj;Wn!S|-dVixV_?zMB@6870Mb!R8MJ*804%enI|Oh>kdmlL)-Br-KZ~ z1CA5#ebtTiGC0;i3uwN$Nd@6&6?Bd3J7k{hJ5xn)aQX>^U3S0(7uuU79Pwjk{HS0s zNS2R5_xxw$OCH}-Dvv4qq zH&2bg0W~@uT=W=vLmQJpgW};n^+>3dj5YX4(bA(m(NKY(uBWqtS1Wi>TMI_r94uIi zyy(}LgjP+V(!8|6Qxt1iZ+1bXQ7Ut5L9L26@rq{suo1H_kqRPyD>*_7J$R2CP0}Tg6UuW= zBu~6(WpON1#nw145Jn2fG{C&aHI8puAWKyhjjuO-4hW2XlY=6tEO8guVZy0O^b;wU z%X1&fQbkpIq=gUd0^ceMFH1hnCVRvl_42fX-e_N>fW=h1BY}ZPqZ?<*n;um-x}^p1 z=A~X7x_sy2R$!O`c8t^V19M>niJ%{iqTf@_qnwr(yF<&ecEI~VMepRaorY>O^|F4< zy;jrrb=tV->8v_mc|lQjfsCtW^4=^@io1{DJQDTYE>diaF?rI$26WPO%R2C`%+?97>zf{IZ@uP3(qKO98f!@QCeQfJ4bkx zCI86^^kM~6pi#&Nt;~`VvU4KQgfL_Uk_0u|7gRrIaf!OY@JPfK8Lp?*6 z6^ro%b1awxUp`j`bf6exJ;xPNjQmswK$~Rac_`1lvCE+Wbs4y@adcBk671Uh3C^te zKldzFkQYj;Tg*&HjS9R86$Iky4*xA<48apDv z;md~)&)tyAE$=lvRt4{RZ~x&~M;No(xp&s^V%)7>8m?VlRcuAXD6LMo2C+J*RiB`p zLrXMv@L5~Cj+OwOt@q;cNQ3QfotEEVbK*67L>tVNLt@<7S<-Z{6w9uScP)Z0ojFw+ zbAD@m6Lj~B{uZNQOLH{a^C$0-)41hd1M@10 z)>$FLqZZ>{poL&pitj^Z`lG^&2V`DxgxivI(V@;R)B~+CwvF>!@OFpYXko`$uF$mcquh zP1+Jat6O9bvYxM5iyQy!tXhOfNaT~Qz?O6#n#NAl5L~eJ41afsAHiHaUlLqP&Ze?6 zM;Y~L4tSTL8*Ewf8n)WSII#7vT1|HpAgYa|smAI|BOOUgIhg3D02l)e;2LjGJ-Ol$ z%0xuALjda3Rm?8pyU($Oph&0XVf+d*q!{G|TyIraQRA&m^8!$91Oy3T=P`(w-Zj9S zttF?+)HI>m{AsTBj(STacZ|n4t8Pcd10HX2{|YtFSH4@WVih|rI7lAKa5ppf(swV| zTNEC${!76;!MhgE!yZsx54jE=&CZ8{^l>N;4w(-{={Z=pJoh|qmUCab(wx3YN^Rg~ zCUS_G0}O-d-l_SO5QFiz#n|WhfcnSa3?8Ie?fMQ_2W>D!<&HRTDOBBVcxQ*Atc}_2 zEBYor@}C#**nAcNc}4DO`aO(t?sY6!;xUbq)S+{B`4DBIl9OLk#6@q5h|<49M-#x% zkLGMqtQhr`1_N&lvw;of_9(RVdMOk#%*I{e2b=ToEUOKoSKbi*QWt;hwWOR!M^4@{ zF6Al9rbofjA6@-X$=hM)qEii*pPF_;qrQ1=aSR-?JlPCk@jmK6sK>qQE%4xdX!f=b zzSZ~?*R94OBg)G1O7-l-Cf+0>zwttUd-*D1hI`p@`K2=3n#|@4vtGPu6^qZ=%%90< zYM9Y}O%r`aQ_*lZB3iz87iL4rtRj!uLnfQByvA~|{Wwt|X@}C}; zff(c1(kbw{N%-_MPd^3b=_)gZ>mlv&UrKVJxlfX-&6b+HRFaF#RY(SEp*(J3R`O9A zQ`&p6QjZd9x!G41L+pxkdwjMe_cF7Db%l9c(ZeLU(9}qBrMXp;dr5MU8No+%*36ca zd@2gxN+{LlLr^livpY9_(9{QnY9aJ7&yz3&ghK3Zx5u}Y?F$+ zW_f`11mGS>0!p2>i}Y77XVubx+wKbPV{Re%6or&KZO1{M&Z=eX8(Qp81#WE?6S$88 z2RJRe1iS_+q_3GnNR>ji3`th1fc|DT0&?Xd*+8e|bNi?#^40w%G$d+aYLOL0=y1HY#LnNS@affQvJ)0N`N-?BulE9`IPJkOAg7LatEA zxR72RSHPC$E&|R{z|Ky~f`G@p3h8YwB&1#;yM*MpMgfD&2?XqAJ1radOZBo)A?4=VUjnjPA-jd-IZ^>znpX+9K>@ov zEtdp5W-4SW^8g`@3Yien%b}HG3Nz6q4g%<5XW3Y$Z-mp64J|S3Me;=3D`#gSSjBn;L+hh<`7b) zkiA24+@pYjW;X)l4&dhOKJfoI3uNnZlR|o%euTV9LUR@y3EW_a_?JEdrJZ`4Pc8%S z0R`4NEjI_ej#XY`%vwS&RmgrJc}`cr0CPJ5rz>E8r{&0i$1w^iH_e31P)H)AmpTQ& z{}V7;0n_0B10MT&JSG!Ts*nRha*R{JKr@7Zk9$a^r^EmAm$vb6kH`0y0`jCnu&?ne z%*>oscy-$Yo;yJFvW?k5;57=w9?Hc5uMa)d-ABkGg&Y`?XM+L;no9_nqkw~)mi+=A zPb*{#b21^nP)L19FAu03ea!&`^i#l0`2T=MyYlE~b|9n^Cmhh$2Z!W1z>}i~0e?}z zA@KkFrFuEBLaN)(yuS*NyA?948++MRdG$As5!kH2*-p#CfY)$^3^utRnf577vg;bj72*Gha7BjCK|MG+aw=p*pc(MZLJ1vI?y#A;V z$21X=P{@%Xd48*ae&$F5c2K}kP79K~cDhC(+nPNHDOSkQA-!CyfZk>h0qkAb!zd$ZCZw2+47t0*07Z3AjN4$HM;yJkC}~Kl1<~jS4xg8+$ogfdkFO z1RkQmQj#J1f zUi=b@cXQgWw=)X~l+UGLztU+L74T}(It?)g5mKqVP7BHNw({80j3t0Og{buD_?lJ_ zR==c>k!A}*UQx&yA-()f0XvvaS^==%O*s?(Kj86}LUuH33E>yjP|U)R97X}VnA-_B zT>)po{|7w2Rmc$2ObD-)0*{7n?B!Dh4l;)m$cw@NOgk-o177bdq{8e@2p1**IXfiJ z1_g{VTN3aNCtuCkbFdd5Ov7xocQjvJ42YaN!45F=GSPOD50uB&W&;5{%?cjp!v6<6 z-c-m|<~~4hAAWOoF^)9sVi|l`CKlPtTt@1AP|r)(TiWBAv)rUf!vaaRvGMJuEiLsf zk2;6c?Lb|Ei}AJZUZb>rW)IRzQX}1>FE}T!y}v$HZ=U|W%+FT>#CL4peo!XjSkIHC ziaSBYwZEyGk;-j3U8OLM%oHqWoUf>Tf%2Bw%wbW;1o9fM2CP&c$Or9^b>Z8o$f{DVAGJBqyh+l*iJHHVGzGho?eXD~i%RV;zk1-;#{%EZtS5ZCL=8`U$THL$ z<>cd-D@Z6yGTlAoQ)(XX!exh|GVSrdO6GF29|r0FVsWnmOG@Sxu6g1xTl06ra97!> zndcHGZ@?#5U&8))nY`gsexcYn!H-A5r)93UU;%z`0f2aqOh8=x-8>A}z?|-$4SPwP z{0x|`W6$b!m%vVs!p?9Hio%Y$pRn>oxX6;!8E&<}JQ2A#jWV~5GCR{P4482VmE~3_ z!*3B^_!TZmo$0=Y_6_P>6*&`t!b|dRC;o7~m#>TrbK3V3uNuEY_~GQ6R(FYe zq41OHVo_bX6mHBASBqnKdqdiW{48>Rj%vs*Fhar#Tsh8Mdc8o*Brk%TSksIijN#_d zuPK-FP<-DrP&MqvoQpClqGc>~WxL3h(TW!qd7Lf~Yd>UpD<#X{UQL#|e}w7ThLd$@ zUHj}tv=?Y1-H0aNfdIeNyW-GUmMR=ZQF)o+gVa)YXFjpTkmQjSbM(DHFk5Tms_>-0 z4uPf?C1k!F?n&=`+fU9nw%kFz@mn{^2`D&KZoXSV!MTObGo^fo`dSw79e2ravZa2e zDzUy;-1# z-DC~7vRuB-D&5rE5SLvf%bhp*xL@%|Vb|-S>dp4If*^He+~Te!F5I(aGib?a$cwEU z^DQ<_h~^8re4eGb^R_$D@-+g0cvW(&h+d~1#e9<_-@2!1cTf&MxYCj8*!#E0&+>3x37+W&J%E`)-I9hx6?|-7MOyW_ zp*B^>Y`HUFM{;z~G<}4;nrSnlkZ|n}wVC9!>##un^%4g7UFw$`rngxXrX&WyIO&=&X$Jjb7< z>x3O_DMXA9_R9Dyex4A05t}du%3$#rS#(n>ugGMnf26mNQdQ)FOtZ&7Az#LeA8gB& zd)ir8GVi8p6gH;2BI<1sFZ@pQvz`=GT7551!;sY2XbWA)mO)Oea>O!Y z`AeFZo>97ae=u`D_y(Z3UIEmEk#00<#k;x4w%#ng5mZRftp)H4z!YX@Ul@Gjz=~5V zx{be(%+t~FU3BEEc#wuCFJAxT3L$DK~?;r6Cs?xbha#`gT1HV3#k?F<6cJna`zoE0nmB-nTp%CJ3SK8tEC4SkR9 ztXb(%g7hBg+Jq_vZ=;A2$e><@T6u%I<;+{aGz@56CS)D{>n)NN;~j93TM@iNE-({7 znA5gA9jv?l@2U}dgQn3Y`y;~&=-i;@qwv`oM(EH1PK0{gc%=h7dzOASGsOds#5q|7 z7xG0_G_TE&*~WuZi`C0)N;!Z5rRt>f)z5`UgI-VZcDCZ#26I-_P-{V0DK&(katp1> zehK{xzKL${0?ix($wyzww$crcxO-}uOPv;pwZVQXin6^Xk8s+4A(hy|$~lO{QYB)5{n|>obx6vwh-SfN ztd;Wl|G|j+Dsj!(9i5gnHpgHx`m-kQ;k403Ijdwf5P7#DQ5HF|_=crzn`a14zc=B&CGg9yvRf`zZBQLq&xd5W3_5vVYJ;Le?{`HyI<)i$dl)7>=jyvBacsvfqq zVI*v$gd?3c%I2&pvczpkWSopz)i`atqX2wz0cCDS0wYNfaH`;C{zCF_CUc1e$$L62 zoEtEiL8#ZdHLADKNTRS;+zDYhUqX((?9wK3jOdzUN1I~-a>zvrli+0m-JvUVjD_w_ z=)T}Q5|_#WT8(s!U(MP1>EV1H$>-sCUgEUz0y<~aM(B=|QKXb5??%<#!q3G3F(ZX% zuxoHIRdE92@zyVlFBJLXsgfSPEI9=B{ z!X%bZ8!5rLesw}$WYp3I0aMl z*O>$p_g^xPFqADpzvv-yYh*}5emnT*%G(XhGgYZ!`4Uz8b?EO&ByC>pw9JS1!=z`w zd3pmXTtLXg7f@qQ@?Edx9csj$1qkIXQX&>0$+s}svj7R0{6am&Jq*U7g@M%BzQnfo zq*(F+!he}q7|cmu_pdkgvV!5Y4?Hs0i~{32g;^bDjjPpq9aae67|N_2Rt-p!zhJW8 z9qq?z#gm*$cB@IYeWny2GVyKdbW(2)Qv=!=q+K91wenJTnRqWx^hpi8md)B3j^8W* zwW}%?lFejc6YUT}7(qg7xI;+tP$v8J@tc1Dr*XdU@^;RLe51^BQP!yl;dv4wnv&$F zn4Hf!=%s?WjF^0r5z0BjH0(4a`3zy&#c53H;*%Pvj9rwyYQwWgp;Rh+br0f`B)LzR zJuPy$>cLZey1%xAXP!@jjJa*3Yci(yW?kVW#q%lAjk++Ff8%_;dG1nZ0^MDf#meZV zWOkO>6tu!cWN;K2V5wP0iYhD=mTG`+`@>3tCMig6UuJl3FA-&*tv5+s>u%s>6{we2 zl`Q<7I|8{GssMIx_pnWT5HVUS9}CYa?-XYh{f1)+k6J1tK_)r7o`PF!zR=`y&p;%e>Y zArZEwGxvMYoDp2Tl&Rd{WT(Yy#CIpvcIUtI^8`%%aGE(a`T zZ46%8*Ct*>_0=PnT5v6SE}ID#pQzW0%i~%wx9mlECC-XX>h5h#cn-u}_P*A{i%?qr zKn#PF@XD}krgQ1ki%2Qpr?MZd+XbB0$=t3z-ZI-Cu(J1;mt)EO6ltxREYp0 zuW!6U!M=SDa_F)X1F&bY__GP@uK%WpXXyu;F)7f)9GkNPnz$dfB?`n+Fwh#<4MhC& zIyv5^9ML3L=;kcLBea3Q7gnCer&w6l{qQ2~@#!e3-teQl{4z>>Z+SeIkK78LD32*V z7U6M>JRZSE?zwL#kNlEwDvrlN@>s)1ZXP@GIF^qHHsVF{IFyg2c-;ICmRrHco_Oq( z#{xc<;qgOx{1Wf2Ve237zR2VIe8e3J@t5TB6+V{Z@hN$HijTO~HU39=e29L@M4wJ{H`8X7hmGby7AFJ?KE{}KOF&dL|jX%kS8oYip{UlIz z`hnoO1VNsA5HtMrjHh=JeKnoUjlbYvY^+VZ*>bNy?=V;1iKq7RQ$RsyMZyYAn63%# z-`R^1C4UVANcA>5oDN9~GM}XiGj6IV^I@tu^KL4hc`MZ;^S4w<=C7&J%uA`BnHN%J znP*a4WS-*P#robeE(K^`jPs@ttVPM0vYjb_e`3n5UpJa6&!6Mj z+ryNrZgb<^nW&fUahJb^-@Fvlt08W6Do2|=f?V>++D}5lCDz980^B-Wt0wan4kDwy z+sG)mvVbj&6ny{Umni=UH`h~Iz4c4Bx?^@e^*?WQ@w~bau!LVp`ZF6`TYtCA|4PGk zWYOqQMf+`#DX0?cV`An~c*`uN;&)!ZK-zhA%w-@7}dSVHkoadIL z_H<`b^Q|i@;ZtD)jZB)vBv=}(25X9ft8qs%k@q)nR}ou^z~iJzjXR9#n3kwhX3BO* z!FpiWW+bxXQpXa0qewoWWGh*cO1RImRVbEM&)c}?8>(kXYPx$HL7}R?dK#Y5M@mvN z+^a$RcWQf}d#n@{s_lX93@sfMC9{LvDSW1nkd1G=5Gxfu$eqA+8=@>;m@yq@ZE_vX6E96QgAZiwz~I|fx;S$_4o{SqeH(9~&Jh9~%Q_S((N>cuSQ zBVE5BVDow(mbc$%-+(xHhP^sRj_G-Nz*Pmz`oEl|`<3w~a+v+VeD#huEK zU7P{YoXrCSKH>_N{Dva9hA57!)GuAg>p=EOcbBj#Y_D*%Dy|?^h4(U#I|g*zVEpxs zgozbMU$P$qI@6Y9I|uUNK#%Q8Basz?*^@Z8QLw!UkM<_RFURco8>I7`LVa>SdfGXR zU`1VbGTT63;QTLZ!sppr{NGnKh;t}Qawg-h*Ccwr-eStXy#Z`Pp06zV5OH@Br_S#b zE)4&Tp^cROFv(YgY}Ms?`^hjy?~XF-#mkb95`46j2^Ux>4&SEkr;@P$h|4ca^5R4N z*n7z9Pm#b|NYx@!FL|pvuQ%DztStEyd1SbI>QB!wfr_~sH7Tg~1J~!*n{kYLzihn9 z_$Kv!7Xg~qn@3LFn?U||>dh0TZc@q&)mu^zR7u49mnC`FR4+pg4FFT5&O-Wy$Wy#d zM%He|fU@MP{$bKH?qn6>#gnPmyHz=)9}G9;Y%Yk^jJBSKkn6X6FE9vT#E^6pYF#s#p! zxPX!|=aLL#NNLxm_xts`WK~3pmK+QSWy$wR`xq1W?#Bd-3ak;j^8j<@eC^KLUk7xg zJ9Bt&Z}ymI#gI?BvuNUQWDUCWSA?HMcvKV8o#!+B)$Uxz4t3E9c$N;uTUFcyvT1YJ z?i{q{_oNRdTYQOyKFLkt91P;Z%MD||3Nz-||2zg1_U+|6;bT+q_Z2u8T!DkZ({V7k z){KNf1ocJlBrF5c}8Jk)dRs;EX6nUT?8Ss(3 zk`>a81M;#c@*sCqgeNY6NL86b4yR^t*1Wy^m?*y9<;nCw2Aq`#emlia0e>^b$Eo=M@$Bh&B#**RuAqGgN^PV4k~7N`4orTn7ups!T@}nh~mw zYqWuL$nHpqJnvi&0*Fu6PSe6DaSTXn70Vicoo2ziBU@jjPM4 zNz93(*kdIQOmwJhybz?le4G#7jlWvUhw@MJ<{qdEzMk|Wq&)eVO4dbq_w?Z<3h$iZ z!;g1c!f;`KrjLJ(z}E8B0saJcb_kE_e6YAs&U@Ew&D-Ox`!bKO+Y{a4%;3vU8?EvS zI5G-Oy5BMu^1)>OJqs7j>>LH3qz8p9n61`c{wly?2A|FWpZ54a_lXFTa(^A--@KYu z^@Nw@QO)vPG|S2Eagi)XBg_3>mJ67rH9nUjuI-S0=AXD;ru#Wt`tbad1O0C9`i=W8aUY;d;Pt5hq(2>OwSow!cXHSp6 z!C&p=Z`uSg^|2n`YN{8qA04--Ha&7Ls@qP{`5k1 zQRos^z8qy4azS2X=3aOT-#W%X5i^)-V?_Y}n}XMCj@F05R0Y0Re~9-`l`1m(=|eH{ z6q||qP>MWpvm+j0L!IxzZ{zQ~_U{J%l?Bm4lyW3R4u~&V&}sn{q)GuSFcTH@2TQ!$ z{{3ADRA~Au=w3^_(EhzL1S&FLNKh5O2Zuu`Q@aH%6;ND?D>lz6Xt^aO?cY=g6gRgi zsM-=M?cbRKDg>v3R1dREK}DAM)w^2k_z;5|*BXmJ_K$qj+Z%%>7##qYA5p0=P30xA~4w=ioJ^r$7?WdA-A0`)RCE6B0L zd+p!r1QbgZL#}eO#1?0XSKGfA`=Da1=FL@5izTkKe-~R&X)2DzpIrfR59%Q!!Wly8 zW2%n$&w~N6J#;Ubxnsr7e2i0k2!*mTAmzBI#VB9idH{Bw#4#cGCugF}m>k+Q^`Z0) zNcSGmd8;w=#F(w$(R|@x&=CKWq=vhQOoWx>w)?8dn(0(Nw2Q~WqW7A8bGZp(%DdM6lY%YpvFV*6Ag{S<-Csp;^U@`W=2}yjxjOl|=Ib2#kt#uG?_Ba@7mRBfq z8IkvG>mm@@upM~f%nLi^7=>4%NH0F{AnZR5iBwk#JjQL)0%=#YdwsoA9Stnsi=n+G zxWM!(*{vX6r)v64cb|~t?RA^59LSyy3)w^~mjhQuPMUhgOD|E-BxmV2ff*Rit_bRS zuKOj1#h|Xj2!3cq7ny7q_hhllau0G)wTjFWC$B8Ke%9QzILbX2N{iIBEZG7Ra%YA3 z!(!9pA~>~H3mqAO&ci!{&9$9{sv2~PmPvH0d6AU*tS^t}oW`CO3|yI)?EV914-pJ( z`v%9-zUFxh2mk5T62xY(ec;{_=6OqLHZ{>Dl`-BVrfQ6bcS@5VKpmND?X2IEmKKy7 zzv$#%F>?wRG`v9yEr{Zbli zPrKX8=S8MtKg7mU(qi5 zmjCYAwqz}v47~Rc%HX#;jt2CyDN?cY7rufk{N?1~%rsDn{R00*fri4-AGMcnqT1Mk z{u^K;2!DlMSXXcGnnip3QGta;;cFr8JpxlvymqDeMpt3uUriS2Ui;ja4vr7^f@2=N z1?x|7=*8OOGpF_9!PW{HL!`4|I9@p@_3kog2$sH z8(euWRE{(ChEr;NJH0*L*oDnLWOK$(u@UMC!e%cOWKtIn`;x=hFo$Smgubot_>L$J z5Kn6B^P}d_`uj|#5d{85`oW8`dZbN_m3b&`Hp^N=ryf|HUM&ng4}{*)rM~AmSkDAP zZM#GZ$JZDiiVv@mCX)NhEAo^tZ>cOq8TIA>6|4f&&Oo(CQHFzs&TW>=-r|?Sh+~Kt zCx}vyLsTa`3Kdko_nCvcBSu)97JeC&j5C0>uu#!@QT_>=g z>JK8ac(k(!KAPb86r8}vt~_Wuw#ar;1L;#pXV;X2zmhaYk}j7#%fG{7BAZ7j+eyi? z+!{FEpuk2ll!+t9YAHjK-sEfxXBa8O^39f^P&UXsEL;^%u(9>Cgsg5Q)yiHfstdZk zl-e4jzkPNOF^-)28&ptI|DdU^q{gqulSB}*h=@Rf-5BLu$a3~%IoKn_mWm7t#SF9q z@<@)M9-{4X17(soz5Ml2tCbr` zxr9@|)+vm|t&%1A940q+RLSB=ZB;5OYK_l04(>;<+J~c`vQTaq zz{`iXbnpsu?PSi11G%*9ZzSAFmOWGsR1n>ph9w&NACfZPS`l>^wWQyYv|dS-iJE)h z7WI~Dn=$$cA6%SD=E6>u+Ew3CILoslDLdT)+i?$O3qbDEwAB)yLr z<^>tx>2j`I-k^7dY~S=$0KT8#odPggFz5C`A{0~8IMP}5TY7R|3%?^g7QkU9_8ttB0HdUwdp;pG{1`XBp6rYA zAff313S=&Gc%p_fG~UwmVu1WTk<$YtoKh|`4#gMC*&M6qhltufK%w8`WkrU!x&G`MfxOT35#Pwd9T@U$jLODJXVo3xirIJS8*WAybL=W&w&pCZ zVEqELKuW%Rdn;a&8$z<-(<9Kazwm!W- z6aUUc-Zg+hvW7BPYB>@Y-U)ZhUKJ%naku-CWp=G6UyP6&w7e_2Vd&s z6)Mfy$}~UG%Po+iG`?}wnfeErJOQJ0`8ClX!+(Cz#IVdQBFUz^Tf)WPcePS(Pfb^fvfX!=!zROon$)=z{Uwed( za_(&)C0gSz9VxDN0_*V8uJ;T9d&ec-A=g%NrEVgwcN0lxC<$`Ir}`Z%_e!j4-Y0QK5gG@N*2bjceX2^fon01rtV{oZ@E`x~x6~4CA2Fou;1BcK=Oe;j z4B$V}J|7cyhr+sPA0b~va@Y1T%z8>t!q2piOXyUOO}Kr6ma=V|OAps0G#I{5*;S&A zjf+`njC#1A9Vs-E!NiRJdLHJWcONEH4EN>3l^O|v%`_IPjfYr7Peqj_3*Zgi`#3f9 z2Y#*qAxtSGz_UlaN$sc9P>f-z4ypg(yil7&N*~42FX#Bk(lzKn$Hnf)HyByH`5RJ_9M0rY z6fZGVkYspZULa6s*I0G{KL)WlgUeqC;d1MgDCaJ*{V^Dw%VS}l#slB3S=0PFU9nYn%waf~;qNHF9$0 zov|1GkI)nsO#M#ttkXO_y*x)VPbKq&?En+8)_4n`J{PgIV=2c-m4n`Q8-Ifkj#75N zxYEI&4P5Sp+Om`7s3d{Cqo!polVs9{?t4#!(jFB;c^s9jvG;0PiNKr z!BZ(-3-aqF-?{0p^+NZ@H?nv0GT|N$A9fuD`i!qZY4!ICY-gRd9UprGu^q&QgkQOj zC%lmF1vxDI#X9F!;d8Yc-My(#)M~DXW_8Bv1lG$yj0qWxOp5k)x$8VZEJ5DUgA>Mz z=3cT~k#Ue+6DFGtS|Hovh&1eUz2O3O2(p*C50KpWnlW&88(5oQjtWH4MJLdPc4=MBj3a#zBP5OYK z(LW+Fi+8!g4Y_(Mo~7pq`9qMUA=}IQ33m=q=5dIRyEwNoH`;ort8a~eF&Yv`?oKkl zhRn6(!y6EA#s3nepBK=Nz{>-Ck<8RltHKXUFn=Q;(w~1I-+h>@A@{||qwVgEcs~*` zOb{I~c^*Eh48}uVq3aeYb(}ZePJmeEMh=p#@f|5*;BIM$jIkQV@>eB)A(Ulf%E3x= z3`Xfpg-zkXS94G}g%Q1};Yi*Z-!KYG&TIS@H{WUU2G1aQIwi2H{ zgH|WdB-+UFD}dyqbp?$dHT6PrYL0n_X+vS~g^buMk~|hDJN0Vw1cO?(LbsAJqlD@`2p>HG3ORs9CAg z5^b%kn5)cV*`>9vCOPx2U#I6-rwho-x8&atvW^gG@BBJlL-PLw9C$iDvwx8NTGIJO zsbtTq({&`C5@hCKdH6e4!R&!$4g5|MGM|tjQUmu21a-XZY6|v=`w+?7#S0rVO}*r@ zSi@D0%ow(H<2Fq_Q&Y^ROc+cRrF$h`WC5=;r7U>|3;1DE$d7tsf6vr3^Lv6yQu~^_ z@x$}9@Ky}RxSD0=Ab#-NgC8~YO7hF4W|5Y_S5pjEIlTOW%S?bUQ`4s;e?xK|p(&)y zXf&t;mzK>$rtuTh2c`FuD`U+LOyOli2jlyaz2vboERCW<6 z`zNM+#+0(;^Q^3sUs+M!)bvtTiucZ%V$7#A=ZZ8Ra#gW1$?KEMXP9Qn2geUeAI!uX zn7EONbt2P?ihYd99ZcreIZtgIp~-(_@?A_GisVHMS1OZ#X5y7hEKB~4!YzC!PoH7o zZY26dq9elH#N>J=^K0lMtf8QH9|435j+kB`Umzw$!ai<`5AZU$MhkLRldH8(rkz zo(S_MYuJG^fqH}1lOtIk)^GY#m_`nxf&1Z>xV%V%F(ftEY^?=Sm9|<~q`~^1vgD2; z#0fPf7N277IZDMrO1(Do5G@cB&^1G31?j6}ZJFLokEO=%0ny(L-II*Qf)OI{L5#q^ z+ZA~veizbEkR-ARS`_z<`>MgtJNAFyV8yw3-2IK&1?E~-5A&bNK~8M%$K2m*PKNAK z_!7TxA>RzLSGXPrv<07Pm4_fBwT*cj^#R=FS!7!QI%usFuC?#7RVZYR0*L z)SpOPtjw52)={CQ3%3y!-oHS2+g`{I(YP_9@scdjq9{rI4`9wSHK#xAndlcTu`?ysH3!8=r?ZaN84E7E$Mf?XM@*pK}H|pK8j9uJGTNi%AL( z;K3vS=4!xp7jTmXe69hiSB)@yY<`YhCqHZSPiZ&gVBj--0CycYo9d6EdOa?`Lc);V zx)zM^){=`2c}3dDrlKy65p^p?ZT-9%QN6XOiy#X5*v1Y8{-ZRrz2hAXH1{pbGsX9c zpHS7@<9hR`Vjfk*JX2gR&lK}hMRuxPZp9EfhvYAj|z$y)vO5JN!iQt z7`%agD|qs=z4`>r&;NSzQyADsD6}h%ALH$4lybDq>h-*TH;LgCUQ%SGhr`UUwyd$ltReB7>nIE7#jKY(R zaALSnQ`$0yh6g=teeO};)QqcX@H8GW<;fA6HxI<*+=|=^8ZHQlYG^y0lKu^<#^pS5 z)dVqH5Q`2*TuHfTxy)k`{Y%A@rU&gznez1jf;fxJ2nehgHmKEPb50G2E4z{Qa4n5D zhlta@=lIG)w*cC4n*FW>zEfyD$iC%IYMMM!)u24a*0NN31a&48~7vsTR z6h5uzZp0YDM@VG9wjIYm<2UK275?4 zPs~isgh04F=J6ljh{m=1c&ZOkz2D;k9Y?6oy zJQ*9DT}A)6F18gIO|J971!FOEQlBs~y~|0kAVcw1=~j*+FQ#-I`6v~47)uddh{7-y z!`&48R)2M&AtN(Ava?9`YXiV@s>MEOhMgfTkzWuQ7=onJwY%fh@x-qZJnJG>O(ERy zo=x0?g3E4>R}M_yB6#U(+*2Wj{~YpPAo#rI_|GMNsNko^;7#j%9`Rj>FPojG8&b#b zu8)M~53H~w^Rp=gKE-G0Za|(-8N5=$k>PR*=5@_Emz;jLT|l-)L$e2>BBCj!zbs!w`xoeU@*x0>U=r^Ukk`|>N2vf5rS&HRH4v=299sd5$33~ zNeUZWhh0wca+1%fUWl~JO*w-!#T6p{U%;C-D+vB?ee+qZY zy0ANBXJ{YHAUa)4WiI1wak{Je7NURV5y?Q1f#MEP1W`)_PJa_qvM(LOO#yEr*c|m2 zM+@{>AB`D+@6+~B(0{z8lFmy#4s^-{U5Gayn(VnY8E=`ID8mon~ zj?3X2o^LP_RZNy+H9nmxq7ORA<8<6)g?p)64`)_nPHYOXlzj4XgP!a1H7xX{w~qs% zzjYEWv4jC_S7BEKAmjb{1g#K|ucH*`gM|8;?W;IA6FGvO3$$d?bC*^6sE%LLe)90E ztuJGB+Rx;|Vkr0H2WjQfjzIb(lSzWk-uWcz;EVTJsdLy zy#r{+Ont3K6WM<#xvnD_W?MQZEn}t zxkeS~4({57q_ftGuI+d>g~;-7&v!h>X*XcAz@PVbO>dnV67(*h-Mq(kZ9JiDze;wm zYb%uJHQ2~t@m?2F!Q_}8SB}w_Xr(agaW+jb>qO5ic>rK?6SMleW(j(%&#dTu!W-K> z0AxyKEzN94aRI5svZ!KkZxHu8HVmAGBj%bC`r2GmBFWO9b!f5%LI7h+j#qO}1hJ(X z59eDH!8|CU=j+A;chMMz1q3?>_ufB(S|?b z{Y`HzIbH@wOw0@P5kh^H|6kqkTPzWD8PHB-nZmb9vmws>fW=!VoEu8M2(wB#n-UuB zBvT`{lD1zHmHUoxR0=vHR;BUFHgf*V6O(QnCl}u6`Bm_nG@i{L>RMyrIpPE(;cH5G z0Tk{`$B(#A5R1s^mX&bKq)cz7Gx8>m_k4X~9mP%*?o4z)sv#%@jX9SLz&JknSZs5? zt*0#Xf&Vb(PI7jmcsEP&O(qGuNb)CkKTJ_SD8eyGNTBegT(WShkWJc;LF-hZ6yLnS z9}Rm+_&5pO&i5CBDhZN3f*^i|d#FF!85(!-`VZ1gC7rwMnu&UboUxuY5IaU=xkr$K z->QFG5#rlF*+;S?Nj9gNp@chba9m%LnK;=`l0=fo(?ojEV{m^G_dT|+kWVCmi9k{p zkHsA<3g!~QjLy&jAfPh{!md=zXuB=N3?#-BXgpTm+|0HoR!)AJBGrz-fWuF97^!}Y zQidsbk)VeqrY?6O&3mNr71%-!sU)j{UInyMVD@QF-DHS(3)7~)m?O`)ba-R~$E4q3 z5fe(&Aq{VIn(AY)h&m68+VBsWGMuL9Q-!Hkq!v4(4woV57DKQ~6Hq=R97_p*$-YNk z&74=)>#;KRV;j`{F^4&!G>9(zmu*5x ziaZOM7~?)x z2N|~?zk|A5l-jXZ*Mxi*2rY}5J+c&vcYAz;aojezlq;08J@Xg%1_9kTT} zgrD8g8}A7oLsxyd%XN0kLi)pK9ZTd|jYNM0uv_Y967`se%5a6BZisjYT&Cf?2DyOq zcvF05ll2N8YxF~dblRvUi-4XNL1#?6m_mAZb|=gChkj&|MrNb@W1o9<`YF#M`J86+ zPS**DxDo^u7bR~)Fi--A%0~JWs(uR8h!TB&2O{hoPnzIwGx$-OU%YDaf4Sse<2|VY z<;hP@lMEO;&azW1p+EMPDXCS*ieIyP* zJX2*w$ASfkanPC!=Q|7Q?X=cHT-5POpdWLM(qL%el|+Z_l!Mv6O3@yO@gP}Sn(i)| zm_MM30KS*ezK`~%vqa+!W}svQtdVb=V8Bumf@uP$`xTJ}wu$Sj(X+u`_2sSDamAw` z0+umnfIZT@NWC5;W#*SvNKyt1@|@5m-+;isVgsr2bSuwppqo+I0T5K^S4=hJ>MRd( zkO}7;WWufNCJtdjC5vzCju;b|b-e%yzg*CpE1gK#IEX4ak{e?x0;f5MS_knl^N80{ z9K<>Y@rp)dJBZ~D;$e;G?jRm?5OVKYS)j$fMDaD>3Q2H?W;sNch))B@H-M<5A+v~7 z>v|b;FLJ1k2bEjjV~cV-h*6YQ>1>o(08v9HBMN(d_DPM!{lj`Sc0mHdUX53=@l_7{h+b~SC- zvAv14Z}&Xd+E+=rN>e)4GDysPu!X!%vlpkFB|doFQMiRXQM1c|6>AvZsrk%-P1P_~ zzIPqixf;e7YhH0+CuwI|mjyn;b2n_Gf+z>R z@3Y*&^FCd`_{h&=4vd@Nu$504&39lQYZ%`%Ds^CdKLN7e!;3Xi-8z8jNDy4<5IjHv zw2;+Cdk1LZ8$hQ!1T#S3R7Fe=Wuc@ND+S@+>Z5oH=kUT=3i*LSH)0#WIOQjOkX{Yx z5hs+U`}vVnT}frOa=C+Z_(>#j1pP#keOpBk*OyQ$LGxRlpQfHPpJ^IdyC4m>2o`YG zCEe&=k}LxW!P~Lh%6|_aN1AY|OZW!~Bb4QKlKTj{Q9!<}1A$H=)VF$gY^tMB&|`p> zuG7tqfR82@)_!z$xO#)i%IAx|l*ssxpIW9ot4|^R4b@kfKCWa9kvM&T{n#dYVs1;a z{b{z?-jzazQAk;yjJ|C|hZ9!?`CcY_kg%gBgym!8eI_gzI-@kf|Mn$#z2!4+4@2m@ zUO#q^zCT632G+)D6U{dLS!h*}U1xou$yl8oDnICuNx$5*7Cut__}AaGI|H`W>y@rS zlzS;n!gWZ_Qs*fLKqh-ZE?o}kP9WW!>MX_=BlbWo zxXW-*%oQr&T?Fd|RD@#8lJxOpdk6T&Y58i>V9>d{1K!rGC=tf$^*r}~Di}B{dgq=3-vNemDWwzX zbtxO01l;&Jz-}o!`ITi7W8g$`*OH9fufi7o=N;}tmYG8#TOnklS-)n+PApveTonVn zY@SaQg^mh$TTQ?h6O1~*htu4`zK{&32u5x^lLBp*1WGATK@R}hi5EE*s5P@9yT_1+@t%N4~MFNi!&4O+G@Q+}=^IvjGCXuNj=m zd=zO4HiM$)G*^$Hukz{fZE`w!VE-zogZiRWApSozJ95fX4yooLK*L9=oAxzrc4pF` z=w_PiofrD>4kP7wg=*cys|Of3q5Y>4)Bf{n%;+al7+$YQ<{jMW0W%j_Ojs`@bG(l^`Z?m9|hXUw2j6c z<>r*e3uM1R+k%dn4}rDh@nQDWzHyL$i%mvDY;WPywPep0_Q2dvFaqa040^31T~kz% zqMcR{^nn^T(F_c>;4AH~f(xW;HkI-9M#R48c#9IYf?TrTfnFC0dP~fNnDOD;DM#C)$=a73S#sKXhMu0D^k%!LVH)jdP*4RNZ{(X9$H|>fh~0n z(aDrH$9LF|+Yvx+AaeIcAiYqsN_XjSGv0oWH1Co|Z#<>Q{V;W~CoXyNtwxj2H8T^V0W@`lq@{x5iPZ?PkR9jnvRgBn5nu$Uq zrnBe9N%w68j|LcPYBPU9fPx!>jYsj+1HSywg0nDZ&QQztH|HRsYy1ehns*Rh&4{zN z6R#Zv4JNR^CFUJs%+8B`wkD=)mFeqT6m__dvS=gibEj$blu)8&AN(!g&%|D?v8MiK zdc1pyJym0Q<`9zM7Y6Sy#2h1-sv%x8ZLpY`<11f{%`;d`byEj2AI^06HxljsP%@nl z;UKUF_zCbrah$zD69lz(G*%A#AH+VZu@hr#Yar%s!BmA@+X4^lOhlzY%bH$zjhB%> zNjyapPXjToWsZwZly!y8#c+j_;RB>Q(W8?p$giIB{P!Bjm$sceDx5Lk_vHJ@+@4@p zo_sUA=L6=xYI@9UHlAPCe4;TkVlWBBtk#&AzVW}+89p>&iY7oA1zN@=EuB|#r4;tV z%)Ph`Cd2G&0)*TvSmq zq{}UzxU@olex3l*!)@@79|vIE9O$$Jsv7r1bAZMzW}}32fYH&q@oXSSARv| zA|HG#;DJJ1>k{bigAM_-MbS=?-Q5Sz1Uy-8VCw6GriSnV70yJx@5_fiTF_)QzAKr~ zV9Ieyv;_GTO;+Sjor-Q4v7+I!z;-=*26s^uvF%%uKb~qocn<{rCER6cEEfFFM|lD% zAJ>%5qG*|3=a;IA`-S7|TZwnhYoGvNU(DM6**~D&sPM1w-klB(12IN>+Y2{`56aA9 zw(p0?3@&Pqvl}-w$;^({2WMskDL>Pc&1FVD&Rt2on;9>(U|%mbgK^&+K%rlL3)V3Y zvb^dl$rg7@g6aT!Pse7T%jDzNGpR)%01VwM2LO}RF?;^TQ{=MD+=k*CS8@|Y?coY& z2Lb;HQV0AQ!QBOH`@nn!1+O~sCG{_S;HL@hD9hFBePBM58~%rYU-p4#5Zp9C$c&>SkLlx|+kRMwnR{30+Cuv{#=;nhi+*{adec)RN&Jyr?ADB;~ zg^v;ND?acTf{zvOVjp-gz!-Z4Ca0RJdn>bnueV8aP~hBtC4_i8YP#T;vrV5DF*{Ll z6eP7%05bNO#(+**4>I4@nr4vNc^&aP-v!R?;4v*pMcOSX5RD-Ks@p-|Pu@Wh-6^7^3Lh`{7DUR42@qqBIHZOI zwD%o?q`}YET}i=J7^L$-a54>iFrV!A$n)bVM@LJ&z`U%uqs)*PZa-~jHiJSHYITHc)T>2Y)6{3wJlaJR^ag45oKNg2 z-|P5D(9Z(x*kiM^fl}$Dtw?A7stDA!@MUi?MNS2elf7J5oS-iBiF32ZS7JS@mQX|% ztuomw=y%p7KReD6^emuVXB|QJup2Qwdqv=>06e7^AKcsU(wWO1 z*fJPEH*#*I#xN5VX=j5L zr)IO&C%Xs>JPCZ1YXtE{*A(ZW(E4dpc*rGs3*d=G-^kddy@qq&JbD@6fugM9vq1l6 zl9+B0emdX@xXQXBuuDU4CNu}oq(W|4eypLd5!#()!~xf98W@KL8AI21=*)?4Az$kQ z7XkxUF_dN+BE$p6?E{XKeCHD=1Nlr1814cr4LHXEU@a}DFR~hrSA%~M=36`zp7={p z-8J}MG2ld%qQMt=;KrP~FCi#N{jgUAjq^|t6i}aQ@W~ns7q0+0JfBJc);^?}{)*YW zs2T!Fs)w-bDgt{GiDyZpCT}G^SMW05k(qTx;B!CCHqsp4gr+PoLaSRNq(B>l0< zukH!IsO`jmBzR9TH=baz>FBezDv33$A(;b+P81ai~$_`f8)4!A>uuhC%SW{_X} zPKv+Q6OZy|^OxtR*+rVuJsSLkI|2u20vfUrRMnXC1AgK?#_P4Z?-RrdkbOonyn9N3 zU#|?(qQE3 zdZwIm{FycsiVanm{=}u^}_4W`G-5G?z=J4i;w;gPKes!#OSVYQglZ+ z5ZxAT5&bfp9Q`bu65SMT8T~Mv8r=|X6@7 z>}uad%JqYDvt=$+!R5bAw^#|4ze4OoRN&XgrM5tSSc+879+=}cG0l|l+% zY}$xQ_*_p$B4EAihHzWYdc{O;a#b77sCBu?x&Z|}49KYOiZ8(OU z_#`1-^^U z$_!1J3I7??W%dM($|TBKC09Hd+!UJ!Z(wlN6&jcA@m+2op>an8chOr}ak>NieHQ6q~Os@`sdyJ(J>krBA=Eae5jhWzTf6iT7# z^>}hwCY(p1lj2%l{yeOrG>)mqvySw5b)5{14o)}t;J!4wO2-V>2ns^)RE%Xwe6EwJ z#$m_9F`&UQVBHMlm0JfJCCAPd=0QS^5g{2W%?J@+q{_9Rb{NBUx??ahBeFL5yoY+? zZ6(m4h?|KP>*BVHD=-_HX+|?_1ysBak!H4Y5SLhSc7ui5>=#W1L)|2ERE2 zwk@PvLOL{G1c5Yhrl7wi*&HDoqQ+1uns7(PP9momWH$5RqP`<)v_TzUL!)0L zDmcO~;CoW>aVqTfs-LEViZc(qt^5!5@iwXOQj9?^n;CoeAr&j6dWunQ0WmHFCY*!U+Y2CURTM z1P@g&g`ciYxCzt<%i}Ps;LhC9=J!zs-xdDW2pa-&D~ zJ<=p|UY4h|zTy)vW`~ba^R^=g~V*elSEIZb40NKm}{819qi+f*XI z_fyG!y|Cx0sVp#eX;M(c@wp(1avfrG3Pm1v^lFo;L zq?;COL}U=3V(|6tk%@yM(oo8kDPRB2vd9bSoD1lEfZ*O*ETpU590G|`1hp0@lj{aF z)6PJL!9fkmJO~-#AVb)J;GcCps}|mEMDf1lHDTznw;@Cu^zVw;?gX zb2`zzfo`0JcFqYNfwmE7y4rgaOkzvm${b6kpMH(?ajI*Yptl0;m}XCcd{4Sud$OGD z?%_89Jq!>sdLyG{EeBgt@PfM2lcpeuyQWsD(it^dsB-7Y`C2M>4y%Yg9r*;bOliTNcen>|6ay$8T0#8s)Ld+?8> zO=psgb`w`Isf}jXr^;s#vFjVxFuU>bc%% z*qecJM8l4edn3LN#4RYv;cWXF=EYorqED!R1g6}&vRDLwci5fsp(*-d2N zejJt?cKEz@PFgS;sp+cRyl@H1Z;O<@wk6j_#c#$I1e4g3YriFUV+-Doe;(>(P=#Ke zGe_^I_SQ@A78@fPvWPaqTgl;*?CT*%*7jh#HZabg5s2~)L4ZkjGUAj7dKB~QkT?_; ziZ{pDnN4zl55x3R_cais>&_wOIO#L>6E>WFVr}D4?Tx%C-Vl9H#BtYIuIfN`bU@N@ zv)<^s#_@&DqL*LKb7d3Yq4|Q*uAXY2i>Aq3ZsCo_I7A;#RgNEcheC3=(C$cT?Po2e z!754)-)R4ZnUH}?j6|x6IrsdI6C@dVK<}7zv>i2CK&*$TZX+G)SC`}06RDbM-W$Ki z)#O$jNA{BkY2!c=Vq&%NAYLX_28>F5Gqd`grs?BFS+EwB2(iW~8(ozuH;dbSsoh)! z;`&|4bVW*)o5t+~k4%I+vANvDW~$shZhy+jl%C5vyW3Kqbbr_(hC0j3JaU4eO<#=dbqR=u`M}F)->>#LI1sDH5)VSv zlNo|%6PrjwpSc2x?9VxCijjK)DLG7F3yVtB@gOCqvXl-wap)|T>CGBCEQ>u$Det8) zxj&MHfbulOdzk*IL>qHhjFdcwRlt$6zsQ}ke4jQChRw|vIhZ9fWMXW2WTGGPq&f16 z{6k8s<8*DK9fX;VAy%omn?alKpNgGd;WuX}KRdQ7IEiZ-n@(@yF*>b8jFn3uKo6ey zpo)EhwsI+<#z|Hw-vq!f`WiLv&@ETNwJw#eL5`nfmj68`Tg_Yf65Dl?J;&~t>f>4Y z1+82FQH>j$`A}I`CI~|vmUbKV>OPXqcWOx12QC&vl4>|%i|KfU&*}G^l?VZvUM^BK z>&oVYqXX9RWlsM$ra@kRYv!hhFi58PAI30bp__B+mhN29r}64Wr?rzi7FlbgI|LL* z7g-Cy#tz0I>&Lj%a38dzhLYJiS);Lzsv_>U9m3lEbUq)xiOpWLlTX3R3`T98)2%d7 z(AG!28^hh`_U3%eVT7Nuij-gbDD$N7j1TkxMen?ccwLO{jea_IaitwYS$K4~&8c4G zLb65RoN5U+p&4QzQkChjA$SlMOQskCE;#08ncIS|F9W!GeF@~bp!q}d-o@(D`?gFz*UCI+0&QaD~nUD zJNaA&iXaP}N%|~aS&>cvI(YReG?;EK)`X!prf@P(%EYmj%WX+G<1XR?Lb|@&dRB5c-%bUs;)Vt`&A4@zpf0CS68Y^v-EIkR zQ1L5HLB?kL4A~P1Duu34O$3coz9JL7S(d_l+W)Z_XXVzNbvn!R37i6h&Xcu%$%%jp zJ0Nd3@S3HLYs%lGQ0i50=#@fgXc8Bb?K5CkP^9`ZHQDCzAHs3lw<(m#b|zu!68yz1 zMVUfTD3p2@N_UJ6I34~P(Gye+?2sGL$mlgg72Pbt`i{ivKLptAV+%pe0T5fVbab42 zv8edz=tXbaCr_5Tm~{^8;$i9uY$N^e(=lh)W`Ihq!Sq(<0(y-$IW!xdjxIMVj9e4T zDf+HeoU-DP0dF7<_n9Tkf$H7$u`*IaWsqUx^cV(Y)ogY}Ob*4=#5F4>7|v0}S`6EA zENbyEH18$0dwOF0hNgz@CpJlAhv){*EQYbgGkb4Uc`?UA`F^1-qwkWcY@Av^!-kkc z9vAL{as3?Q+}VueabkF|`UV#;Lp|G6W89Mz6=9USi?Qh*b}_M6YOFENm$9da9j&qX zF{VFF48N2{XC7-hn`pbE#?W-^&T7-Q?S$#mc+Ng%f+wa2!-LdO+H{|BFHzKcj9b@q zQ@qTpTwnAg6+AhML@B6bsTJ`iGPbzLhlwt7bk>~kWC&TmJePU0o^nxMJ> zq)u0)mAuWE7wx>`(r)7_S?VJ862W~pa%8K!UBoX$Y~}b*h8pNe^j8{KWJ}Et#AV=P zXBkbfk8v?A&3YPatAm-guF}e0H;p}MG#9V*sRT||Az?T9-SLOVy0Z^ zFJ^Y5clx+yR3?yPP5Y2mYwp&9E)r#EHN!=WAcE()n$O^(=2g832Db^|&{Q(e%awWt zrCwvCW+1mto64n5|3bc;H9=cfFFnAaI--IkGg_{XZgA`@K>q<@n9(`Qrxj^?zLJ@u zL*gi9UlWMKh^Cn)K1DYw7|=;V?c&Cm*L#Q4*|46*S}#R5nHjrRHqX#Z>KRSh7!Ck* zgRL-GLR0PjOuFh;VM*e2}sw#w9oGydO-1FlCTy-7Y38y(dU!8P7 zClT+Jk+C~Y&4}@YWF}rsi2>5h;g+gKfO;oEdj>OpHu_Gs4N%XzQqgK1grFOLmM&P& z5j+kxr&)T%r&10Q!^6Bwn-dcc#N7uYQWYD0M+_JB(?M7)jh>Sqlk<5#eNv3oDno}X z$|hY^qik4j)78!Fr5Od)%EYt~$hAsBaGpny;*%iXPFt7C>*<09mi;1)!1D@;A^BGSn5gPdx` zC#%gwW_R}MZe-@^$mAF_S&y;g^qu;G68=LZt|H!xM9Ec2y}MKumSI_I*Q%pv6|V}X z-!s%vE`o3I*~7Flj=neu+Gv{IIXn1r6s&T*8E!@I>}Dkp@AM~gyu;k55o3C=*Llu% z+zK}|>x=dXl>g=nX~Vdvggxt${mEEPmK#DJ`3bD$_ei4K5~ zm7$`z?9LrZ$cNYI`BSS}!fP-J)@EWtnBq3#QX1K0#$Xp;EBl#oG9h0CWMU;c#jtwq zzsHLB#QDEiRxF5sg-Z!8tJhC>tf=D|YDg?AdYlxe14cA7=GdDt$-Mdt);Zk_ggY@x z*6|p)M9D<@`>P+Mq!D5btx)xJq|_s8>Lt$8bT!q`20|YO)Db9H5jBaT7Ko_4?C2=W zAMsIY?7dBsNpc-X8mDD>i~_wtphMJGsDYTpu%Kkeg-)_D2*lJ2PtnOx@i zqL5{&Wt5c~l3Ww!IE2+IzbtU&rwCQ?%e6GO2o(A>TmvjLt0{6r=cR(tS1lOhXZeo6 zT~F>|9*vLv2BLa-C?4fXkFG&nH0IQQf`XsD1xh#7N&I0pE!P>K7sybv(1YOeod({* z{8l@h7b<@ps}o}FO%%EX%Muf5t_NBJ5Z0V99-1eu)EF(I-W4(06)~M6?vD{6py@sl z{^oIgwS}fke`?BYTORI0^s&wbGLa8$MG2+mKm^V>O`^@UYaN>fb)=(k9)<{PoH4vC zt--(yKRAvAfNO>kiurLjGvhpwY7Q3NPRwS(C{)0>{JU*hfiY&i&4IGst2M;)Nc=R2 zacZeC=hjW|_QcJISswZ`+M(Lrz;#gC%UJEjrFQYv_+q7piHY0FTIKl#EMW=)$_q%~Y zNc3(G_nx+ftszW`BqEnipbT=MtV@92M%r#J6f2~JPU{G0iVHmxP`O6Lc<)ZyaTV>* zXSk$1Nv?}p(B}XxF^KZC`$;_vwA+XrOHAHP2}gm%iH7%HbGQYS;o~-*v`Rk%6MqDa z)tbdBokh65Fz|0$2>*-raRE|c0Y2-!^^>3m&i##WCdB_GhV59no^$$aO9-iTK?s#rOM{6yvI6-S&ctUgp>5KLjcjQoHqk712V4^jqHrfZs z#KMkR*qj(tYG@H{So%Gxz$T;G2t7A?i7T`Pg|?63q{hUefsV$bW02IC$0Z5zgKzJV4l ziY^jgx-`(l$BHTauw`6;!CQ{EYKA2OEmgg!EgZ`AIHf-6^J)g zV>Jonx^Q3B_+gb3+=3noez$6L!{CO~CiW>-qoNPWBJ$M!?D1JY$jTo&!2M8 z|D)~55a5^^9{0me0S0bwQ1Px^V8^+*#_Yzz8g&e3?u{dB@V!-8;Jy!>x>rrgXF=)I zy|J!&f_exj$2^lUt28a3>z=MW>nI{bWhG9;wt*R*8{Q?ssUVQr)f2kaQ@8}hz8zHd ztudtUle8;kv5{pQ_wwX?KxE@i%E?lnVPqXt+p!=L<%NvK;~$Y^t0Acc((VcQcuq`p z#r(^UZiYivuP;4(E}5PO_;a<6cE0YMN3jsFyod z9@!R>ouZ`;VZIK!O9(2sgn`pUUjHUsZG;O=eD%HnCNC}ZRqIMRa4`(nChch zP={QW;4)_sDabGHc$u&5%!&%&JO0V4k zsnQszXF088OYoRy!5-2)Ng95Y{@J0UM*Cd&-SfoH^uz;o0QuVNJ3Oc;ptY`n;0PCqP>CXQ`kXxy5k~(=ZImq zjY;JYG`99dUrSaRBv8!kox}c%a1_Dw^e32g=rB8#OzB{9uUX&%Zc$e$_gtH;F1>BId8>yV$armbN?E>|%#)TbEriO{_q z{^><&IeV00&K|X=;0*P;L&s;Xq8RT=Mi0XeCst$$L0odU&n0GkTYXJ)hN{sVO*vZ! zTx7WGGK1+2hyj_iXk7vlc*p6q1SoGQVG+%8isd?v@8L{9O+?P* z9HWZCRS_8Rmg_73df+f49gCku1C4YnG2m7+W5Ppj!$)N^6CK&ZsqIR2ikOZOHCJlf zAb6fZuw1tg`2y=6>RWORzp0PSQ*Gh>Hife(m24<(YR-a@yhQyY;|cS_WbL}kVQGSw1e zZ?tuOF0U3YI-__Px`NzCnBG%-xQNa~4%eV1jb4|Z%g@UTFChs(R4*D-yvL9vs)ZyO zo1gnI5q*kJKwF;s0LilrNs=lgNx%HuM+rWh1P?KV>xq!9%y6_KZ!C%ewyKq2biJQ5e>(>0{{#wtdXO0D z>OQ4-Ke5lbt znbDK3m1smu)BYjtNQ0*PCq;Aw9fqS=LYK8RgBnEC{?7%)r4z0X8dQ$tSEI1DCO4AS z+4C`=gH$Urxu2~2sT!1seKCHZ_QYG|XJRsIRgMNPTg=u_YM(@8E|20{k$y~@sRrAw zdd$MF{2EmO$I*GSfua;l!!>4t!Spr1XTA=~vI#1G&VDmBA4wxmqmg<~#omkwNPaE{ zD@9ioqhRaRQ#9~(0pCd*%12?yVpU#;6HFM|*9KMD?4m=r~m^^`VIeziZ~VB zPTwQndf93t}EZO;9D66X2iDoGKR9 zAk?>jAesfi8&O!Zx{JJcNO2%(Xf_@KH&(AUMt6$=6=`3uk%F-A>PsIYLg6g#QdpG> z5O~qd{M<7Bid+GFv|WDg-9qt0cTzl!B_xQc(=-J=wQI9~6P2|vq99fLsxF3B^$k^5 z1ah|eeJWSTg*THUFrKF9qKNTE|NX_#b{_ktL!@-VIrRRmIv9vyynQNwU(P;v0Ez5OWRzqIHz ztMVKa6$KZdwC#5_qP3j+1&@|nmB-;PeX)s7evRmohFq(hNAa!7^MF$Y%sLj6{W4j|^>6_G zW%9V~V4f+mH;C*s36}XOVrFu)j<8NEXuS0Jj;N(L3E^>`ul28A}>| zEectc5d^*t#V^6ld@cP|q-=ycHhR6?Mp%tfU4y`n;u;R6K4Ax0F|vx=`UvDT!d=C@ zjX(ub6YyK{A#(eEF%a?()^MyE4q9zIRjJhw0yRt?gJ?vPr42ZN2H@Se zdUX~IQ1V7O*X?P9n4<=GmTcPQ3Q^SQ5w-S+?g5c{3S(FG82;F*Hw%1;6iP-fhQ|o} zjrK$qPPEDo??T9HppkG4Smoy<46Mr5UE%*C?*424t0}0^Nc+8rjzhA>5r4F&`X{LA z$a!o*#fLnTfLt=qhk-^~K4>k(>`H(M0NVLt-+HmHEm{_)N)ifS!6J=rQhR@&q@h!t~}czhvh zS*H0evLX+-G^HL*0cq~gG#8>FI)L{MS-@AX)f+}|d9FPHu2A6=dm9(xP2@98NypJJ6KBHvaeuPpKf%@@L1 zrBXnP#Xm75Ey9L(LcL$Q!f>y zuxFhtR;jZoH<_FXlsj6>&9KUIkg_TtWalE%4=2q&?7vewvP?Obd2*gZ#ZhkptzN?) zJDzfKIjXSAr%PsUY~@J$m{c!#lGGcpLF{Vp$-9&Ct|eud@>cW!cS%F%qA6&blN?DA z;x9LnB*)Itq$;%@_Da}QDL&$)dXcspWnHdiRo^ZFqMa;gr?FX}7&v3rW3Cqz(dq!ACo zrD}lbpZgYR%9YgZVVEy)3|1|$S5leXyAT|bQ^~We4=J83P>Uf0265;} zzrBg7pa;A^!cvYWr@RlUVn0=t`nRE~QZD4 z@#++$?NPM5q@k--o`8_GDzgy=+PF@%>np4f**!JQ7_0mrXtD8GhE$Q?fkM|obNj#$ z`vAIsNE&NJ6jMU;iO|%lUN8o_dvQylMXNHV^vNTtp1{p$bJZpIZ9k<+ zhvA7QS89<*cpnJ|lW?Xcyv&MRV1G-YQ>#C@JnGex`%sR2wNug{v@EQ^@(`e@v5~ZIxFb1@h;#2SC0ZrG$8d zXXlZ;AIY!R_5t+T$kQz-f21Hr{R>p~E)DK&m2c9izEkf<_hawZ-YcQZxC*pUsqYj@d1Sf->_mE?i zDZlH~TKtQuwc5+VtIWdF>#0}XvXV*rsDC??c0n%ydLpL{^F}TQ=W-neYsh&uIrTd% z!{u@_gIr5w5J+zO7OqweLI+l?e8@8-hVBj0WqCq|6&~wpc$3Iho{;IEvx#}$FRG22 z^u2T;s}+yu*d?fx@YGDJd?s3NtMV%Tmg+Yibn2h@0~6RD!*wcE#;?+$^^n*R=vSPn z{K(Zk8-MIzA3X>mSSHqK&A1 zacb306wTjUtSM>eSae?T>AK`T2NE+FLb6J1bJdlvk-g6ha-JwW=qCswout ztY+wBMeavRyx+l!lxb#!Mj?ny_@M)@RpVIEbzpWVOd;ee$g-zsF)gh~P_sJWGQriW z)>G+ESevm2Yw8rMJXr=P=i{%=PYXxgypc^8$^4nkvvKuwS5U|J5PJ)0#o0DR<&Xt#~p?|8 z5ma$BW`;0*E=-ppZB_DMrDi%6df+?5G+UV7N3U(4B1}@v%lBivTRZ{RZpiYw73l^X z_CsXdyJ)vn*@nN{=!J5tygw{1{s!Wmh)R^a=t!?9V z*X*sx>-^PIFR@d>^ZboLXiO0wRHSVsx}xI*0?XQ&`)@|KKx6O-2R&x3HcJd&BgWK9 z=aLE%`sXpiB7bAChyHmSzi9sFSQwyx770fm?H^e)uItVk0_9xpv`X&+fi9O9u-5}{ zUGy}~R(OpG=2?s+0A+AAxKjz(fX@?potFF<`pd~t~Ro! zQdal;T;`)i8Eh!H}iBxyI9(X!!YzZ6fWgHCVzAbKAh;#`1@Wtv%2oI_)Fv_kFf~SSxCZ@&S$snN9FWm-H zy5Wa?IdM3NiTN*5tVcaX$h{PjFG3iMR%9U3jNM9cNN@Zq-U-Je7wJLuBjg2D5enQF z79B(xtGhY|v80xP2;_BIhBM{b#*j2qu1!eWpSESzo)I;#BW+bq=0dC3{}}C_Lpk1v z?IWy^@UxpLH4KAosq9tijB#lEfHX2fUWQBQuEeN_H0LO<~+mNvFLb2G!`Y zCX394S7YL-=fbP8G!Z8Y53AKFYh31Yv5v%*huyD1$fx*WcNQbw6s1W>Gu&S1uk!0a zYE@o)Hrz%H0zbkIEq>aRH@%MISw5@s z6#;IKHHN<`I=;()+#ah{GMWKvHSLodMD2fLAPDbHv&xg;L94P6lNVYN6ieQQYF|!n z1kiZ7jarHTRBZsUCukYhS&@^Nl5p+kkk;ZQm12s>fTd&MM3Yw3(FcGcz~V z%ws(>3&5gohir8#|IEZ6dmWk|6zUAC{C5;;BHjh8cN)l({cS zMoKl+%bKc%+Pw`__mZkWs8*1w{5@>7T9p$Ck=|_t$Ps&AtVNi)!;f(*z?w!3_r99j z?_~MSUd@cxsuZp}t-~L9Uj4ZlKUT?)di5mBIuTX+V%TE;0M*D=wpIT39*8b!$gwH| zs5^L|s1Xd}INaQfT~x9K!s+TLX5kaqVXx4jDA%C8WrEtsL{N_!&+QI@TE4#6$U+g@P7D3t+KEUojo z#?*--8_@=<0*V~3MYgfZ&qa?=Ttxay@6}Uy6pM^#&FWJ-aGEK^#5Ym*dK&!9!%@sb z1gX?>tT~G)z9Yr|idGBRZ)HX5kV1~qseU%_Jnx|5Xwe>k?DsXHWkpsYMJu*0h_#|X z=d>Iwq8MlE3VAnU%*?mNOE4_o;M4thJ<0vA-8ADgiwC<1u;@ub zi3Nt<$l?TOrePaUuIhEPV3LL0Pw=ZRvVb*QX+NU?=*5cR%-CKG-{65XEAll{LQ(?~ zl-5N&!Qhrw?ekiE7~)x4&uxO>5T&2x=-Nck>oCK9NK3umD$m`|c=-VFB15r)B4t$$ zMNz`?I_NDZ?4X8GoeZJTYE`Kv5TH(4DXq^a3SSbO`Up*jZshi(+13)Q`Bb7nDb zGw{c*LdyrsZ?GcIF(n?mkJuaWhxtI(l>e5jAanHz?1kHqgpQh593B6H4%L%luhL=* zt?~&-73U)uO8`f+nxtNZfocjQ*e7eMn~FADmApR&W?lp;mis1%66!Ki4<>a-O?{&k ziDyceKh|zgxU*OJ3-`}wwTueMa;^Fp%SNgUlp^p13fx5_c|ZkupKe8#BL(Gkq~VKg zok&wnnnjvsgcT`g%3b4)qT<-wQ0KA6J7lkw4nccT_F8R|daDtYyoqx#WChhTlp)iF zl7^91B%gW`)O2l2C$)?f_&m}K(RxM|eO}xd6z6D)!&Esbjw3}UO>rvr%aFo~5aJG$ z|Im~f>QYjsk#bL>dJuEoPZk*X;US9zp};+M@=-I4RttjH@!f#y572;S);{kAMh z+D~bkGqC@qY2MN_omB(tVPR4&!ym>mD@&EohPz7$zv_l?yb8Pw%Bw(WFDG~Iy`t>_S5he@O^K1j zpwg1&dXn0xHK?DeJ0)Eql1fEV5NTz>SQvi`#jsN0j1mmn7{-&XBR2-sCwDsQ^!?FI z*fXVt+Nf$!qL>Y6Z3R2&gPOjbN+tbD(k~GDXQ{7zC8({+nLkjd zT4H#*Y8yMM&)E>nAU2RS-DfW<&iW$_*BER7*%bp47Y{DnIvQq3+7Gde67H_Bf6f=&Ld>cT`o4wrGPla7tq6LAbnm-;(8vHch!>8)aMBIXedATHgc6G z|AvW6JCM&NUqZOMdWHD>{M_4tFB&Y7KgE<&E#rzb^GVY?KbJZS$vr}IXR7JMq=t?| zGhkoytVEO9BE5-`b1Ff;ou}`LoWK(FAfTOn8v8qlLi@S#MYNw~JiLn&l{Zt!-%ADY zf}bf>1YfbIlv2^t%@Ls39;+%Q=&T zyqMoTEqoXA)>U$C9*w}>=^OmI2!fhQ!mKyYT14R9QukZn1r+h+Gju}|z6Dle5vD;^ zCxF1VyQtAmelN+FdgKFyd<6k~iLJabXU+VV{12$Cxx1P!IuORMFyXw`TmBxZK z;25hp26hnDbxp+A8P5*Z;(KV~ZIwp+v$8rT;(vuuE&j8YA*y6#LsIlL^*fh|e&(NK zlQ-NSNE@!xoZ&Qe8n8|Bc`YKCM1NrA%0(rK3(f{gtpN-Cgz;B8bJj;>;TH_4S3RL# z%>o5~tb_!0o&3m97qfmPB9b#ujU~df;+#h{8R4P7zeg+Hb_rN>{&)c;a~hJNpMC-G zz|%+tW+Sy1DRf{QZ~x;(QZ6RtFvOKW<5eetzCdUy`KO%an?i9|R8>5+1a<;a9gxC&F^vE*JP|27z~1d57z?L2 zsIzsVUY)KJN{!HoI(k4o1^>gF3F={;h*J^xAH%}F*z#*EtW&=}g`Wwa91jA-70!Xs z6o3-d`6T5SauA3iE=jebJ5k7QkShsXM+jFvxb_mn8DkD&3#E-<+D;JJHm{IGqIw?* z@*jb+U_{*LP`u|*R5Jm|kR1nQj1Uy=SHf4PcEL1$A~Fno>O7Q^_#mhg_3BieP->V? z)G>$cv|;gz$6uJkR5gkq=5YFYNhGOp?;t@_`-&lIp2_HEivedw2fZW~Bcm;~yd-so z$YVx-Cl$G)%O#PhzCnT+9V7 zu==ATVc(Ow(&*1uc?P>8ZABSkbRKW>%fPQ^-Cvpb^}6|mI~drMzrvq9N68hsdHk`S zSCXR>2$Y#$Y=$cWh2|Gx&b{KwcNLDj{*cF0@<}s!Wjy*w^xpb*bNpliANV*gRAF+8 z#|&|kxzJ*T{SdU=i$OcvkXG0prEi5mn8`mWstw!$tGZ8;hP9Q&Uuip@b@Gj@jj58? zwF|rw9%51`wVy-3H^XpdLgXG7ncKRZbi~uPf=Wx zxS|*1f=*~@D+0qcJA8r|A*UIb8)RyU6-Tk_f#o>iy_90hu9Lz<*o z%9s56E|xrROXDM3{APcj6jn70Ya-5q;nTu-xIy8buJlRZTToNRypfB-94jvhs;5ev zAdck}{<_^U`$qDo zYW~jTj~{s#3VCkyUC`gf<(n|RiVl3>GE67Kmy0By)5xG#F!@H)*YSYntN^Jx{{m4 zT%&ldXjra(qR5IsXQTK!0XL{x4NftN&*x7Tr&f#+ITc5!_*LW&ir>J^^+ENRX8Y_n z<}Ohk;7{+mKB;9ZZeu9m>q2*Ec_+opf*AR1xlBTNfrK(IBy$_i=?5`Zl5wQNxSmZa zBME0Jsnhv{I%Zgx+lW~Za4rhuUvqUEutbZjPt$3-_ZZglMB$DCNoKx3O3vioo<6t#zL$J z+~U|V-?%+B#QCdz23R~(Zox0d9oI5#+;JJwp#a@+B2z6+L296+(5bK;>7ksvknTcg$3aN_dVrMoAhnyR_N1&s3Y3FL`7@yj zguX|p6&jR>G{2My1<3U>Q}L9vRA46~wTP*t2vYY+ia}e>)E$50q|2Znem=mTy;*!W zFcp}9)K!uq@g+!D$T9U?;SjVrGpt*}@iB-yI0;~}mzGBVqM2a=LXw7o0n!_5?JZ;A>pOg3+ zdZ;Cx^bAwtq(_d-+pLe;+BQwcg5f zTqv>`tQ$!oCO?A|%!_Zvyj_coXCER`Jj)~3_Bmkj%!^QzXWotcDdwHYlz4U|Q=VtX z^QV~i52PIPa+!vC>tG&l2G{1LA_emvhbgZ2o`8=4yUj80FCxV}c~oIlgFg(v!!M_S z*@ASaLkSe{4sLDRGfeft!7}wIQ_?u!ixel~p?g_<*9ygWq-HX8B>8V(YJV@Jt`geN zO7>zm6DnREj}%Po@~F@3zjV9U_=xf9DA#Oxy&w)O;#Fx2`%{!eQVLQqr4tn#PG|rd z18OhE=ApK1;S^Ixos87iOtm-%sm+pNOZT3nSgop<3XtO!Nm0skOeGTbxX_VzAydic zB6TNI4a1QtWlB1Rn}seNuxT#r3Z{|?yO5~>x<)mQsU%9tXDUi5!vssK1~GLQ+ux&+ za&kA6P{~OLrX(k+OyztF$~dMvvKW5S?8yl_wZ=p&{ick6_XxqFQ% z$=!0MBzI3SB|08rN_5O;N^(4xsTR!LEEiV5l;k+fRDhBvF_natTb;wy_ssDbOi4hD zKnek|{~=#MJc&4N%-K#*SzrjlLI?5XtYdqzFpg+21Fat5Mi5I3bfip)j2}Ux{jig% zWcpzXQ=MKyY9mw9puWpg5<9E4Oi8!(B2$vTB}_^F9${)9gL(l|V)q?L!R`?c`|N&M z*S{kHlZJODky8I|rs>ClrEz1Z2aD=-3L3=FJ&CCtric#>W{TfEhmK>a7gKB5hqWDn zp9A38f{llFeW$ktyOsNwofQq{3ODL9>y*kZTaqW>>i4>gi@PocWRoWSI025~{AyS;N zgwD7WEdL*8Zvtoa*#3{tOmk|Q8fT(3s0?kBClpE|CK;wEr-%}dEDz%-Ds!x(nM{W= zb4($65M|AlEG0|KWNEXMb?j5Z{pnc7mMJv<_xrl;&vK?buiy9Yr8)QKzV_?hcgc^^ zYnw~9w$~OX+ga@P45Xv4%jImcm44{?42dG+2;W)K@dPM!iNKkGj%P@6?;wPr zK%Oh?Bv05|6t?|mEj?pEltUsZhOLz7v;PLPUanfdia61F8-b$r`((6K7`dtR6~5FJ zD;N@oE@4QL>OqFu(v5c^1noP~;g2(ne$P;Z?-N{Fay3Iz`YuBVmW*;0xZYFX3o39Z zz^n&o$uJU$B}XaIqWJ+!I9LIrIO4>Tz8<4*$mrWfoApem8PR5ZSk*Y$H>mq!)$#oXlN*O(zq1Z`K zglp@X3HN76y4IZ->L~ReLy|!03`vjcj~@||1o{CXC^wHza+T}ZN)qTA#7SOiAW#yh zE4^?RNTe)_a%=I0q>{X}l5E@D0hR7xNJfX%47H}3H%LhGKSD@Ip`XpLrN5rxw2~RO z0edR3+p#>2V5sy&gbEoFlLsp1T;{uz7%Np-K0{K2?9GsjMB59L6*;d)(3+;{2ZVlQ zPW_P~sphvZlvcqZU?Bj%@Kf5~^*&$@0H5%4&wPZQK?unrR=mcrwc>eVh!^HCBsSd0 zP$n~R88Nd<_GXioVC;po>>`HRP|LFkZ(Y)v@W}$F?@nash_4Ykh9OBB}sJB&TxEruJxlV@PPWG9;Oyfgx#_KN2Wuc{PI4@)CoRbXvYb zpu-Sa!jRBD$dJ(9B~a4NVMyfO$WXf2FHq7>V@POA7!ull3zW2{GbFSl7?PQYLWZP2 zHc;@$r7uImrZ(Z#=ZbXo;d@R9yVPUI7A0w0oZFnc3lRZLe zjM!J4likOxI`jWNCo95nmlbZ9uB^pH(zr4Ds5N1|6w>tvr?2r`RkUAphzX6B32{v1 za)x?sEHhf3tik=v`A`;1h|L3zhk_>OW;_4w%|+8c*agaKCv&lMSJB*zYaO{m%o%}d zO=5fU`J>|5xR{okQh~*9+^&@%Ru5uXEsinekyI_ROHfCoIjx8k&}BKCXlBfAsf(~F zj2>$S?ZSqeEuEJ+U#V=MNST3joL4oW=iab=#|L1s773!q$h)GFaqxRY8cF96V}g6-m^GsN*DHg7ab)9 z{6fG`1>_g^oI>_O@hbr`&q^2D``q=4b}TvxLCA2^h^&T}?%h1#Q+%152w5Fkhp;S; zCqnD(&JxAzg8cIWVz8EZHc=Cy#|d98*zR?sqJ0aIhXC7!W2Ht=kXDhBv_e$VSNOC5XOS3yIUK(%hG_vP%wNk90jJIkfI6&ic z<=((=a!=OGGeCq7a2kmSzW7o^Hdk;8wB_4EClWGVAntn?YzMIFYuSPNB;pJJjy!qM znbs_Kb~Zat0TC;c0nFjVY)5W*HmD!EQn>?1;nEVemtTkpN z|4sblxDwIpLm=Xw`*6g(Ot(D5?CZuX zNG|q`I*po4q$awLQ@q;^sOnt-j|ABDuCss*K~<=c+czWu=w_!IP~5a>7~@h4C>)^n z(uQ{NBcfIvp(Np%Khc-^(vO&XyT@xB#k__|OVLCmOVopia@`z`OIifzPxt7@lfE*A zUZO5U6d%bLi`6hcrwC{`S=+aP@PN0yd=^&Ah14ig=<<{o2G#wB9TCxO0>yFO)mK-d ze&@s`o)y{M(=z9h<^x5@b-j73$5Oy`0DEciB-28c*wKi_SFqA#ewT+i@``6TQqBJH zNnj_)I;`0OhfQETQt=>eUlDyTq3m&B?#kWQlPjR%0l8i(eg+5F50sBf$%50V{+ls9 zf#6)3f^`|Oe!}FVpJ?{Jah6)Jxts{^5CQiDCkMgJ`Pi0RhK6%P8is($GQ{Aw>|43{ ze*>Z10G(C41UYrEAJw4fa39_A!$bdtDnSR0FuNV6>0eOcmawVM5R2+ z;oS`^nb-g=I*k&YaCS<|>t0BB+)%;8RB~VFA*?1DRno5z#chB0(|6ExTJ{^J8kyg| zA$(&)#B4)7;oQP}uN4p-*~H$4=|?_@k`5$13ME;Fac=b%8|6MFvJU0Zt>Vu0VxQ7jsp5v)*w`Iz6?deE z#}-!}g|g<#4D>Y+6s+cmu6a(t7Xj=QEiS7=cN7u~(74IWdpv-Lz;d-+zZB)$WFT9( zEgB%$FZmT>Z0CcwI-?`AE{<~6jHe&9;UgMG(~8E4gbRU|3Vh1vaZ)Ofdr^27r`zU& znYj?=BA&sIG-xK{*G2KiN`>Z=VYUXaW2NkpIws6HoDp?f#n7JAS4txflskn2tj$8* zAfDfejT!;)!2pZnJeES0tt`Dk*bg(&V$R|b0e?e~d7WvJ2t7Je9E8yRl?ds5=NuKU zr~D0^suVdA?&q{zdw5Y$5;-SP0x!SU4nG(` z*!fV&-`My-ESL)PCQyz`LAkdy;8ko94CSYQzdF4!6}#d&r3m_NMl5R9h3ay!zv+^)qi|g1$Fm7JgkDs z;vXJX$t2|e-@_`c*kF8vxk*?V9JE*)MoYiEWBI|z>?LXWNa0tI37pp<5N;30pGH7H zXdui31U*WS9Mr{{j>1sMo0|yZ7#^@zWsjEQg<3G=oYZ7Ml2;-+Gj@>|IS!E?-;;@P zIxs?I_2mbfOy)5R-!LpLVZ&tp%D7+E07Y;MT~e$0nd-1YSutwr8( zFChxY??()4v%HduTxhcZZ0%Z7a5PY57S0W^7;cL~vF0nk`cFRug> zC28h6m-0p3z!8|Vj6Aca*b0-EVX%R`SFAzVdhj>?exmH7$J?DplGjhljx-(Vsw*SrAs5wjkd%w@>Kj=5%$#19L^qgKUbB6e&S z8q;4lR!fs2ufhI+c}p}WaxLXkC%VmvfW8DsniF@L1`5tBJ4kY`o!OGdP#@#eC;Es; zcaFU*XcqlfqaaL&VJzr@p@|uw3TFMCkYH;Y7Wu{&`~GCD`oAm8}cc+(684nU0v}P)zAQnd#{IFxl%% zD%h{;jf66vAP#sFrlU@;Vx7d-9qy(jbz8x?ken-<&J9=JltnFGhc4(qkjm+yFg$v} zwdioo#rumDrk;dt6xbZD&S_6zN2HTKE%5}>%M62xJgwmXANl5O^emhWsGJ~ga=3aJ z#**Qh$MF}rH`feDd2*gn==tI5{I-PFU=U9ZcY~cXPl34W|1$wT4TWLZ+A{G~$ziKt z@^pyODgIJ~NIDUu7;CHRlhk~q^0_t~KMEljy8yi)=Sap5;mAB(eHRLBxTcCjphW0^ z>w}(qk)FHB5uWB<{34-^zFCiC-ymOn#h$rib*K+?<9{4UNokn*0lrLMBn&XtL^I`D zG@VR(3EpBv7;8gm6~KB-BBBLmC-N0a;T*)>!Bnpby?q^QmK-lH=KX09i#dI_6ZHZ+ zVm{aaY;%1rkK|{VOwAOxkWF)zx^5VZQP&+M=4~)NnHjw-zK)j91uNWKtKM87cx%iW zil-aU7)&3@19HZUP@M~*^JWCiQAh@w%v)CG10OSt+%O`CfVwFzZC;KbRZKVMAwMJ! zj$A17)s>4s1eS&y_l}t#)qqW z5auN`bNN-h2hulO^T9sCot=3Uj4x^A;_t+s21Ue^q8zFi?(BiEdRUpMZ+&E%*P({F zihx9D`?bM*A}>FlD~v+Dsfr$(fQauXqKFWiDN1`l>vqJE(RHm(C^*AE4#LaC{s?iO|1ORFgLeU;h@G&qWG2 z#}a4A^Wu^_J2B(`*%dK5Vl36(uaV)`mA<$=AWl$lF6SC(-Y4DJh7JmSgIiaidbnmm zH{oLI&Od3+X%K2hNm4s^80zLz0T%*n^XUpOU!hr;M?{=`NU6u1a1~uI)~i%dZx^-qm@l z7Pl2Ju_?Ka*$a6P%#8V%T(vH_94OBFNK&77Yw~_?i|57^Lj<_Y1@2;qfbVd@G~_%j z6FJCkGzm{QP&lO3bEPC;5-&S&CIm=5lg2Vhtx2zf+8oO98hxR5aRZXr)eJ;y*PXy~ zH2 zX)Ao%zLvHxX>kh;Y4;+neSqcYHl!|v05ccVP`aL?eqm*RhJcMQp7@K$G-wtiJ98;jOSa@p@be10=is505lS5?v2HHNu{?kFVE>L zglk1aIz`;=lRP9OBII}EUXW};3+HUf7mM(~#t&lA?dSk#zWGo(lW;@5+3t&b0kqCj zN`#j??q*1;-iLkkb-t*ZiC#gZA#bG7o<>Q~3lU>>f3_XCcnm!)MS8+3=08p)T^vLMcp|h3)}Y(;liwr`wrD{(R7(`Yfa{xN}lT z=HY}Fw*@J$Yf^bh4vLUhEl|u$Os8X%*S_KE0))afF=(oeKiFe)7}+p`Ph~(eVq3Dg zh8%XVuGbel;#&}w+otov@p{Hf5`Hb+FdAoYp{sD}Eu19Ryo#VXl$@550%uvn)z@^y z6u7-e>LH~z+}r3R6b09qUxQHjf5dw#Wr5-aT*u;d9=UG>$Qh%goyub67XwKe{d^@o zUP)=rR1gvz{6puR^IU&*j`8od|DUXcL<9;ZU@!sJ7R zWC40F3#V$wN?ssi4-j+Dv)QbqeW_OTrLtG4U_6v?frju6gErRTP?*o&~Y=DwB&*)F9@3Rg+qhk z4kuJZ^TDb~`!jb__2FM2I?xwsGsx|W2zVgCyY@vEkTOilszUZf^!Wtacet0pUp|LN z_lDFf zd7Nfcy3hqrr4`FKa6Gb^`&8N|fJv2yr_xRU>u?R9qjcU!}OOE4pWXD!@HQl7sy+00~BiZe1CzltF#OE)0Tus!($T_0prH23?%_0B{^9aZ)& z65c}|YmwJkU|#H)j%~A=d@D%W5d-qp!zL;T{UTvVG(Y+ zwiIb*9w{QE*vQd_-1okcA<=w|#UCR0tRl~#<_{A=?|ZL)25!THa&WMc%(EofmL%PD zC&?8;aw|L*j-R9a-5gyB3iCGqsJMj?!;2P?ko6|U0MeTyxOA_B_8c>b?Vxo-QFA&9 z`}t&FeXPs~H06m#XuMjH^<+_ttXq+z))=$EW>@BC2AJ0Y*?FF<~#dBaE$q z@pCx73L$c6MvWjGx{`zXbs13~SJcL`Gt1u=!9RwpSFk&@Rg>lp>38D37&7p3qV?mC zo(jL#`zo9RzUFQAaz`oipThCM2#EuK2*(d$tfc!_Y|nA;I2^QK(B1QxiIky$SI=u&S5oM1YCjJTbKFYc1@V~B$pdl~k-je|eV9jI}Ue=ZKk zZ(zvJ?27>fGbF#;S!qN8odhqN&q;WW65=B7)0@yr{abYzqf``jFJvP@NHq{tPG2R! zt=)O4l8)U)QUho*C}|oc{fb#L8Wx%oxpu827CWG=Sm3$J)ze;nfnt8hr)`D<63D*MTj8MYM!_`wzU59Jt zBe_-CqkUz0(K6gZk^58GPD*qcuI^N6XkFSXI+jYtD>hC089{6CFpZ^aKSR*j$YzCC zaL4&{fr?y%Zly)FDM|I%b^b%fslF4_~gewa;)VY->yw z)N_uc(8?w}fY;pT+CaE*$bFvenrc)18E z_h~+MHn@v-yuBF@Q1{C=FgoQqym{cJ&*8N)vk?ZB9Sl7}ieo^*=kP*i62(4=tP8U) z3|CLWBux1zDJ7B<%}N>ZEi`*d_iZ6+@_%WzM6EgpsmR9AR)R9oaWS+tAA`ue#}4di z${7!#9>P9uaRdrqg40c)vS7|USx0wX*(+|E+lWIAzVnlJ%?^FPXG?V4cMI4 z4;SaOkC-ILaIJUPTmePRL8Si}xWz-BLbeIV>lha4ZxKFF>5(gP`ks&c6MP_sd2c!& zh(RCwJ|edza`Q;zJrJ|~JfFmUAm$s!dD-x>Q6Q0QxR&l-`wrA87Ij{rI@LSTvkKSz zmwCIFKGuY%n*dMd*{7P~x%|r3XPwHnmVb&m<#{MWqm!_TrwGb&%DbVC!Tq4<877OA zGIltkTA9g=I?TQUm0#Wtk(p*3BfAz4p$;)dg-j8nvP<5kmPbQN(})OX0f#+9UKCYt zk}+m2!rWkYFXQ4@APy@H-VVhKU4Q4d+-UQ04Y-)>U7CqZ=&2Qj@l==;r@Ozqho955Nm(yP{v%>MN3`rg> z06=8S#syluL<@sNzT7s)TzVvCEil=gJlgsvFHoHTKuy24c$Ck{CJ{2pAbrVFX*DkQ&XdNm}GuI^nce>ml{Bkeqi8XlVB z&i>+^OsySg2twD44WS31RM^hv3kW8UMOsXN{v>@6b%1Ex*VVXvipCpJ1U%5NUB=&`W|CAVsPyISiz7Sn($@N?b zJ2*?<;*mgfqs$WJGr+~|qAVuEQ=sgoUv=yc{mg9eJ^y^iKbvV!t7tpvj5=pgQGL}S zegeYC4SxWE?kEH+L0kj1oc@Bi0$DX2-;an`YIiw3LWEo*@I8z8UsxqTHU5<4(*&K- zuljVf?hgZ&0V?W2cxbjCp+BCX&xm(rpc5}n9=K~GjKI{A;ml@q)&?; zw=pc~crRIBLI(Y!?)evRk*kDhOT`+1(#?g!vfez34vP5%G#qS?qc}RG0Z@le^}&ob z`U)Y+*q?xg%vGSk&lLQSUk}o76!rvY5MN4grnz0foML>LX8w%?FCOxo==vSQqU$fJ zglbGlk14 z;c^+mZ1n2*Rej)ZtT?t{oC#&z9()DZn{`$Odx_>j*yqYfGe3!^_=IEvxz6^H_1@t% zX3LvYV4;~$x=AT?&kG$pV`F`~9}whTk0*pKI5=enf0x;sJtooDed_I880kLsMuQ#p zC*3E=6AX)I=fgc9t}hN%z}N`#)LNvw)i)+`jfp`nAmiB)OEVYa%e)IZCn78#5T6Z3 z*nEIk^56x&mPdcfqrdX#1RhSF&_Q<;3_e}pKXvyTMjYi^RJFf>iev)2fy$1?Zbpzf zaPu3Y%bVzPm|>7=#?ugeGzXrj0dLn6W8qRc6^eMulqL}l9)fr$0fET7f8yyfgv?%+ z3*<7-u0oAw?YKk)*PBHgO>CqUV@Nt=CasXyTf#NpGUKNk2T-lbYctrQM>Am120VFi zsJkxl4lM>y+V|X+Hy+VG`htQqps-*bL(E^vbD?75y$qg7RxjU4==qk0Wu7JDWiXk zw#`0-WE0{abBH2`g>GF%%WyL&VEi4(UsF>H%-~h}cwoA`qglcX#~s}dzX~|-J>6{X zLL7#l=iqra?xIVCPD2Pimmk0ag$0{dUjvaY5bp_3AZ9Pfh=vh3*$4fBAYz(Gl~Iz9 zd}6j!wUUan5FF?uzC%Rv{Zzm&HUr$*2S26Y4D*r?ZjxYHAu#6vOc&TQ2smMjJcvD{ zA1cZQpiBmec^wIbeANUeG$JFi|JsNo?p8j{JW5a^r}Q*Bek@{la6gqe%-J+{6 zaKsqF7zvE+#2878y9FbY&m+8rAoI(1s$|)h;*B}%>pli*T+1ZjdCQq}_)r_UIu^iQYJOWRY}1`a=(F(M)7SEMLSpvN-7LbvLzX9m!sa{-)!qH_;u zaJU#7Ofh+B+7mq&X(StkcM|0f81N>M{2 zUA7`<4{$?|0<31chwmBY9_&WMH@T;uGcjkaYvCKicG45{qo?(_;;H-wAQ z(|PSW1Co81t`aR+59kN5DF=pg8e&04G9!VT&Siy;%yW*saQq?upP(8u>mW6C>-T0^!Ukva$NQvs6-R6zz@0L<5|6 zIexN{u`2Vm4-=C;I09F5~%*IiHqB*?`F>p4`&EUE=6{vlC=r&Dq3#(Fxx zZzZJeh8HTrTC)zB(3e*m;Lk=W!Aa(ThLE+w%31-1ksRBw5tKK^C&t2Rx%|9pEKWVH z63dR-$eZ9d5_1T(#qJf+=&l>6QD_I=l!Vs2;~k8b!ksIG8wBPov3x5xrHi1Ei`BP_ zsZSqXx{iOdix%Sa%F@5UYYBPjW)r|h&gbdE%BBMN;5k-X8(x$ou0`X-PTm|?HV5`E zHSe%qqW3CmTL%F1%`yRmZW)Q}A~ORol20}GV5@mW9{f706Rhw-*8?<88@E~DI18Zg z%mbOg`hgRuFO$V^Q3VGqgjAviYE+))t2sWwN)qIy5J*(WjhbCl;bXr-?5!`*pu#-N z#zDZ@*3b&Gp7wC(^yjaj2_FULq?dhB&WW=*5wHN8ksILYhv9$+ zWGsF9hm+ID9~Ic>j54_BLGVlDY(1IzXY3sRW`(ts-n0T71D7*M3N>6ThtA76 zn}p1}jF@H*il|a5)=C-{Xl>8O@@Q+uWZ`Ce6XOx z7sV%|6woZ~32dgD=RQwX(i6CxN-%F#kPC&sEdJH{t!gAn*QPMDPdciP1a_xars4h} z9O}Y}RNSjSbrJGFYz1O!5u?a`*09pf8qqEdZ8@qAbMFvX`^Rzka~aUhqQjU4LPPG* zHwG5;7ZxT{qYstnkhxK!8_f^+1$I}7&NP?vle@Z7-Wd3iRz0;G1$?x5zYSA;xsq+2 zr&s-V0CV$)#(g4jZA}mPELx0QIZGkW3M6E*@yVXgRE=IF(V6DgepH1!^wUyb8fc{W zek%TS5r3poUTVeP%1`!w^Kt#r7&aWC$pYHfJe%|X^ExOffm$LndV2Ep;;M?Q0&qnK zp$nXoO9cfs7B^dj2#S~$cZuT&!xJ2bjX)cH*a0?bH8VG^_VI3D$t8K4=()~C%)eC? zdF0LuZKP?l(1}j5Li1f{WnGqwLFCFhbZ&6K*gczvOjDHGJSEGj$hr&apa&$vE_SxF zKH-6&5_VS1GCbSjo=$d8oy6KT$MSig@iB;YIZIF4JFOIBO@L!eb;Dp&WHga`0U30R zj~FSXObb;Djl7=uLk-9&2ImTD5z3`atLt)wM+=P6z-V4dx0)S%Le`^?lm2khS5=hs z0fWGSy?7OX#Z{pdO&O9n2l-?-k?gO(g-qn)B&{q9H(>!QEjbocpZ)W~`tE{2_%8qBcBhD`!BlR6wga{F7ckPe`Vjr$uo&@daPZCHIR1+<63DE{ze$ zNJ3`RO%W^810y@0encHlujC`k4%(1&ewhV|fYz(ngj|E_4HC)4)V*)VjOmmhfpm#WamyI64=sPv~ z#Imc<1Ob=1TyK}CY&tkLjZqU3m7E5qqhjat`zU^&kMI4<4lIu_rjRia#B}E~y3aDX z5S!1~!HDe|JBZ)tDWxS3!uKh$efiys-}~bG1kIh;e1-MZk_YkQj7CQsRi@^oi~j;c z7BTN?0W%j-D2mJrO_CSvHDjym`e0r%aO07lpT#&gP_8&1<9xOQQK15s%S56PDn~|_ zWWoPt9&Y(4PQ>fQ3a`}XntmJ`*vnvI*wzUgAw$lTDkr<-bMmbO-{z%PBO{wHzXqq- z@eSY*&LB+e~f)M9VDHU(j;HHqlaQv!9y(rj{Fi zgi?u|8C4l+qa$d%>uvP665SKCGl*_&>TL9vh+bVMW4FXSYCn8+Et*u+Yh#9zyo1`l z26%5mq-U9-E^_sLRfUwR%BG>%I+sDU;)*Tjly^{Fk19zjxem&sY8^YtYOS@hkNiE6 zPux!WihisHP>W}mNNhjGR@UZ$1QN}i`|rf6nos!yDcdWhRW37jq7VO(@b8aMdm=~WUA=plP)|D z>Xs{k|0@OFH5_k`UJ{z%CT3Lizn8T;O`VmIhO7;~HfyKh2t5i69mm}YB!Ip?!Fx9g zL7M=<6eWnAj6xrp-K8CKWa+`XP~NvId*Hz{%sg?f;>tqmtz75A@Y#NOz+UA7-s zqlYy+UJI3+fk58Ho<%s2pJGqC*|<~eDc#2+N6hoTA<--s&h!z0bYR87q#Lc>pyhvR z#gUR+e$u{~$CM8xArKXZ%Uekw6PRXoGu)SkDvhecpxAZAUaGNWb7H?EK9q%iPYX2; z{oiUFr)pfdJ2koo)mZhbXSAEY4+p?dvJnC-`+I@y~#ZTby5g_lmv{E5TY;Q8eI61z8ZU^P=E0*SE0WT;8-5k0vpl8}%Tv=}%1+7Mz_JRt zMTD2_#@~Yr`IxhFFFDLu#dKv0!g|HFAcN8IB#)WJB}j&S{wAF^@0zYW4DMtpt2th}O6-oG zMbls|=uPZT5f8hrCbrfZC@PX+B&QS*XE|{&getB|XbI;nj{>OLZ@wNgmrB=%+n#|hmS-fea(^}ghPMnDIVDzSx(4HdUd3iy+RZJI15g@krcorXw1fEnB!7%-S>+hk{#aGd9?LxVU@8|6k9TcoLI%sjZFONd?tbXSTM zoo`m391wl`*5l}$a$=9EuNkrShwLH|RJAavfHoOHAN_m*;=P>Xto zLYgYDx3Zlu3m*u`8g?eT}@frlK(7A5Iz)y7IwA56@M*cB_~5r-&m@MYbfHj z{~AQMy}EPek-Cv6=>}AW>~B+)SUo&nNRX@XHkP%;#O5i$3k+w#6E*qwD=y|*+iWe zV4D^_wwP0bK$!z?`DaLPraIVy21D}Y1?j_3Uc?lgGlVKVT~j>vcaZ%+)x?f!*{DeL zeiH4rT+Gr=`&7(ud>~?}4w$nB)p@f?DTMcs@O_7lvGX7etUT>JNa80X0NR0GDb8F- zn)^uOwXL1)aX1uh_JOo$GX?Ee>B#61ZMf{r#slOrL3v2`L!2zJMH*X(wx4|TVcdxM z5A>!kcj1>)DfF@xz@D?H&FX&7UpQI6Z;F-NMdbWof*N;;wbz#INmL-o>}YTDUJ5&% zhiO1c^Mg^Q+x%GdouV^>=k(`;ytU7XoXAX(o);Q1H`8)k^D5O&Qh2m5f|7{BU z0;e7P6zmcUt9A=e^*F4AeD?1WeMt&B<`9P?maN;7wZB+oReFy!*QU@Mj=mq3gQBO? z01Li^~6Y)yo&RMj%^f&!<-}nZiKMi#4lcC$!9BpGZ z>|jkK1R%y@smx<W>V{z(cvJyvKZ zR9k6}$D%fo)shs{uCY!OnFEoQgg5Rd*GCH&T>^*m_eW9H)kxlSx;TXmve9@j*F^5_ zCGtHS@}l4CCNc{Y5;+rwI=z&^E{R+OS7%Ic!@pF6^{j!(v&VRSbH+3iK(tN zZ78lFz>W(WlI;Yt2O*m6==v)_D-U#7WwS}W^=snP7Rr7h=6r8LT^77#{`QHKH0w;V zXGx~*1G;;3SE5ts8kvs5u;1(39sfO=G_L<}W*_ls&NHC)OVU2%b@6U^)m<&TSk1cq z#BIp{FVJBdK?<+^$ZNmd@VahSUXKNNVU`Eu#uQ%i%GSG^ceQcAuDt#o!+)B@zgOx$~T1#16r4G)5l6=|Hq6&S*eG7KSF zXu4=Lu11W}qchYA;u~(IY7;vaGzTfLmC}em>A1Z# zI^Z~2|7@#hTtvqD=aJ0Jqra4NZw%DZNIPa%ySACyufLt>32b9oUDpmc+S&g|=eJgf zR>c4}xU(Ji{wReBt!gQSeg1`=1CWMRqE;eG2C1^-uIp}PU;mAqi`+<#p;$+>{Q{ui zh^ZfpRk=N)F?<)Uf=ucd-H5cuGx!t%|#6?{rPOPXUR=UoZQ%WJv)$$ zLD5)Cmb{4uiMUIL^8>ZeqOK$A&5A0c3Y!pzDMRZAZ_4&gB^I^P{YTbHdqqe~`($U0-IUA%jU@m^0Pf^yPul3dYMCI{TKhqsvI-&*qn@@u9E-}Yg-TkJM>d zanCK_?Q=p7!2E9tr^CUC+nIyqw3!$Q?BokZ7BJvjp4BB4!|?4-Z6tI1~i{MNzL>kC;wCzz!0nSpi@~#%>*d@XCpA&}JI6 zu0GW@y`!ywVbcyt@imbiA`&{$QV@$!5R(&pHd}~MnZoA8*r80W&2R;Fj0D+zOXM?x z?6&;{cI~4iK>ayQ{2P#;BtcK%URbDERHF9Os6kTtF-0t+0)aGrOl9i^>0s2iMYIHdt%nmT@H;DF>JDL=+z(AW$gJW-Jc1&=v*6%8kr-5bD+O zXt4gvdL*@N`kQPfE27^vN$i=7_1dNitKBmE>U_t!vg#BsrW>pDhZkw;tXPTzu}2>D zpXge54U54%+YGFiVvuVlii2FAg^2zMk6n4nV=jRsw&>+>P>TEI-s2~Uiz-NXyR&ld zLY_9F|A7>EJGH1cgQi8M&!*h-$jdE5={taQ1Zi3Hedo6)=8>YIo7*L-hen|TQAeBE zEbaPYWyEwAe+T&OL4MzTK#N^|62+6RG8cfGA!PT0uR@q4&!vz^)FL-3n1cm!6CpYb zj~=RpY>PsvgOSw=`@-7aNvA9CU`Xy2U@71yXiDVzktMNDC;4+YX&AnL<2Q+z03Ug6|si`bFHRRP8ak+IoG4O%c3$UB61 zErqrDVA4D%G;YP()txvmMHa)vVvYbz&j;Tuz~0W-G?Mq{wVh zT$z$<{)IBi-&&ALlhi!mKkGBnaLPEkCD1H|B8W`M-$i7+w^*YsJgU%?#;!tyx_S&J z`giXJ^+=C#FlY4~LHKII-L;@W7@D|iK{G!5TMt(HrFJ9c;CzZj*ByjKX;)VUmc8idG~FT$3qy4ey1% zmeNj-CHo)W2^u~e*9j2^Tv9w%?We&e^!{;>``gXIGkS`(q>Ns9)~K3v-*Lp|C7k$G4QZkQ$o+fEwix>W0&Hp ziW;QPVVkqNs2BP2*+c1$UPcDI`Ux9$79#Is6*SlMg?Reu4Kc&jcPdej6%*WAr*mwC zyMjnL$RN{*v=5Qcd#WHqbG&k~2v-n+x3R!#fYEEDqzNt#UF$6)duy-mTpkO2BT^BW zgA-LyR+d<%F$xP4m|1TL$4UKMGseQB-T8GMlW;fN$a^#1N(#^9PAsIAU9+gB*2jz1 zg#-l0NOA#^hnXN|9x>&?xRjvhe?oQKm9GDmITgQpLyNb}0e5zX5;}p_ zB7xfwpN9&V!0?K#6(6OXr`L&B?6iWnc03gciN{hs+{cLaS8$-TZpr}+0#;qFK zLD%MG{PgLUkiH1?wvZi*86CA}Z)*=vue+;-8B#)AJ(rQTZHnyl@XWozOKK5&5NmZ^ zsb|04H{D_(`b+YuTPybJ#y~9DVne))^>WSO-;*H*1AOP-0miv~l= z+<46wwV+!FW9wN_%-n;CnuyP#1H3|p3j?sI_@{`NFQ`1dD;dI}UVW(7jJkfBAuKQC zmaPP~ClI@;z)t4V6P+fXB?}V3_7)@-Y}7>r_6w*8h?69KcTEf8dDM)%mq6|AZ2kQm z5R)#E^VtvC$jf%9{R259ghO3c1W%=A;+T~=`V)7GRp8eEK2E2@AXK8xvO>of&(4x6 zCDj|UZ=iX*dLvp&?{b6$hfwWbC^Qcou+0@Z^8S!lkY6IE8~lJT9-Qy`nzUgDqN|CT z*m{x|^*CRx7Ejuu<#YX=z*PjIvjVo*7dlJwXlNs5;;;!+z9dDq5%o@@dfmo`6ofyB zaHS%!v1?vNVkU8SUDL2d>`&s2vNCn48slj0TrEz-r)UNlCTU38$AK8dQDuR^AEB%| zD26-7V(szqEI%;en6juEG1>GJh|i|Scf<4yN>9WwJ>kz*5Pu#f**Gob3R4U&O1RyT zrBvq-4?}rGOx7N7ISvtHPE2S}-Qrkg@en=$JiUc-a!<`QyRdiz1QGMxf6$jOBPc~C zb(zbl*{z~63$NY{fJ~o;bGf@63>PO7>?c7VObQgUsRni}+`D^hxbLv&)i%3n@=K0u zkChMS;Wxmjs;~gG`+B=K9)FXO0n{*2uT#{B=2wX-K@^rCeng{c_WQ^!9|9T=kd%+v z(tiTGepct1Cm}0Dv;7$4{tgtdF9lTMR1h=&6-(G7i5HNlN`FM_J&F1K>k?}@f_^W? zek!p#wOf@CO3B#*TuGqU_@oH$Na6)bEOk+kSb!BuJV#0pT<+Qe$(=|%k#K(-Y$@(_ z45+*}QHBsDWSdSd`=oH;JzUPdMA4)5;?cDqxE>X78-N2IbsiPhX#E?1031zzLVT95 zKGPq!n&?UiD_(KM!`x$FrGDbh9(XU&&k*KmIk;L*Q8W82%TqtzNY3xa{ z*hS2T*~stB%cw;O&*z!-RnQK5yxhDy^G2wl2hKc2xphoNaM5YvBA?mu6qrtCs2Et!Niui3{S4^}upGIq z`K@cEw3H5MLHv4cOX7)2%tc(6c&rkqE|g&YTO8~fb^>*YS#~ySo7wkBvRK=Th%$yK zRTWyw*tSdTF-n-v8s0Ajy76iaos7+v%%oDQo4GtIV5@d4$-zUrnH3es%6Z>JycV=v zJY2(HS?I7TjiO4gzKWz>${v7u_#G)~8z`$PE$5fcq-`z-ouoPNs*icCvdQZAvqe9ntMlq-L#KrG~1C>yKNvj-$l0 zRiaNJs-FS#Y?(q1C7#AGObhsP8KI+*-{cR;JtC+8a54lTX zzeOzeGW#OJ@lBEffmZxnk}nhT!a~VAJY5n!g|cQcceWe^jFiZD3A4&>H&>reju)sx z{^n|l9V-e&&(!j)ecgaA7m%_Kai$a^@hO61KHpYB$WqozJzFJq$IG-eVlwHppv8Bw zatQWYN+{(uptFmE&SgLW0WDV06j*mmzyFa*W5?`DJISa0-<_|NGos^hd(4{AnBhKe zQ#P)7UbnVy|-BLC>v&P zJRxW`f)?l~NbEI?)zuJKa9;z*O!z+`r9rBROK8FvMJvD|7-X1A<>Fz4cen}|sfv@U9 z;%G-gaioBoXKM7OALJ$Qhv5P=!P+|est|%@uQ2kjCjwc;HAf8Ugk+S7M$xj>_B2lCP$_3 z623&jYf}h^$7D|z)uNzDoJr%oX3~F4zNlO{E$wBA*1KehcgS{sVe3kImr=PYi8lzT zYb18tGL$MFlrXDVzGO0PC9}V$<_9ExA87QT?ViWRMLUDWNBWRRONf-R3EVpmF7R6j z$9eGl7U#j!%t5bkmF=MvrR&LZg2ysqYG3s7j4f235M>ZiV2u)~ihbQY$ zIff>T!1guVpMK;wkcrFey**4Hhb{X%irHo(s`5=lIlv| z^V_;baIEQuI73t$zoL`a-i$?BaW5ltdl)KwG@OF6%|l>fE);2@U!O$FvAPbkP5(R; zkT<%m$R8$1!hHMrd@<9bPxMjYhCTe0gU4M*O>oA2j2Z$wFbw>M{v5 zG{+iDJ;JQ_s_|>?;m3fSo$b=1=bK5_VSanE$)}vvMfE7atS0KwFKJhPATP6iT1e}G zIuxj220d01ySb=7`2myh)g4eF!2>v)+u||gOF+Z2BvJ9Vl&7__Eh<@O%QGPHlG%2h zhrzEYnZ6xSUrnyR4Ber>i_EfG%PSk>RAD^&O)Zi0%3sK&>F`36IrmN`fM1z-CB6%F z`r>K2faj-qofbmYKivp?oj~RSJ=Xs`CzYy-(DUT7p^v*iap$MvRw?c-eDjGriMSzF z5SH^fifv^dNSxwSe#i3cwpXSFqZct|)JaVj?ELf~d0PU#tLtok^_*1&X*@2PEH!N%R@@%ao?{ZuUGOEsAioG-8U(3b0c|PV)3K(iJu|e0xOjk_s zW6O6uvGyZYC<~WrVL{@UZn}hw#<1cXmF8M<= zBk4q2CBKPgCO1Vx$uFX)Y+RD5vkdGbRPzE<&BD<+b-M<7Z47w7Tvn+O@E48YyP@+=7#Xh(IcWq{aX@R=~fHeae zAUU)K#chT3A~k&#%?=GlO;C^0Xf9d_jim?*7(HD(#cpc?G|9Z3p;2*OA`7-*m`=z? zRB0hvF7#4dIG^it&Tb*1l_x^L!vi9ccZ2qy#to}OTerCxqopkz_d0Mk7hlAVdtY|# z5D$#ES&#}O%9aw5hgeo8nU7{pz5D(hKD+!!g#0|LZP*0qIV*zo=8o1to zh>2@m{~39l03=u4pOBZ;r2-ldptoAu34PDCUyy~~11YW#$L~-P2AKoN!>Zs*;(USO zD>9qSe+H9EjpjS5-&{MsIK9qy0*?|nPYHG{vSyYKX&_`CAzT>K;f&1zn+UpAK_Du^ z+a!%fyn|=laYt`D?#Dd=oEm(swvgnc6s_ug=r@G+QK%G$Lj4!N|`y^O)-$s0G}N+%M z?!Yw<4#2;h{|KwP;!D?d6m-cSHf^_4y%NZ0&7ub|EMx~EqXbe|tjbE%(TGAuxRT}X z+ZS9r1k~5J1J^7s*P}SPrxtd!!6nSC^b%%h)t1+QYvS;bcX;N>95L#NZ)64@H*+?y zJIOpQDJ6;ZxlDh{QEw(vy>eOO6Se{y=T0TeOR~G&s%&3eAX-Hl?)@5`MJJ>et#PU$ z1Mu`%nH&bk5uFdEgCp80PV!P9gvutA^IV3@AlEWT+Vf?Wdf5l;_s-O1HqPIas8#}7O4~gKMn9W zO+(`>W)@Mh?~ zmdV9;BNh*`@Ztpb12~1$33h~+^ML}yxPYSph?uX6UNc}9PzJJPRdJYB< zFA5SKVb~hT$GfU`^^*USdV{InB6c`hs3(AX0En2v{}=W4^VNd`aJjLmV~m7z%`z{X zXCC#!`DTF^E--Vwa6c2b;o|V~g@YpITq)}CD?SHDOvHX-PTfo(W}slx`{C!)BIaKK znhczu^Jub6Z% zj|Is0jF`LaXY-Ui^RP#iZ|?HK1?Cnn+|S(Lg$J1{y>Ow4df{U8Z-iZy&=>G*KhzVw zyb!jR4^t(P{|Z~-;%EEGMC#&k%Qd-PIL~By;e6BN;TM?i8Agqjhay$FhbHeJvk*E# zrLzDrj~s84f9V{4&i6j&^K-WMxsadN;xj3eZI=2z4=&VmyicK?;e87AH1BgUnO)$0 zF6HOx{Pg>Rs6=oz|GAPQ@FE3kDb%Eu+jCLzyvicK>VRV%G$eVZ7~dBgoxv z5G<7`Kl`PA4)VL|m9>N24>T0QhCOI^u#9SYKd_MrX{6U6Hkh_uMHiv20e2tg-1I#f z7wPKT2K*x$nfMj$N0dhtHL%I=(kqzVy z>HSzncmRD3RLYgZrU(^su+t7YyqShc|4@d6iV)hKWE`Q5He@Y8IZK2VAr6*bcq889 zN`!9HuTwlZu9cOwnfgu%5;{q}KKuoGC2}q#!R&N1jVm3AoC)}(mWj}KhP%9n+RW<7@xcOWD}k4xwXn*leN$gxbq zoc|(PJ#Z&Oo(JZpd{x=6TuGOB%GXu=!XpADX@K&by z7rI{pyUYC&*zN9@sC$ck!4fbls>KhRyjrR1aFccDO2Vr~B0}o9y{OikKS3?6=X{@x zOhx2fe$IjbB4_SxhG;ITP2N?KpO!WeDGV9?4#zA7ezV1Ob;F?p`h;?OxbIK(^?iow zz~G#}DQ|XqNg+x<7hkY=n+Sb>m~zTW;j|Q;V98LxST1Uk!GjW#_m#|?qb2`tQl3D& z&qGUiXrS3(5mr>BrPV@Bs*TG6DEcZZ`a`0uc8%bT?XKubkLOg6Cr&1-=p~kOA~eZE zJIh0Z=mj1^6+>RtZtKe)^mo@ES)<|>WBNTIi)F5VFw}*zUiI3G=s*5I^g-s}6Sa(S zYr(Sq>cKNah-=1W=u*38WQtbw;4hLG>cLTi#e;`>TK?dr)Mp+VXu5d_eLaL*zlA{< zlcBfFZQ-atJc%1fM{}Y8$&C3AF4$EK?+2BI)myrNhv^tELpG&4{0Nd=4>b0# zUq(lel^O+{+)o{TF!lEG&EJ3c4*$%mkjPmpA$9l{gT&#jNhXcX>mJ%O9vU3}J3j=$ z=drrPAw_6m{EoghWep@|QsCvrv;1vUgKC?sQO z%h#zgk8`tV9d)c4=?XrPf;(`LRt2-uaj$YdDIk0?9%Cv-0%2xY=65j<76r&t(Txf!2k06PFS`-iqlR2O!xT6pwUK!T}=&FrC4x~R%? z<~Ta@b;omN#H?W}#ngL2?<~2Fg1wsN9OBOeK9Y0xF;JZcGR&DNI1`C8kvK@13q7R6 z1S!;=O37qYsCc#{hWU^k-r0JhHDH3&d8kOL<}t~N>o#W;_t}W~DrXZo#NWeH^%qgn z4ukX@J;t=YmtE?F;37NPoXckh<#?_+>^MlFVGjiSWb4~Y$>>QiLN1P=0zu6nQFoEI zomee;1pIwa6+k*m5+6kMs`Q7I&vaHk-ZywnCi_v!p0mZ__}(p1E+fjn6r}+3JDD^R z&x@hFJj#Nh6{)n^z?AdL54i~;;0%BR3E}W4pE|?keF}K*;+`Y@$bfqe2*!HmwhP93D*w(# z(kmI$scKa2*mJXxM4gE!Hw$HWnhU5Hpn&GS<>8sRE%QeO*|$^nl7(h+jO&xYSu==Y zzS&JmUd+s-$y#afGGe?Ra!vCx{!QU<135gb9FPg!vgGY9>;frwj040cCQrF;8)a)r;<{+N%zWmqov9dbB4+vWbGpZvGes7tp%6uMxS zqpH)IaR^bpUJ2Vw)WP{I990O7oW-Ux5ej<|b2MV-S1!hUiICe?BIZHqsJMgb`zW&M zYo=l0IIWo^>KjBM#|`d)nt9Isu3H845kS_h1)BKsgF*P^aFh)rD=i}H1w^FL!mynm56mY?o0u8xnOxzvhWvQkt;B{b)U;sa{ptc)1!_VT zEah%?2Jj+aZzm>M3~Mg@2B07JS$Xh-oUw!l>VU8BQ_gLo2RTK6xy+M`gcv0T>uP-3 zm8;0;Kw5XTi5}u)1D#`~Ph{r_z?#r@MyqP%AmE$H>}1=g2~(FQ1`)q*dxlM`PSRTB zv(In-90($=JbZxUZA6_*6U0Srq63{{$Wz613-vtRTbEf_bvL(LENm$}%NjzH|Z()}^Qw5e~?o^n8 zA{I8q8B16{Q>LH>fSQoKdw@lKG#6j>&;$#~Ya-?qocu!c28rH)Xd}^&Xf!6!iWYMu zyp(@d@DF-{Tmj5A`#^?Jp?1NLo6M#v)xzRLd>j-&_5R?2vL&dkiOq%EaR!6Y-lbUe z#fiie#z>KK`G8#$S4?d^hYkL@pp7_v($k!sG5vTBMU zr`}oSRkAY)+^9>cc2!!UUO^Pfuq=&6uqMTPXdnE13Lwpj+N-dg3wHX?MU`FbeS_d8 zvY)2xk?Uo6qn(uIWf8d3oV}EZ>W&`Rk@r`%bun7{X(>#r$h506%}bVIVy|^sak%C{ z)FjQzI1XW&U$tBqOLJbux4jeEvU9?th73OEVr!KqiFO7ZK4=4OnPr!SYn}%Vq>>#{ zY#~#~V)1z-U}cnbDWBI_8<#ishIiSi0ZrG_h9%T6yp&gU|6**|;gA+U3vY4SZ~ z*>nY)tXK}p=bB<0m0cp~@?Rip|2QR`|6D@LHN!|&dXk*Sk+U{_y8mImo6`hb1aKgy zIVhN5!b*%AJ57%Q@LV0|(gBz;wPY0m2A1PKPA%6}360y{77GW@Qs!@%hob+3i|hjU z34n;XwilQ-3#a6h;KFJE_0xX65smY-`jw+!SL;_ZNfJdBK>JODvk-JNI0wNmH8>x^ z_Yt&Ne^g&o*SH0hyu9*QM-_)c6V4m-RgAw$zN?*8BUjj_x+@OlQ58ILf6gK7`cEc> zH3BuI+oR$Fle1+TnGZ7WV&&V2A-c1{X@zSYiW8xSy0RbD)r`3P|K5*c!TY%6$rv050G(HatYRs!+<+pWNkMhQ7>nQHCX*45%kvsv=%-E5L3o&jW4x`#c`#X)&VR7|2>i?tcI{>39y0!ykA(U`KH6kT6 z4L$H01T_-HXcW*zMFA;x*R=sA2pR|&R)Opqq$r{yVndNvkXH?2NkFC8f>=;NqOWBx zixMk~ius@C%$>V;6a2pavux(hoHl39%$(`=yZrXpbZaL!O@c%1SCM8iWcLOI@0NsZ zmF|g%di`s@T_|kOfP1^v^Xy3yt(Dj$c%FR$zKtH2FVlKtJXUTEX9ZR2EkXyVO1-^} z5pa@5*{PZ!8f)&_5nDW-bFUH z`@!5Y9E4wq;8Go9!#iZ*r4#x@2j;v)q7Q>8I&$InVgmYj`wF6abo~@;Rx=)N`;q48 zTG>shYg$lz3y9dFQFPp^tzqNh)GG|BYiQCbs45^^p!WjO5B|g@=2_R41<#^pft^sR zdMrtDn&FOi7P9hv08d01;0!F*SxvpbEcq}b>zjKZWhC{Tbn!+~)c4p)TouvD>mlfT zto~tvI+C{#0bi0j%%N3el;hW|f(yoKf%G*@?*ZN7)7x|4BM zlg#o5Fo9c|SDqhCj6|+5Dbmn8D^k?r<P*j?HKc~D zE0NG0z%sJU0a8YiKNrz4Nloo@oU?Vkla?-tJY4BgJYO6eMF@`Q&FXH#yHzd|&E#pg%}J{aWre#ITl4bPbDwD>geiY$o$Mq7k}t`t$yb#C zuw3;-7v*D-RcSs{zX799&pr*I0ZR>Bf7) zR}gAbMN(FUl#7()e8!1pL|aBP^qI8kB*ek7Gb-Y88n&nF?GO6>EFrW<6C#{qFcEGM zqXbSun%=5Kym*txicCtG%$YEbPovV+Ur-*Pvj#8e82iqf2@~}UHT&+A8+c9 z4EcDOAFi6CRI~U|S!#YaY3F4;>pbVZ^LOMQE#%D!Nk0Hl-N$>&ZlTy=frJ>UMp1 zdcC)kY^{JrJzj4EjMwbJLUoAxjOB?2{TAkHTPOuzn!4%Z8WTE&sctbz)Nk0`W{PQ8 z*c6i_eTO8E65=W@m;!IHQSFQ5qV{roT#0Z@7AI0izvYRJW1?`l7s@V{RGAVI^}khW zI7{+PiJYVJJp7n;O#M}J$GcWxXTT>L&0^aduAL{Aqr-Pmk^rv8u$GE8aPblt7%zcu zSz2(B+SQ}@4IL1N;;R^6T+|BV3$^V-OvyA1Hi9*5B|yY?vcx~n_(s77h+nJYqZZ*G z(D4lszeLA>EAhoTo^RYDI9;uC z!x`!^H=L=KxnZn4yWt^f7Q*!y1zdnEHNg$1s19y8O|^8x>8ha{&QQM}XN1gD2i))w z^(DfF5oRD+hl5!`zk0J6cFFe9ne23Cexwod?BH}$=d-56nMaMN#888WI%~7{?ZDy1 zHQa~KlF*K|VUimhttQuF!dq_bt2LQ)_Be7oFMJW%*RqtUGN0^Dxn{%#6jvByZ;Bu@ z=~$u4j3@Ivjm?US@wA*xu{;180u-2{cb*_Aq0W?=KUKgth% zG$OH5d}63Y^+-#CVYvP>ZtWFL5-xXPs1!^ha@0$}x8rMyi_EVXF8myZwk2UZEpS5f z^_SLTXp#QH%sJEaiU27KEyH@bLy9#x5|J;Hw8}|}gd`+Vt)#-;@f6PHkv1 zJGBOC0#>H|wb^$fL3I|VOgBYrZhdVvP;K@#OwMdi-)ah{+atazY~uCfh0u-~|1<)8 ziM~^?TT5ext<)N*HoFItRXgHmY5WHysj=FNg=Fymb1MK=*2SNufoikAVe%Tmuixp{Q<9OB*b-qNQ?Fr>mADDgSAI>4RB0h#e@Bs8_eSRR(ICzup zLOUUD^>ETo1tD?p;!!`!6m5E32m#z9vAJpiWcJ{{hUf%#YA+@^nEx%zKfDB^zdCY! zGS|q#hr;X-=)~oasOyAdMgsNP?6stOYg;P*Wl@63I{eCWNNE5iD$PxEbYt&lN0*=w zSG)Oyua!YUR(@ivEwL$T1vu&K3h?`k&OVMZT)=bvSoVRU)i1~=nsdgZf~jxxXPW+W z+A;8Q+p*FJ(QwHm?v%vU2K#YarJ4pGg&&{u<61f_P8+rps||pz&8|R7ZT1UHU%{+L ze7%~`W}DY$FJt7mHqZ)cz^TvxwC+;_sln`-Ogjvbc-2T}oz_^jqnb?1bz(3b7o#-P zX-(7-P8s8 zrRc5r3nCfRDAq~jkLcGw+GH>hB`w}gMk1Mnmo8009DqAoi6bRzK9Lq@A}d*ffIeD> z&?q^jiJ?bHC63o5&qq5p#3id+G(f?3leMvQBw?aGd&e8d*&WE4sl|8{fmlM3Km?CO zr1Iiw>Q%TTK&_$+Bvn=3XTQ)4lHyTW9OdAV3|>u*0b2Iec@i)iK%sC+s6$2fjMWKW%Kcgc%fd<} zO+^c!w?IW|9EeCrLLyhpjZ5MLqnUpWrRXoc3h%-<(1M8T9ub+q#V0@uLMb9+C{1HZ zj$Fah8A;EC@*BzVwazquvlC>FVEOb2T(2Gq@m>r1R$2tP=A!){)E2+ZA;q0!{?q^n@6t5g{i9H07U@ zW|*YV9ERMYnXkW`{0f18&RbSIZ@3>%VM>u?Jt=|;7`)(Nm|Ej z1XjV;kXbQdzxJ%o!PPdp0Xa(C-wt>!SfV~b6t6CLkuoGAH+7N!CUSWKvP3;7$Qfz| zk-ZhamI!wu)jMX9iH%a<^DmnGG{hL%9wSi4YSb!0BrcM)MbisRelX;PE)qnNsKz2v zx;h~tKY~2eMfMR{;jmALdx-2U@Mc6(@+i3D1Rp5iM3X`u8i1dYzvF{N%j#r+jA`2 zI!0aTFwGR^@xPUuMgD^brPigo1;aE$9+I;DM64RQw}hZB$`>SjUCPIy;5RE71Cm$=B?iF{T9vP5-9RAMca=qyD0 z)s27G%gdQA#U7+sV@~OaA|z@T&-I|*$7`uXe~DQu5{^%OYJS0^B(r&v^4Jm@3# zF?ujPbE7-4487g4HoNnBxJ|F2zxS*6jsnlj-28tN`1W}aC=vo;FM-{E4-w7~a9So2O8>NwT?*H@$7Bao9PPgX0C7rt5{V53r4q}tw z6#I5$$28FVz8v3ZM6fvu4^&3DyEk9o8Y-Blx|mb#9D|8fCl&$M0c*Gj*CaU2Zc8#; zfh!$@xDO>xHbIqM1k!(`Oe0V&+jd;WrrjCFGyob_)_8US8EX=}&3=b4yaWc<@?8m0 zu*GdiaE!{o8hKA-I^BL$V8PT7oNjZEhnL{(_8o?x-saC`uk88jU`pK|c1q8=teV!+ zlhY7xw>t+PviTBE)`N<^B)1fW4u_iG*fyG`?v(G-`Q3=$H_A7*zPW3tA~)Lvg+0Hu5kJWRnJMSae^6s^(}(#{y}ZdMR+3&lA<*53|F&&EJH3P24gE@DX#Rg zQx8+nm@llKHAyUCqT;fZS?(3clGvOgJXHm9C9&efm%a=fGx{!zJU$7ztJ<6Rypve> zx)2fIkoJaY6o>f+fzgREJ zc^H4K5VwGCH@vpkG9Oud5H1hQ=x?7 zr!}!^#JI#ZXxsc83SXGT9Fk|zkHueW3JPB?1)evsWuuyU zkQAB)${8~gVYB)UtPB)OqkLZlF}X7q!w!?5tpp!W5gaq_4Wlt8DNn4X1r`8C;of2| zNtkrrWK=NSQl5(7xcsJ-`PM66C0UCr^Gm*JfTp9M516Or`xYI8aTOVVg%u?X>hK#) zbC}&jW}FZ3$PY`c80(7s88M$0%qQ_{%uQI8RQO%E{e&wPxLF=J%_lfealORDB%MtZ zpLe7g?uG!--dcKU)Fmq0y?P7LO#E^Uex*m*#N7R0>{W-nk8 z1i!JOsZ&6vWR4Q6f>?nNg6ckD<7v!%d%S|ljfwXO_+f%yRS%pRcV&`guL?5gjP0V zngw|OfW0v0w2wx2Jl`KpPx8gwPX#Y7qQcV=Lfv*^O&(svUWG++I;4A1e=)XL1o6>nNI4NPuSFXp zluM$u*66;ymR&cr$eO>$< zQ&>4+hy~P81FYmhWbDv^*XXILB{euEU~U-|2Mk`%W6W{#6xB|$()tI#3RCk zOzojlhiDOEY#N&dRxqWRq*P>Kl2+JvB>R`)p&WC=*I0FnX76F}B*|=*)jN|%hrv@! zc}B16xePWx4hEMR28l|{4USi-^%!g*nX8V);031Sy9~4f$CJTtIG5%rwSd&La{!6) z!)wSg8*N@UCB>zCQd0?DCDG#m>JQ9?Ehr`68K~l_xzs=1M2Pzz@r6fXAC9y@N4jFl zPo|9DmSvda?J|c4>!AgODrVs-0|exH*qHRrh%7iuZDao;Tf<^OJPBQ+MnF7(;u=~k zS{SL`r&M!6Sij<^E`n5whj^pygYD!hVKqzyjRhMkc;DiG#iTJhMoDG`FI7)mCWhoG z$!hXA!bJ;htzr<(S3{joElN-)>b(!DF=u1AZ^=Ean9*A_T$hYnWv)(_6J{~=QtB`lZ9?U@O4mb8w*g9fmT)EMWeN4x$ z?+VyQ+}MwFYys)s3+i4scvilvG&dQi5Ec7(k4rWx3drl;y#8_*(M@IwkB6T)^zin%?udg9V%;HZ)+A-a#ta86Maj0!{{Qf>CL zL~c%G7g#1M*Atk{PU0+uq?IELdo^w)YSlEX&kYQ4Fk72Fkuk3$CQeM|60ZhA?Uc;g z?9&PG769z#3G(%($T?p5rpHP2VPb}sXNYVWFx`rz^w!dR^)N`EmB70%5x?isS^bPi z+99MNBTo^v2{Uqa(5lUTfS<9c-dqeIrAIWSA#SfGv0TstjjM>XH312i7ADyNBum!M zB*0Dp*t~^Gy7b!YzKo0{U}Y0)kilwBfThHedhM3c5JGWPP%7-V4*}|RxZ-i84JAMn zOL4;dO#+M}8EH<%P`^f^X-*fxZPCqXKsSccoZjKau0xY$n$v6C*zP)3n$rv1SRC~u ztTd-X+}P%j1hLYbc5`F^7%zXE$72c~J9D=)OLFT@(4mRG$44M^n@;IBfeKG3uqow@Bpkg)=r6h>S-*OaD}S1B zGNxL4sQHX=THgXpu4Sm}$bdtWj3n;#m*Ev>hSLClof@kNa9S{B79Q9T8B=C)s*pgr zg?@>vjBz(&uEHrr8Asu}qqdy!| z>L*jwc*xixnQ{!0y()Pjv8EUy#T7zvIVt`xDn6aXP*=tGk;bLK{@+wQSaV?6X%+Wm zM1qPNkpWelsa4z{$bkUr2=#vtYPy+Q!*Bp8PNKrAbn%o1L6nxkxi~S!nIC>ThXB5FhH(^>M5&quz9Xv_xK!s4EN+TQ_xL5I z?UAI%&3d2n6bI@r3tGI2c~|F2ugedRI!IF2b1{&cm=?$|!AbgoNh5U<2G8)rGznlG zV$wjJgaLy*RkO$LkA0{#&d|$ea|obRSNKf!fAEo?!zlzST+s`^WkcHOD2qRj>!I}dc)QW=EV8!*GqNdm@ zovg&ii1=P5LAk4{hNpKTscVHpyC?W(?jH&q&_JY-(aTuL!=BS!dgvykIti(t(S8Mc z1Um-yA)9I?3#=BeqYEc0f*~P)TYgFzpA( zsU&uV6)Hg}%KCAo6+V0%HT5XXDdH=l6s3fsV!M<3M!7SP<9CVc!MH~m7xCRK(5c1z zGxvz2q@Dy=ECB2Su=bA&9wNT+1ggcb7WPZNp}EkKbAOr$d~T4-Fx$Bp;8%mFy^@Lv zZb#FbRQ;gp*XkW6tI-C$kE3kR14|ja%3fUDVKKWyu$SEJp&&#%>`rhVPqf!!&DN(T zVA53BLSwnsm)FF6xJ=kTHpD|`mRR@pPmM#MLKF|vou zY9$S$w0H1gK~&6(PyvEI^*ihrrRY<+2!Lg^TUuzQX5+ce?but=5=}OW>q7hq`~}K^ zukoW!hBVRkMohlJ)1OT{MLJ+t=29f~?N+$xc#8Bx21++0Kj%J)3t?bml@;JL6PJ(J zfua0!fy0szn8I$lBEGBV2dh|3U_MpgvlNO|pRomw_^!Cmo5jnS#RtBUtbh*r7vlC3 zEXvAUkJ!qUgt<+_aFjN?Y0w9q4g*o>;WZW-^?-zoz!nft4s11ypdkhtSY*VDEGTpo z)Y%Zi{&*PVE{R=bg?XEaRTgN=#;sa)flBRio!G_-w;amE3{1i^kvG?}9FkBK>?H)s zSw}5|X94UFrB0<9K13agW_YzJo3#T^1>E4qZPS9_fu;hVgC}b5%(>`*B?XUmF>qj(jH*D zwoj)e7hP$U-3%(s)+C67bMH)kT_-oN!p(+Y;qhbUb}w`Lq)xcb3Qx62b4dqS0Ud

c8@16W#UCTk&{~0l7!Aw7179fdyMIyEaaP)DB*<* zSVOcgAkk}-L&a`8@erwHf|_5Qh+iTkt8Q%l9>iKse$Eptk5CE2ZpKy-r|QeZjJ-C} zWK5D@L$W7h+CsI(IGJ2cDho;F7@2&Wi8t#+W|FN`1@abC53n`RXK3=Uyt7@Mg8DL! z7n-IW^0X@**59%H^6*kEy8DoRxp)yOf1c(xF5@} zI-sK43k2~6L43Fki+c>LLp7m1UZtl4AODZ4#smYNW2W|JuqI?9zOME+P||1jk;fYR zCSW#H4}rAZnrusA=~j3XoGGhJ;a69-Q8KX!nr3kEGO0}-^h^RbJ6x%Awz*NYFREt4*ffg*#;6`K*G(m=%-uZUwe>j&8gtK z5GkVkc#%=xL7C}Ch#wR2VZRG#XfX#h9_wXR*+6t-YNWw7^#$*xJN4ylsGbMCg~AD- z5dD`ZKpURVRrv?Zf&B#)!Jb0B0#)fc#I0ra7|nK)6;5eDp%<~o5GQUCrX*bkuV7-| z?nT%f&hJ{GHq6{Q^kT=z9N#VqR(F8$OW(17RXuqdo>tOYqqvGC&O1l#QFX7F3~ zDRC-)Kpe+H>t^w5X0fqkk)0MszrUcwbS960fjx!HOJZljiG(>>W!Lqk6A5*>wdlX} zL)87?VGq~96Rhx4a5Am3hR}=F$ZU4|aft$iZYTNTdaD(F9>2v|>H&I6`id+=pQU^| z?3Z^`I9lmV>`&3S=jZGY>`H{KvVJE*uVV}aQ|xiAe1JmpP~lwfKWHUJt<-$Rf@hZn zt?Yw}v{sm1d%Q5GSzDpA5e{G?8z}C93 z`7UfX!tNH>U4(7!a8%HG6e|^jMUvK5s1HNV-MA>Ahv0+M7P5eXy;MuoGIcMyF5A-Z zZLQFsaM5HO(%uT6`#0;)S6syun>ho>_2iGsG>|e46Pa=-Q*J%^<9YoTVcQ67E5dU6 zhz3z$GI9zsf;f&$+7@Ddph}&LhR?nZ;vp)<3a>;%XO+R%A(%5{Kb=$``~*=Rqq!Te z?rNt;lJ7>c7>)Qr5_LT>w2RQn3RSZdDGly}EYNacIDp66bX-bd)BJ4}u-c?(qx^xi zIcpxBSC5hh>$$rsbkVqaE}3uZRIB4TM}ggLiH^h>l(;$g^BMXo$LruTZD4@mtt21( zm~DXg8DBtGYOn6WoIK}}!jk~;=6UgOlV?d@jAW;x#O#~g8g~mv5zN&B9yY}Pu*=yk zYYW$_n=S@Ed?{2P9bY?(laTANxa?OKnnb*WmA4)CL?VJ*=(9P#H#poKRi%p1YT1Xi zQrEK}(h$ppM?XixmpXytP3zuyaj02R=DENHwe6Hl?lOsQL>te1@A?R;0RX(7YT_Eb zN#cK)7^prj?zzL*MDu8?uT1_C}C;_a$!)h{tClQ!BN=8{g=Qp@aC3zT= zRXdO&Oi#erFARcYC9$SfXeC4O%GeT4o3LVs=&N7`XfdAMcGr{R!QIRUJ16u3pP?w# z=cu^$<(h1+6*?CoaW9XvLZ@jKRes^4*1};&eV1NKJp{W{D_Q9uB!Lc^!0}e7aU#-m zFVYGk-9V&ki1h71s+mg^R(L=PoAdu3FPSnNhkB83CvsmRpG4#}f=o-cLW>!eX61YO zx2C7;tOy*ni9`+3Ce*Ku-Am_ z*U$)i3HuL4cI_>txur32_l@8YG z6pDCCFk8>6`W$H*t6t2VSMa68ZW_n_9Hp&}uxi|qMO8m8;=Te!!kKOb@-d`Av^rxj zXsSw0Llb$-G1wzy^29Eh=4$+E#jK=G+6j|gQY5tlK>oqHIRH+^4 z&g~$fa~>3Z@C2z0(ekuwVW#}hwg;(c)Y#2(v<8A`<)mg)Q0k-Oxh}(73-jaLW~aAL@2A>O3ab3RDUTS<~Di z6`@=WHc3A~LAsH9S|<^)SQ{ax@W`qVQ!Gw>xDyFc_Nm&uZ^Eah`z$&Idjw@IiFL#P z6xp}R9{daWlgf2Bym0jt^K+7h8HMp5Ly{UmD%n0J5~u*ZSoJ+JVIS!u6fdyC_h39= zm91}Va87n`Zgz0Wh_jJ6Z)u!iMFXs|Nk@zX$qsyumq!WUl|``@X{0l(P!U5S)-Jfs z6swtoGLJ0$MA^&SPShw@TcPt@l$F}kX1$X=zvVzl!sg3udFAj*=$4?Q(ZLSgUT`TY z0Ok!JxD)e+?ke6dIHFs6ClT5VIYqqWH&&nJoe1Fl&!KinB}|( zmR4vj!uEPbl*BH!LJuRvMHuYL)m=g$3@|l=T3D!|F0sOMI#S)gpv~8?XF0H<=8=S* zq+!Qcq4Qme9RYNNb?KiL4q>=i-7L{kQ2;nDX^^ir}@<;me?tjt0Z=U73yvz)U|5~ z+?fCe8RYg~aS2r5F62o40LpglNzCDMlEXJ-?t47kI*mF++%f4Qp7kRBhlp z-pC0RSqWqB2sa^zz!M3~g&v--p{y5qP}b62Vfi!8ZCDyzZkmfC%J|DRXzF216d{MR ztnk}Wiq`sf3Qmze)h=Q+QX9y$eB9NXOZ2@!cUEB6!7`%UhehDpLOsI45kYrMQX)Eu zBNP!KPXsrWHbjv51VL+{`tO7oiANa(;Cce69H0|w6rj{4s2KLgJtZ5n;r}2cs~5#Z zKU!rQ86PkF?#AuqP^Zoyr<4LTA$`b2ccr-A9uC|ejSYAeZngyFqqiy2vnX)2gVo?o z{MdO~o(rweK+2N>a(M6Ru1bP(KL0bS{yy@ucMXwDbr7H#bvta*fJSm1iq5+ z>H+9dy#)71ZNQH`NDFhl73$1Tyio3itFJq_U{}?EMLL)84K;kAXs10#>H!+VTx)OF)q>=Hx+F!zQ~ii^%`3BVLzs)yt=9ri1iS$I%=$2 ztx$^Qf;>))%W^BabUW5f@_36C{<;|^L{YI>KTi>;D)k}qQ7?8UN+1P=6hLA~w>?V-^0c6qpR@udeO}jH0;4)mL zh?h~sSXa{ggfzonBW#r|V2p@5P@rpd57LX!I|X`^Kre&CXO(fN9X-*UkX(gy9(P

lprg)XH+f~Lv0zL#l^*U?YNBGfhl2oko(I9y8eZNCP9K;uBb6mIUcz7mM+xMX36)#qqGB#=4l7385dfPblSlx z`C7;?*ui7?irc|%?T?~ctL}n~aB)^o0=Cc-dV4F-k2MQ$-a=I&>=e}RTSc`Rw4)%I z_Awc?(S8h|e)TAR?T#YltCS(!7-6eyA;KKsy)JR5!CkS+uHD+YHLN z0EUMhHq%tHWEz#JO05AF**Bt%mf|WnUj=x=DL@^@_9RnYnbg=%ud{P~9O;;O`BIm2 zfFlNVD=Ev|&^mO$q&ExoQ&k|^KC_eL={76Wk0DXsUBw7Uc2I0QSasEE6M3ljPLc`r| zg%=@&R-J4csGdlpXZ1ZS*v0ydz12u!-J-FkTj4AJW-)zp1X4=Io`Lg^YWdzx-iBd0 z8U|8(5Y(vi7Wk{4puk3;6(s!=aP2ml^b9LhdxD6v0mrnmcy6$RUflauELK!S|qy**j9KvGHjJ)Ge*?oy7s(7!j$?Xl3GSm z0jJdOLdhnSx`0d*Zd1tZdNNWSsDct<#LFwJvJQ<5qpoHQQBslRGP;_K`g$21Uzd@9 zG!;fo$mnlW54)I*N@C5d@Ye6i=6uvcm{byY1e-b~vj?WG1|Y^Bt)W|5;eCL^tRQ|_ z`cDnjt2oG*jACYKmD~=$U83qQs!XB0MVp}*0AQ^ohOD}ok;KVN)NSwuEH!6QB>`|6 zsSFlCX`q`BkRy6ZF{>-A{S=5m36G$%xf$XRKuzMHV$SiB{TA2?DO&CVXf69@crmc{ z{Wo~6{n?8E1!`+`1ED(OuX>3U$>{1in7(R6(mgfl=2oZ`LeS}RpyeT zH^Va2WPq5t*bm?`gAi#IKpZ=$B}uhHmog;gy%sRg#|HtgK30s@`gjOf#BPbd>M4lh z=JR1zOXl+&GCcqyb_-4YW-Ams4vJ}I>Obwi1~K_L?8U9n=L`$)0a`v40C^CbrMjTV z$!{Sd>{kV6fz*{8F-y*OjKD>O}|scEUGt;6r54 zh@d&^MT#HV12{>|2QYBnh8>f~aN?voIHQU40pRj;<_XRw;xtf~07uM$!*O^p!3<~( zTj3XGnNEQ25Y|l%wTAW3LnJ0V#OcBsElEM9ItWYC4vAt{T&|{w(=HC$ z5TvQ~_=ye#y}FIr0V;p-OKi;Mg08x{oaMlY*?Uks?KOxqxuL&7X>@K_$dJ{{=A9$v zZ)A|A!h`U2gyS*hI({bG6Ua7rnmUBCm&yrUQNp_WqJAUrk1uNAEn+C#zW*Kb)GY8d zQ!9|F-hn-;ukZsgszi7Fw6sNM;0^>#22sm}gHSc~y4t@08U+XotMCL@wVxL6AjmSr zsx*Q$3mhen3E-g}owHE%_J7+@HO~Ob3cbg$6k9hqIKjVI`^N&+ug-({+vNhvF5U{Q zMi{j}M|*wM`K75H!f3Rt=PUi{=U0H-#xbcRs83x6Fngw;KSlKL)d*W<)6m_*`eSfP zkWUi%xYQ6?M{~`sz-B!f-%nEyfu*=$9)2C7+Htko`! zJG?aJg9ZRMp(23$5+tEM=*5E1Sng5Gbm!;XEy8}xaNOaST_C7^PZF0q_P+p>>JPgS zyEbmuDNSHaoj0=1?IXaU|6t5{6rsRp{H(^Oz?W2Dbm;7W8A_Z3FSt0H0VGE{gvC4f zVzo~OWA!GwAN2-)>|7D`9uT#{=K;bhqfu+^&V-l2MtpXHtalmShVO9lofhXi8~`3! zPd4ygS@Vc%g;TAxlaA55c0=Tpp33Bz%X{sONcL3blb`|Ay^9yUUa zfnR~Db@v25>*?+S;`}>~Q>=k7-{Dd4g#=n4K%&y|08%qyuc`n)_HPztd|G7O&#*qL zGpkwP5+Y^-kw*;VWJU?i$vti}0EFz9h*A<8UUW4k-_edc$4hExq6z0fQs=nmK)#xZ z9#U$;d+-Vpv@n@G_pW!funx*r?}Dv8N;5jk3Jqn5=R@?VheS3{6}xQiARBkd>v~e2 z1jy^J_bgHoI=(-Du5BFb_s02XEYy*TI9#idcV-gFFBY3$&-7iQ~PKy zwYG4PT8x^=?MMsRlDj8r?garUw~eq!y9E}sQ7UJ{|4T)Gmxl0p=$Sua?K%9Flmkyz zq2OmwRRf;a1+NRL2b>@&D6eJRY2cjdo&d8B*VuZfZoBLk5vYg zdvBb?c%SvI@2|*m+!o%T8eUq9I9$8(x8js7=2q@dPm@TJ_U$esom@?)j}_|6P@KXx zQYdgKbTSmK)fB|_Yex!yHx)_x7L^xY;lcla_$Ryg`{2n0TS9`K8h7=6Qsrc0v>1L!nT~>FP@c96jAjVCv~TD9^ry+;X-; z4l8^kMs-%%zhEK%SP$R8!nkv)a>+DY`?+czcxEN zvDKffFs}i$%J4J@OVd@jlP{e^OfkiN`k!-n01OjzIF8~rksSWb9PU9uF<%Ohvbp6S zsB%vTN*S5lu9nuLI)PL-JVCw9A=SGas*3?BGAC{UnMClr0Pa_F@N4rz1!Shi3fTzB zir67cWr0$$5_HGj9RF8F%iC2diPQ4xu4Y|B^4&=u$jr~7`dX^9$3;+T9;ZZaLpjXl zC&+`^hgQ^{q{aKu3h`EQDWM;%u=q}8qXArB#JO<1Nh1gv#}x5Kia3Y-91(vwwuq*+ z7I?qNccLTTV9J+6`Cf;uAeRTN5C%0`eNijC&wn+=35JLZnGd*_Yw;$Q!I7zm?n8yrTU|atEmvj z{+T!>u>)3!BMLDE8(Sb_aGz-kZcQL|3oYTzMu&DiIqKYSQ$)#|L59(0De5p(N>Vli zl43LppH0yHkI^9Z;Ws)lKZm_p;Rx7Z3|FE23ZF(Tx8Qcm(WbcsUk<>r`K3vosF{d@ z5_7S0Z8_HR{i6d(fK<07%qNjQR!PD$P6Ap(q%2@cHB+=V#khrxdzW$X3t@P2lmDuo7%ad% zVz@n0&4*=x)w#H25qJ6bStDcK8c<3{i8U%56ZEMx7^U3uFdk(CpUkKJgnb2DAn-E- zDG1mMG;`+XiebQDb06?(3$p_ApkwtZJO;#_hq&lX4tXEX`DH2}M8GD^^C2z7OHtieQObxUXs`JI|s*=8s@+s zfVHW+z#%#cnVIz{^B#i?Ga(-$ZbAfDG*maR%gmlkx~G$EK#fKc$d9Z`9&^3K)eeeZ z^#UWw=C;bly79`L=EIaqw0XYucxC*Gm4cb-Y`9g(Xf@dHfml$$lHbiJIpRbil||4QgR(nIsKDlGHL-C9t@Q+M0J78a^T7Y^qiy^4BAf1^z3X zb10!U`~6W+WTzh3@8ecCn{Xcyu5?a1H61EzLLdY#xC$O^0DMx@gy(!%Z{63GDjpyXe}u>}wT`nv*1a(|Bi_8njp z&(V)WZx}}x6&`A4~i`TtohEB$lEF#!4HwEpm?{~w#xSZqXo4`0Y8c+ zHQ30h(d%f}GawKg2DA!&Y76t#1vE~MulfNpu!EKS9>@TrXrXUDxfO*P9qu6c3eyBQ z3BYOu3_se-NoiKtMV-pZR_IrMfKL$iEL%Q?;6r5~MfIiuMtrOB76=-tyC0WEDu!bT zHQ-7!Ly4ufxDC})-!a*p_s2$jK@DGwHydz!;S(cJEI)QZv0(Bgx-$_Q8~zhePtmAj zR|x72M6KjY??inMmGv^j=%VF7*uL%|8b*qW;)Q33GE`D|fIw37k&2r`vv|EyBvkV~ zY*4xkejM_C9Cklg+w@KU$!kH<3y61o&xbg#GACYYwb@%3{{-SO*vNj7AE}gCmzs|k zoT1P1J%UTE{lTWS*-HrVST~aK4ZwB3ZZFq`Sz59}s!BQLKh(SwV``E#4@tVJgcLH9 zU#kDG&MuJhFyBx>SJFBc2vTqACiF)Fs!j&KXa{gv(wV3gkfGnLz~GfH@s#$MFu>xK#^fl|Mb?uC zX)Int=GQ*}oc$>Hs-0qBzK0GWSC}L&94fsGb1f?qxT%a~$?pb^_sMTG`=dayHv4kY zh+c#ytjGaNE<)Xx}ub|KSMp%;Q#)flG83f zc0aF9bb1!uRNspzrs64{5=nKgAk?W-;;Gj{BBERL8pfU2@p5JiW(o~*&Hx`;&G{(+c4!Pn-M-!jancyTIV?H6_Nu855 zoZQ@;C}or240!||;|UnBeov<#%*@pevz3F0;^G!kMrbsW=FCdC|G>ba;N=B@%-{sI z_Q+psYSLhF&Ox+=K(zhr)%Atta`Ah&n_vp-2C=Apoe|E*ZGZ7jzc#xy)63Bxs1ciw zn#UhVR^KQJ7aO;kIyZ{CW4Z^)sTnx=RSJI1ZIaL??CKTdMFiu66?J!8tRiOBQDEx3 z7WN`2*J@^{f|c>xHuW8x>Q+q(wag*qs{p=;ROhLXHKdDIV9}sxdn!TL-0CUM$Y!Xn zni|}bI@CZv@!^r@NsVvr2(@%WllNelYg+YPpn(N|ROf?mTnFev(}Dw4cKyh%Dx-d6 zQ`NkFB=#O9=v8R;QeSx@sbasn^f0YpR5~8-7=hrip8GjVnhV+q-x$IzSRmpUjyyUf z?}{vLvdB0 zD!qz$^uRG`zBm%UAL8-vF6dj8NUH0=vvKfkwdu3)GGckif?Lb&Q6R4`CPvkF$4;{> zXdUgEb%V^kmo$ak{hWx(}*x8S+y)|U5_RM`dlXo`UlWK|tKc7rnBLvuC7!ji)Y;%0$cNOTT} zii9z>7X>bPLp_GqAp^!Kgb5G^XPJZw3QqTxyovZx<{p_uUNW8bbOB(a>C|$%Y9mIM z;b`FbWfWH5KyCCO&ljB`C@A6<&<19KsjmQ)u9hOj3qw|q${Rh zl9>JxeTOHVm0Gn;OqVys9QiopQ@=uGMm}v=5$K8<>8`FuW~g*2mzbIj z?a}=2fQ+gyiygHgO;s!*lv^7#kuONZwFE9oxYoIu1@g=9$VcEXC8$NvR27Z9G68vy z7g?TQe<_Z<#e*zjrmHK6jqWWIdNKuY{oiH!o#cm*yc$e0)G|!P z+$VyYuG~_V*Jx4+3OPDzo>C**IBIZj@=nq>$gd|%-RsTerI&5L*1yTS?hW!!1I8h& zZ}q;P5s;5FUit?4+sPpA>C@Cqv9aASjRKuyR$mtMo1S>By6WsVp2*`4%l%AT0BZFy|n;V|S?JAc{CQ6qaG zo0&pmL&0y*`llQ>hOE_5+^vkoA3o^v8c?b+wVVR2W4Z;m!ttr561y?3;o$cUTI2%g zaa$f+WpXsSQ8U;V{(nh^{rGWdIfXAn7|eqF?*b3j0%BY6$_l6m^LV2wqz#eVA{Z=a zh3N~HU$wee7e;mTB48mKG2cI94G=68aNcAoV1OTKi~^RoEN-nq)^q`%LnnpmLhC?w zg`EU3*j)8RN)WgHRbeu|F`-KGs#2&``)}Bh#};V3Do@%IS^HtH*i+Y^G@EB0A!%c~$)L?yzb{9i{I8dbn#0^k}R^P(eUXYaz2=^UDZvn6V zMU#q8H*8qhi@Xpc0nx8$N%1FMi17{t_Y*~X17ZM|km6#T>P>GJxQCYAA5*NL5pzbp zjokKN6;m@f0gG)$1MpXzuo^YyUPo>2I|{AAPO1=mQh<@1v#{|3X_Ws68qTubxL+`6 zlcqzGoIwQ>%KEwti?7|tEQj^f3O|sB)%TmDY#cAM!tbD8w93kHT8D=-!hk6H z4%!P zVavxeE}&0ZMMlVRT1dYmBzbEg4>6`$KpxrX2q6P(NAyVXWPG9m7F^yO?FuUa7f^RI zH(wk?F1|XKx!`V2EA$S+Jb6uIEA$$__(JAbE3|=7jzmm#B^s+GdL5QYwULgNXrh+r z6Ea!|MpWAtw8HijlH%NBc+xN`=yjMM6ZcW47wbfvG8=|au$9_JlpGz4d*T}l%9UvJ zSu}gm@e_3qdPO^31L3B5o+H4$gXtRRWdPZKo+C{0%tXEqUCjdEGZS=7 zoM$GI=u|{}uZ@S=RRl@fwh+mt+df`>k{l~kJAlz-gUEt(S`SpbsJ z6|$|uJiPB4QjWiFQFsaZlo;sBN!SkJ2T2FY+x};=S3#ixgqyE|@H;6QYj z#s|KO>W8)!5f>r?a^>?6RiS7b+w#~r)Aw8B{9Pq~OY*kU^({|hqR~f*or1Xzt8BZD zghIrs3wUwT8fd3UaU0yJ09}B34%_(JyfwJrg2q)kY89t4aq(YsH5x@v*M?wyXa*&D zt5Tv@0&YEs_=*QYX{nd8=tm(!{H9B&v{Se$DN570hv-Mu=B+;liytM+8f-hk$N~&1 z@^{6=K1%Y+Q|#_gag;k>PS#C{Pkkgdg!-!WxgGMjFP==L4JE0`Xk9!np1k)RXtb9+ z;&l+dcyb1tA6oVSyXZ`4&w1TsAAAhl4nGLBJ;S_$GSx?G=fj9-0dh*ARx8BET0jn0 z0o;dg^WsScN)55zE;AFds)4lUi0|G@yftMewe{P#f&n@&kq%!xVLj)p8{3p(!tBy8 z3Qd#q;>m6pCKU3W(E}1j0;^h#tTGnALF*pkZvsBYf;!o|(gQDz0LuxW_YG`8FzQn$ zhG5p$w-qgW&y$~bLf!q=u@tu4za^y~7?#JK>e9~bOaxI*Sz<9ZV_YNwd zuY4%=CQGP+dJLa-17Yz3S%jkKJ+bM*i{BP7esu(eXMc)RCWLs|Iz|kwNy6*;Xc8KQKNu&7r4m(1GO%VlG$B9Wj?v%$=+Y@$4^l%}cUhf=|_ibv=3-b?}7b z5&`bT5K>YwR;%mT_u)%FJ#V zr#8GWKzB9;3}tnXQ~8NhhHEP3v!llc<}&6yk2VkNvMHcS&A@sa0&s-@IC^*v^3>78QBvVG zTcAQc03QX2qL-Sl#bRHz?+np?Hx*3+E!4k&}XK6-p&NsOcXwMCcHspSRuwX}}#%myC(&LY`B~UK{ zLBzU`DM?}rCaO;ORe!>S?ER;RLej194e)aD{tAAzLN@A#SXnFt43RU{w?IG|=qMiW&?zLyLscw|AtD~n3%C}%I^(2{Ch9Ib^kMLLBNO>;Q@)TO( z(-11o$FAa=AqX7!DkQ6u(2LuBGz@OZdP`hKW(*!ro+I#9b_sZ;jqr!jQQChFmOM_k zLfv1g=mjCXTA3m2 z-v$7hs$PVfL%4Z_(|2NpZxP5%C^&YobMP0;f;T=EICI)`*{_% z?^ox5tzE1^a54XlI)sb)XJEOx;)SA>VkHK5L(8+9mltB-d}+ zZz1MW#MDjuFu9!H=~r)MBHvPw%lYRUuT&asxt!mDn@YGV<3#l3{7&LDCY~K9(gf1` z)r;)=L71h*=AG+8kB=1S=*lKCdgvedjaBz{x6%+G;;6nCk@dtHx{* zPBb%%@d32^MkOD}BkJ3%VKYEo-l*Ko-HfG}ld6ERJ8x7jpoAwwHg?$opxJ}SsU$WE zmfDqkT6D&@RJ+Cw)pMoPots(s6sP_7K*7O1{Ra@jz^;?Q`4G%0NgD^J3^`Ee6KAK! z8D@oF5}e<38-*brABZ8&e&Ofv;pjrGLw@Z0G~yYUX@v@lH*4YeKn#(db&%$f(O0NU zY6g)eXruxw%-7hgvZF_!lr-cM_fBTQrM1d-qINk|gEvi11eT{C`V!>TchD2!=BRxV z2+aUXa5pulF<^AF`XPmQk;(c>^KsH^h@1Z_?XGZ+y8CtmqViyW5S?xB3KBLQzcil} z$Onq6UJJZ|1^4*JFfDUCL{m9jo(pOChjl~N<3j)aPpsqY;y7JI-u-_XXBH#s< zO$><$PeV4Apn@pGTMD|Wsf))-VlN}K^8!mMhFVtHuk8%}^$tE?+9Ccj;_tZ4=wSo# z#|SOsg2YiOa?_B5R<$B4To+*N`>njbq*~7WnV+&lDhDn9r)$yatFS>h9`@q+FZ~9 zQ#?Md;Hd4xX)y2jLmgZ3shO^YQ1*rWA$3VC0RIOetL!Hr>oVvrvP&B@mykU*WDqas z0jBs24Rus(SfCyvRBb<@hnuXU3`uEz7KgcvFkfgG++^LQ6(~8+3vU#tDzyn9PTSX% z(Cakxl%h5Ieo{>{1ZXiw=N9WPp%MEo4SKy59+Se%bO$AXn@TxVI7oMPFLbMdP?>#! z#<{@?oyt%gdUzaq1ffqSbcTk;J=rZZG}@>?kiZg1lKl4tksP`MR`?rfG#`L(hF<(Q zAy=)IK~Ol4(@5<@0p|2K4!U=s#4jNRHw_*@Du6~2XdQv%j=>IMXthNc)YL!QN zEmSvrs+nk6?O7Tgw+r5&As=xdPatFy75fB0V+rKkD|i;clGJp7f$mD=l|ID}DE?ro z+DYi%0!^F6Wfg>Opz;AN`ZqTUra*NVVh(YK>LkU-B1&@%ukno!(Dm;C~!$EfnH5Z14zv+VB{z_kRt z1(z7Kg_I4|YCwvVrKyiyhaOKZc;nMM!8WRfg?cV)^$0hPOh{nRR zU6N%k$p%`wFTqY_ljKm6j))!`5E^D};jziu3N1nox7y|M`5K^L~HcpKbK} zd(=Mf_c^cod7am}ywAny6nLe*m(u2b3Dzi&#rReCk?(u3fE1qhK!~xry+6-GlR6ed zz=~%?l-o2ui+tLFzBv=32OdM?G(p~-iQhO%bf@z0ACY8{ffVY z`jGOk+X4BX$CL}i!p%~3WddQ-zrYvk&7f_cBFue+8L(ZPV+x*SVFB(VoWOL#iUX({ zfPjKGeI2-}ngDDyjwE_(Hn@+lO(aqmFH+3?fNw*j7DTE-P;(#QPjy)npLL|u9RC88 z%kjW{z}pX}Q+w&KpR^anlCl1QPhl~swu^KjtNkh>y+Nc$2x<)Y z+IZ(N|BkQUsR=Q%+=P;rk2B~m2y}(9u=l|D4u zeWab#HgjP7e!Ph)>Kgz`y)IN6Sy0PSvg{4PJs`t+;L3sV^A_MK#A~wVF-V}VRF*zZ zwMB3-$k&S!b5yh2!1z&;&nm?&dKc89x$kz^X>-pJo{Q9rz|n4K=GyN2%t`Rfc&+zA z%ZbQwuh*N47c~^7QiJfvZlk$P&B(Fxo zg?rBtS>G^APwt(@quKyt+b^{hb#W*1$5l|a=1%1MAOOo_J8k_pI2l}{xT@CvOofrXmD zwdoU0Lnu6&dw7KI27`$i=Vlf$bU9L-(6-a_AL9XW+P(UD;aw=e3|2U2QX@%>$c4aC zLT!*2YH8BSblOhTboVM}`hO@Y)SBkLjpjh>WNv9Z0bDJGY62+x6neejj^pBgMR8bp zyP*&JzbNoPEp;ED)eg4cyEGgQik~8ITwg}=v-Y4|oQVv42{$L2KOt;En zw(rIhNk9F4r8?#VR|>(L+FlD1goZjgwug>806_v{kOO929A=M_8QXVfdX5*wKzPcZ zi#&UpmLb*(j^mSPKbY)teS^;TYXAFTt^Gli7qJ&G`Xs{yV7Hz>)U7qy)uwKirdunc zhn07%rBHU7n<|b7i=6v{i;5uR6B;6m3ZP&vOiE^M5Li=^;SH|C!>5cUg}G2925i0E*r*frGdtL zWGaX2nWs>0>S`c|CK`E~c}ue5_1iN^r#tANB=c1f9$@kC_1lsi$86O~nB}Wu__d4A zh2~kM)2*Of(GqTMcY(KQZfn32YWo&Iuh!7FWPE`oDCqd1pq$FJT*Iquc&fo$M;)Fb z-hCSHCM$Rop0LO^tMnQxcr~ASo6gl(bc5$iWslW>xVUrxpTrM3(}cQ-l^)q57+Lqo zc;*_*%`qo0E`>MyPIvPLkfpz46SY*$Jlg1&0!KhVeiH%tV#tAfgpg|islKK1JLn7V zHUl$#acK_kOTs0xNU@)1GOsVqX@xFW<`rtL1S%euKMkdg;HWPVJ;d^fp;7Tx zQ{LLAsMe`U9SG2VGm(hvC6WjP7@NP(fHH#eA#?dmP8f0R=Mt0>R~5J)Bm zQC1xy0FT-Z;A#TK0#J2g6$!g!ea#H<4$NXw-zVH}8$b|sv`~Ex8|gc}P9aSTRa^tL zr$~J{0mObp9kw?$q2}vEuh;R6Q)l6Gp+x6ivxP_twRY|?n~yhWj&Fl62*z^7wIA2Tt9|JKN2vk|+lRvPlMb}+6ao0JYo<*E$OD|skN}7wnzwRu!yu2Vv!H71ntieFw_=_9;{`HI(tPQ;EKMT zRA+&LofS{(eL!0TZ^bh`hQZPbPU0IpW{KEoEZ(%oyo7gp%<4a-Br%!Ul?q8uy?78r zDP;MqWsBV&NY3@SaU_R@NRJ8eD$J2l9N*>oTqjDEL3->hk<3NRQBGP3vbMR)!_fTUArlLO=9PTCb+6M@yzs+*=5tFJsJ^gjo(NZ~1Y6R8eyYSzR4q+#N{Biv;p5 zDwfj>GFy2?w$X1iH_boYPWar>J1~oyVo(z z?SfDG)v1_uYCzu?){}!ZT~j*L=%)jDzc6!}r6qVlLt<+X*YD0p6VZVaialY9Riw&p|iGOq0Ig zWF(&+0RrxOZNi`eA77+Squ@gQ%w;DX2ttk-Ei(V$_g(?n0}w_`c=jT-7u ztJl(t#Nk(wobi-JP*k&LliXO#9yCkx}+#v(>7ZkqAi^ zNq=AO$wuEFJ9u-e&2#(u{U~&Aa#l(BEAVHUFTRklwFzq!{Eu661%A)_r2Pl}s?R>e zpHJ||eziV*e%y1)8ga-pQyQgr6FpAeGK3AV9+b9;BRF;(w7Fw|WeIj#{-T4ELE+Q>er#p-1e z{vQdOdqL9p>@Mw`L}jjj4;JCE;!mU0fhl{V>I0igJnhk1Dqhy1QB4nRDp5NE6&-u$ z5{}>adD!j?)S=L;yC_*OgERZPWrxu4-4wo-i?k$CWTux(oSK$NUBGQY|+1*6jwQoSE=1zqv9fs`jJvRLc~*V zNAkQ*eYR2C%sz+@0WkmYj7^#2J^Y>|+7_TWa#Hx~)Z;*l6#fB+&@vJ-_hmeFfHC(= zlpz|CtWsRMk-=Qo@1G_0R8Yry&s>LzUTHd1Ww;5Ic;FIZUI7RvXr)wK%s0J&UVFLg zwSv={IQ(oY)O~$Npw>blOzuC)+Fs!U!=~bDJbHU9ocYCZaH~&Zsop}u<_Jb!?on7r zym28z?U~}k)?_z6oL}Fmc8gYv9qGMeQK*pXA*5*g8?Ai>;N^bk^BmLg8ci?`;Ql}- zbt8UNGGd_JRs?*C0tV~y*|qkYL^!?*fIR`ordYyFC)Ad}#8h?^!M`^MVSQy=6^92W zu^JO`L5Dg4Y&^7;J3&-!f^blych&xcOnK6;UuoDn8un+tC15zah7bIb{}#aw*QFZv z9Q6znB_hqjlL?_0psXO;bfmbZi8PD%i{krKvp-<{fv)Nj{01&}*j&vwDtA5~7;9tM z=rg_^#AhhDDDDyYPCs?G^1k9zI0CFE;dS|@#ER52tgl(aN>AJQ1RU_O*!&qjpUDY6 z8t6Jfw>ZZM9tTOoM#tU<-GoX!|8q()5fD1|J}j`lJ9!WwkJW^q9`nNunu|yeiAXi@ z%%0)Hc;gzNW^B>K=b0Zd6gq;?iXoV|^EN!I8jQ6vRaMLudLBYGy|o3sRX1^kYO&M* z(wmhM(M$%C0Hr@0w8E?D5h^-N85AIiop8cHFM@IOr;a0(>z$yB)JSjVfW14yzfLc} zPAy-Ms{(oYE>kaKNjicw(4Z8Q6@&SGfQ4TsjW3lI=))EhAxxy5o1>!u!4qNUMe275B*=VuU4v2{-cZG)LZ=+m zJU}|j@jhP(tbs5WRw~1neI+PqHy+o)%$WTcApB}6{(_p8?tD;JX^=wQjz9J|e#7J! z{+vO0vhr$glEkhImpj%PzP=yyJs|j z7Hgp6R&XAkkf8>nD%tD}fcUYDdo%Y+CkMBOj6!|P{N1?MF&vBW7{q`hh4*va0=IxG zO113ah)nYz1WnHuyLagj3CPe@?`6Ca>JGS~YE9j$Yxbp9kk@Lej)sv(MZzzPq&g{* zs^3s;N~&MrkDU)%Pzra8EasCw;9oW#Q}1747|wflPz;{Bf)vwd`a=`^!rx)E0pO`- z10d9&6<`FBSZkc`%|lRj_LSFIQ?|m30x2p7F9f|<8(uBPyWLKUf?HM|02Ho)0Stwh zWP})^lC%&A2@s-Cy$2JhRz@&xqml9L3885m@+DU8U*Oj2Csxb$0e#a7M5qOpqOP2g z?o+czYHm#_$}{*X3#;IEl!y2vg_j0K;Oeor9NjKA4B0np1l*2NUwrr{^!_OOQgVR- zZ&UYzzsG>bDRzXl8F*@l?AugzqMa%5Or|*-zQ$%GTD8S5EqM~Z>NtGO{*Dz@51epD z0ydTNBkU9}FUhTJ;f)zB=u1W(1jWd!OH#>r@vF{492jvkUdVkmU_+C=JeZn{)Cfno zg#@kv4&qX=s>bZdt6Bu09|1sonjzi_aD;Dy-}0BW@M{AuYk3qpWB5(2^%MZk(=RX0 zYLKHePPem?n_F-vNu=kfZP{9=|PvA+y8?IR4=Kz`3z>H-Y0=-vQJfmrl z8JMB!e}>>_5Hya9%yKQ}Lp0Jv3SeaZk2_ZczKaMvz|e00o|HBIYf+w*s z?p!$nfvvnju7x)OR42tL+5G`Hfm=l6Q=TN9izLXFj9K4tSTo>U*0SaKlbkSQ@4${Fi2IT2 zMH1S-Ot9Qdomnm)$^IJI!e>6V*~)DySdY;F{Uc$G??}r??u37eGuk0ubgG)JNoomB#pi^%5}k zUH~0H^bCis%u+|hsJuBw?SPMCh&L0|f!qNm#YHF|GBHZM%b&XHF-^aL79c@lrqZfh z$@YFb+gpRn!|MD%{T@(imtcVU2B?5OgX(!PAibwHvM8N1!w%B$b6W#}i~+%m6COc+SyBSwM*|**)J#O=Quh+AF8m?Ds!&x8 zXW~o%U{Po(!YPX%g&F(R1t5bfC2&JYDeC05JgLw>;<$d?P;z5kP+f$h+Bsu@Yeqb% zto=(h@WTUH`}=NkXyoYRl}SRQ1!*)|XJ~8&TZ9IEZ$VXN1wkG|oTPtZ@$%#wpilOiWE~Ahu zHJm_&rEv|&{T_0^gWNIO68aSsu5c;HjUiJ(0j|-f4a&CqGKa5ZU4bl9J(Sl(ux=9) z(PuI7kRYB`gDTL5BAp{5#g`?Wssq;N(?BjjTLK(@UL2PWDO?{}>Ts3pVr08qSv)x? zkz=_$k=xkrJW^Q+Fi?;iN-lLNNY?XV3dP{f<)Bih_y8&89+BGsqwAD6bpldRr`%go z`cVb-p{QWsI+1yzhNB81z?UyMDoA#7j{v$(VI3VbK#Owa327;e7j1&K~{kH z#^4PDP-ggb21aXqyF|Yk5<~TyAwN*R8G?QEn-I(m;#6jg2YDG=3SLUQFQx8_TOrhI zL#V}>u++}CPnMMwYBra^>iVBI|rlZY{FyE_t-rc|#LmK@K zp5|xlY~M0XrCNGdmr5N6t1RhaO6U3r?iZ^G+$-WCxo*zwroF`@T42eJKhR2DwHVj# zM28Lrs)X!7)zEK&YN5RWU+Bj`_0V^L8lhc*nxP$mTA?okF`-WbwL_nbPnrK4&v1?N zt6^QmO@2rO$FeBrFmXt@lPT2rkeP+~GW0>> z6*?>UP2eSX4p{;~JL}bqR7_uX7)d)4^-0CVW-7m8VsrIu#l*(yAy1-aUR%wOH19PEfu^dG zyEV>@xLZSdBsh+{xF#EHIRh_F;kE_WG?f6@azC>)eUC{Xswbx0Qx-NxD+4T5I?%*Z7R(~d%(=NoCaB!U{f(aElE=S*2|=MrNLeUP|1>NU^zu0Ez9=GbFQR#*WN$m^qx_ zGmz6hqd2oms5+h!(kCz{g*g-OeqMTt;IzuvqH#ttXCQJq0OuUZYn{)Y{0Z*tii)k4cT8dXw1XLu99xuv@GSOFw|8L&x*eZe#Td6L>F??gI9P88BEw z9*nAZON%^~s3(x2o)PSbA*`SY0d+#49o$Rtrfzl+bX`GM!Utj9?O=^(2y6;{O7Za? zF>6>!2mPx$Qjd7%=&r=DlJ+L&JpShTCd}1Muk@@2Q{9PZP0%lrt5@HB+UXZb7Vl6o zT|1{^X3ag+1%z}j4V|-LB+&$LSg@avG9R;JZq~)jI(g$Rcd)9R%9;K=Q=YDz42Q0PJokr9GK=zRV!aFC(&q0ydPYM%RRFgBeF|&7Y2@_}U(5dAPDOdru$<&e;DfkpkU=4?xcn6A|P)Oug)@hyM_d9%v&Ddv_WUi( z3qX;slHRf$mpq4%>=(tcaJj=!#P>lg7znTh2%ac4KZ5sufU0QfLqRczZQls0VR|zt z^&p2{IjJSHbvW}ZQdg@eHIK40>IoafH1YY zDRZ_%P4=#)chfewt0KL&Y9Bz=DS_AYy`&n^ zCqH0{vH37H18?@72v#WrR*LiX6Yp%})DeC?X`*E#1Sc0T@DHquMpFSDHLzG5PFZ63ihBV3C;<(+{VnM^86NK z<#cRCCO=~909*k(+_RCI#)CNE`?Em^sRdGz80Df=G?Y{|n2vL=BScz3k%mJgU=#rZ zC)!p;V_rzXs;YPS11n*A^HspuE1(;!cb}D06ANgpyjxKOCVxKj=jnVLaFvWWXXV|* znCmtV?~&Kfhr!DePkKG>#1qN>0@)Sg$@|1yPE2kR6HiL#+BM_1lKqg*?g06s)9bVF z)3hO^s)y<_r6q*)tKmque`M&Bedz4;;p7fjP}^@HfYkS(X0O#SIP7j?4TM}{-xkOR zF}Z3}sYd~*-XL_ghQ?WetVdQ}bwqDX@edIV4S{?;^RrCas0l=zNyN*DXwLkTy%TwJ zWT?%;Top#e;%7l^r`Q^E4&#r#lYnO1e}*)UyHC zA?iW`^0?U?E_kr=u0h;UYmtNIr9eB0Iv*$^eu1L(?8(CJOR2{rrPRvcfhsE!>y%gv zGz!%3)T^sttq`owTai~irg*y-Dw!m7=tW;t{ex*A`)F&C5JwB|QFTo@j^L$?xq z3xNiFE^O|BGP1@p+=G$xmYwJxr=B3nTRxlG!>I0-v`v_KeaT;PuHW4t!B;BZ- zU$}ljuEBmJa@T(l!J^RkFpW>4hh0Z#dPy1>hqku?#%Oy3`Q9i*wup_#p~6~u z2k8J08d65ulK?eXqlndoSXrewX8J^R;&75NQr^KNU|L?B6Z9vL{!O5YpNPDB@vNHv zALQKtOv8C6ENHJL5jpGoDnw2>ISP@faagN22$iFuuC;>q@JX7Y!(mF(2$QN|uFLq= z%DamlF@gFr43$8riwHH~vnYB)7njy6VW{uG+CEp)!fNz`*zjlNRdFF_xsZq#SG9EF z#lR|v7pVuKTcQ0kLsM2MPGV?N6$Rf+3o;aldSFmhtp%XHMuXurhGlq?(-`s@PN9Au zVItuq0ph4v2|rK6<1~geJ~8fU=$J5c4MN{f=&Ln!LyU1ymbk`3p_!1+SXeJN3#jR6 z(m|bKSXns^s^Ozvl*fs}!xQ|OpH#vELFPsecxW16uT8(aGRT^$j~8+PAaT}we-vKk zXO+R%P&K{qJTDC{ta`$bA>8Q2LkzP@8)4@H=7_93x!h2SaV)S5Y%`Y077clh6bX_E+Sz$^Esz#Vn zJ*2C~r1TGB14m zsRxqPVjJ||$Da_-aDh2uBv*_!Sj|R8xc0up+AG%qcxvy!c~0$>>~Hb4ref_~O3b&A zWsXJ|Xl`dWz20TaegxTafa*4t#R`yB675%~1V>k66-O~|hCBxC6{1}graCA+NhV88 zHdiXy{lZk~{C@Sim*NJzgc?gV;BuAP!ndHhUj>n2&*h**4jsK5eW}c*+CVe_rgvB; zXP|KG>ogRO8NCEgR-UX<6;o~mq^@FvRWI{g6u3lnAo24w+MtYfR^CK*?*%0%OuQjW zzBxfpHW4`nT0zAp0i0~;6<`vy=z!)^6u4M@foF99f9x$9YZ~gm#&YUtitvC77X-Sg z#e{#K@K0%YoWJ;6HR|zwxc(#C)c@{kI$;AE7Dp9c5lNf(CFnX3=&6$NqOKu)KMfzq z_$-r$sKCvZ3ZS^z`KmEt8fh3DNKhq`<{|+Vc@xzi`$4k?;rC<038iyO#><&kgQlZh z0C_ZeKE{3<0c@n{rdAV^*R|MhXw2I)3b0Pz9iP+_HX>0E6(rnT4TsYqa{y)K1^6z~ z|AuT`venepcy_Hbns}o$-W^u3kBjj(GT^y|DRN3=L7=;8P0&^v^v;a0Fg(XJsV4sr zvK;a!egoKX4#3PV``vZeeg}G~+ZYv!C5OxJtl(#O4)jr1Fnyb(FGe~hk~;Bb)FNh1l*|_d z?_z`3Pt9W1V98o1cr{SFuu}-WPTULBL;@rTz!Cste262#@vBXc1+~RqoX^{|w<^v! z$c#y?jV_Ko{a4iEv8w%j2t4x({q*A`^$im3uN%=!FOpkuJ)fnp`cz8FBB=yTYR|o4 zQhn8YlA0%^UZPwpA+$4$Qz2wll&b-Wef^8bwZKEHzueMc_ZMOxh+OSlxt3H)sxe8; z)1-!YNcC2SkZ6}+&#&2gobw1A#>)GKDWd2Y5R`p6G)Z^0iSPvi|E;io&4p|ykYy}l zLM|laQv&$}A#*q)wDPL4EfLB`0pLWk0G?GLK6IlUT*1T@fe~uF3s6;!FwZM+Xy*Vt z+ZPJuw}dh`^ICa##yXUrCAHr81EUt;Yv4OvSBK&H%xWo?Y~tqR^K2gQgn|EU1dbta z+33R1K7;ar2jz9FIs+NstxR*jhd%SN{;nC5Dz|U7-Up#x!M`DoL1YuR^$Dbh?S`Pe| zujYfX788Kaxqtxzz9WEYIEh|F#;r7C>|^IPX6eddANxA=->p2kQAc;+{OPqt7rFVZ zP%C%?iNr@prVa{k5u=JLhPs9>^)*~hHl{z#uQgm5kB#ZMc$O91&MaFi z(q97vXubrssw{np%GE|?pK>fuQOajx2!K4EOqu%A8eEhNV*tynMM+EQ1GiR#jpxRqGez3Fh-e(A)hiPX$K_XN=KX8#6 zLn=Z1i4glmESA*H@(kJL|LBS>gn2+VO&3U%3r9jtw7*wV(GKY)=%*bame>`F40kEM zNQ&19MRf>2>JR=ofIs#Y_H6WB6~TNwb9dl_qDXU)l5-=_4{Jt|c``gih7`uX|HPs~ zE%K{maO#J!$Rv^8nBM4D|C@oW-Bi7Yx*R0%@m7*&B3buy^3k~TLyl;OsOigf3BN_c z%Y?A%4G`56f9!f9^hXpkcmmBEt-ncxZX=!2&br}nI(xH#Lvyhg%tQV4^JuljJTru> zbDu}6H_4CIF2K;|MZAdj2nQX^3Ie0le58l!IHc~!n|ca=>~!|e?LFnr=bU@7IA6{&YNP0zay3AQOh(mWGPF- z)srkUsIzlVm@ThZ00Q1$g|aFa@P2g(y+7O={{e}v!4tJq_{c-tu)*Vz9yWLk z-V|?fv8xH!T(QBQ==JKjcQf;OjJ@{QLXcPAczvuRb&=pK*J&kx4-pF0*Z5J}@yA|C zQUjI>*@bvUA*e!R_*E`laDimMD%veV2*YkfcGRR%;UzJ!YaDh<`Nh7Nb@Hpnk;>Ki zV>$6Ok}P<)m~$vmFFezY7YW5@@cqilOTbeDKVf%*{u+CkJ6@S0F6a;s$gkco95 zpi!U}hx6%yp%mm-%jo0gUlY#%29NlR$<-SU_POEQCz%_QdYq24rwA5EsSOKcmEtZ1 zEGIQ3_ZEb7YHM5fd6bIBv)!0r`Vxg;w2PAAf(=%OK-a02zmdnU_(19$IlKU-%A8HV z{7~$i3k%DU!;W1q10~lJd6SE(lc@W!+SWwVF1aEwQt?oK?UL->-i-4sD^ z8><6&aYWdIXZw4OPk3!eaEl(PI9g8>mMm*DPx(SaqF*<))X<~xQ!XGxdxW9L)seZAk?+j5=`H+ zkh2uenX~XM{YLWU4cc$;0b3;uYIUMkfqSne>TJ#7Ubq2OmkX1(MZJL<|vNMS#Y1n(rlrkdbAR@ zi$+nDAxd3{9~yj;{Ng4YCRf4g$tQrSR)es8jo`lw{ERiYwgSTqh*izNuhH=J)fB?> z;s(33z`suT4p!dYe@IY$V?>-s_^MdY){F3$5&i^JNEz^&$j8Y^P=DD#U#+P(RMiR1 zqnPb41^O$2exJ{xO;2P&o7)60jtU)>N5)2UOixyIIt^=pV)H~{j_3+hsz4R0L&UEF zv7TcYet>*?3W@V>il84)5b8q0M5`o&vcW+Shl^G{Bpsu5)fY7Eb{ZYWJ=Norvo?}L z;YT>Sz_AeS5PBOR?Avyrpv@6bDen17sk3>$k_CbMsy8@<^oiQi0s4$+y(>k#Owfvu z=T}icv!6n&fi}ae;Dd}hRn!oWgvO23>#(u<6p;1|4RdkEx0y`=(Mm%!R`Ut*3L*R& zVz`xaA)c%}u1W>uzsLivc<~}Ni;(R#{laOy(hE9GJOMR;1 z44kzvh}vBU+&RP@@DyD&6FNt$uB0CwXs(_l%-e*SC@>4f;kaB2P&G7E3w1l8atU<- zq2z$1)_fADd=41_)~-N*RiDqCz6zYLs=Lqq)$y-@d<642IQyGs^Wl(yD@wbc0aPN51=Wr8*$=so~BN4b1~XVA*kv=Y=&7X2my@G`vMN<1+X-?kme3?)cDlF=J2 zHhf9TY5^7MV@koSa>Yw{tw)Kv1E?w+e?qqc`EdHR>S?^tm;fxQ9II6I0}L3`YRyzv zBAgMpM8zUsb-*8VrboaI_JS`3p;!-S5)nAabz*O-nCtr({(v1(Z~3r+QN2UJstA17qxi1tq)&d0vWTwkW9F JQi7%73MdSf3f3+$n*uQd%ES3C)4?iKbXoj$%X03lJoo`YBH{OCu1V#qnvC{}BpX+Nv2~l~n z8(IR&vJ}vLpW>_o|7B{i1Dmy}3KX!9gP`>m%1bu#cfdFAIGq16Cn}0t0t@(n*Qjby zv*i^J*qRfAqAEcl;D24%fQXC2nS_Nfrkb=1#k$p(1=g6#weAeR5Y5b3VN*uy(i9e8tLkAze4ktLY!h0#U zb)0Mi)qk1>F#uF8&^`3*1eSv~6nz?7&p*XxwVw7&NS~6msit@kYzX)of%EN&l3aj2 zC63ulRxf+7&Pu3|m1MWqS#iiRo?H?U4{#xQCa zj-?J}jlf8|0AN_|pjP0=@6C8cGU8PpGIV&@=EUMK*jRgx0ZWa>r(h+QKv)*b>FHX*1U4($NF$|!NQ-I@Sgq3kFj7QM#iHPJ{NSm*{mu4L;^|E}u9wsZ1ng{`9v@~O zuoGQ*xw-?#&IlAkD9}#p?k>>XStKl>2#imB&1?eAAm#I*kcZA@v;*Q ztY))IZ}J~xewNAqNHo#hV&o`sJ5@7ubZ$imGOQ^ioZ<}oBuzOWQ z8-=(=!Coz7;#Gk5F}@X(Dp?DWW!#H4yVOx=hM_zA40O33!M_2a^b87X25CXDUIOel{e>#QZjZ-SWn464URu+mad` z6g_f1|5!<3(dQ~Pu9x%xFKKj==($@M;|%qAXDZ$^Ql|~yAcb<}9sK)0NY z3kfGM38z+(dhlzNeVSpBdSsQ>I| zngos=GxH2WQmv)74r+jO6{pESoUCaTdCW9+Ov!X6x}Jl{XOQX0H+%yNj}8nt&*&R>zuPy5*ba1 z;YSD=kKy-R?HK+DNzMVu32rY!l5QXu_sB5yG(EgBt4lv1fI+G|emrs)Xro!cybzWH zM%fKW$$H=PbDUE(;?#RI5h~5ORQ+GlXIp};h;iy^#yq@bR@y#j=TrX*dOBC6n~p(p z!dc8=&8=V6Tlynva=lp{%FmAIVa%YC^*l<;gVeGhyJ#hruMa!gdaJQm9^X{X(669M zmpC#}qaNBev335?^`VuRB|zfX#$6DHi+~YxQ*t@R!E&tw7#N(*ta?Dd+;c1uN(F#7#JS#f9W;|>9$%z zN3Nb)F5F~qSdP%%l6F&=WlOTW&tZv=F6pc$rYkI&*Xqn#Qk7}d+kA(^{$CgnI_SCB(MR%;L~$7_homCAv3 zQ@fVqV^Qt{&l=Jrk?>p^1+L4og7aB(Wrkb(tQ)`|zru+lNz|ebq>wn`L<%X}3z$_; z1e_C3m&Vj^`XCsR4v%3+Z{{C5Og_#Lg=$V22%BNQf%u9L4{Q<&(!Lq=zC>TmOmlJ} z#yw{KL~7UC9L_d=LW0iFF|yg9ns>Wux zflZAM<44YNr>UNzIlywT(X`%wXjeJ)98Sc+9!sZKFc&a_EtlU6NIi&p&^#&#i?&)_~xcN$Kk238iV2+hGKbb zJO77#@giSS^>huO?zf^4Z#22%~{a|U(1L3N|tMod@gDzb*IJmsLbZ!Af}kmQM8htaedj^9=X$7See zQrM4;WrrJ%oejs{!V%s@cV+!Gei|2+d;#d-d+p=YVgQOwFM`mqfVF=kH_JeokwRKp z(E@ha|=v5>mC-Zr5jTv z`?XM?QYh|_MetvQXHV)Xq;h_np$d1%yS^KXkA7M)L*sMO$Rc!pA|BNjM7TI?p)Z*~ zS$LoU#a-`W$2BYvj~xpMH9&Y8JMO6l?O#PQi~iP#q8Ee8St7L^x){!$t%sY2eK3f0 z50fT7&I-+kXm2(FTsjh#cNZn$R%BD|x*KZ>N;03)naSurF8Nv47j|R4ATu=xyN~gz z87f)j-N%;9K1tom3Iuc~DwSUyZU8a4u$0p`_%|Y>UMeEhj8CFLHYqOj_DN5!kRa~I*HG^&a{!4 zp*LfIzp0h%^FnU~&uAJ-1)FooXeRJnqMh`J=&$9cTh&M(#vaIpeRM_c14z@KJxa)Z z${0fvG(`Sk*4A)VN$7brIi&M+576;;KST;~ysD^?_G20;(G^g#sxj;CFugb|5VAddu;AbW$vfLsWv+-@oK$(W)BT^AFVif ze?4B1fX}+JMuF7zD~`%KS6**67}>8HXbvj0n*?tO6QoG9aiFS7%?D@o7bayz z5^Ph5S3?Ph3X#g8gZi3z&ppe8m2!{O$1pu4a-zlVpwwIIYuI1sshwXm;D zz8SP0MB5>|eYKNGnMmpfk}7ekrWNGppTI?+1kDluAr?EaB z;oAt6peBMCix?khuu69*0>3Vv#$jMirJfGN&n+V*RWuth&n~Md7MpBFZIeW ztsF{^N>Q3=lw`#8cHilyryH3+gEqvk-ovm@ZQ*ASBrRubL@iPan3|72Hs{ZobwHcf znrr&{rX0so)U~p;)+4HBEF07fvLjb$IiGH2}%WXy9q z{3-{q+8?C9Xa%{OTPMh8$_=}`p+7l>8egt`%AbUJYQpY+Z*>v9+wuxl+suZP#MoHE>3t(-B%6|wJ`C(M5 zsjOjj19~deT_yDuNtJ%os$JSSGFhPQ*)c;4E8UJ0D4lHI4(4-J%EYij z(@A-9dCHPHT2oFyi-|CYN-2wpaF4c5B^Mj=4*Z2)ZLOgA|VCmFsT{8!#^GedPrjJrRdeExp=iX`v#Km z1Zq@0{pP@UCw^x;ZP>kJGLPiY{>}k{Uv6(qoMeiMZ<+5OoJ8LA6FE$}SCZn>I5$HuSYFwK}>U51_WU zA>V|G2TAm!pJ*zl7OpZFLp)TTG-=&2ow1kCFig4WjB^6q11<$6n@!aQl#xn;eA0n& zJHrspd;|oz>CNR)iVL+AOFB9ZD5>3$T2|;xssW`B@DpV&EsVd6_$Pl9EmpYrlKLl7 z%L+}GsE_Ila(*>8(ZtNMbdZCs#Nl5il??*#S2qBJU3uCmt%cKm_o>i+_XXUwA0Mpf_hrZxr(BRNDc&(8U$~4pEqe7P;AqMLlB!5h(KVIWAzIXC3!|qCKOw4HN zB-|Qmf`k@0yH^nILHCGZ)lQ(k?nJwLm^D7iV#(CLlcE=j34=qP4SJ@ih3c}A)VK{< zqoA^*Vh1oh!%6TxPNO}IQ!Bf}8o9%YBc?JpN&L~Z1YB@Hz!|w%b7RhtDphJ9f zP$%{EKlHg_MXCovKZq6iRX&%Y3QPbn+z$LXfb1(M0dCx}asu!YEAI#_AqNiB%}`d} z6`VB6_0`%D6UCLQ#|rVQ9{K|`rFzke1KhFv62&w^$Eoqq!59*eEA|>-VenuD2kV$( zJpO0e{E|K5v3Jm8c|dBApJXeT`F#Y+vZVV#N8Phu6q^;byfHlYMLD5(ojOX~(F399ple>z|=ZL}kBIgmm+JIG9 zerQ&T#JUx?U+gGGFa9bnEFK$}rJ5c=QM578&T0wpch0)VDwvH@ISL>yb2uAGKd60i z7=_g%!hnBL$y!u0drsJZsxkxK^)n6F?<*Lv_ivRLa56f*FkmYHXbb&K+AF_{G~m(x zjsYe68D!Idzx`UyfKNasziQpZW57ghz*#(w;A|!t<5&Cs{x7?Y^{abm+;;FiZMjO# z3tCTs7Tj~hcJ04?`KwaU=GoW9iO1obxl8aA;>GAV0d62uv7X$(*An=rY!Hd`_lDGv zZYqP_smD=g<+J;7>RdiZ9Ai99TK^@CzwVbxjK7~>pm9G60JQO|qf2Th7DXEWo_>z; zCA&GYY5Y`BjPTyZC>6h2-pOP9%L9ExR%o^rA8>K80;?GO`GY$-9dj>X<^88S!o?F? z(Z78Uvc{>wSV)}ioK1E{scYFPD7e0z>e+=lNjcl}dJOj8y zhR_>`quU+k`DNQFt}p1|@gtr;2(MXl8@wd-VM=xZj&ej}{1BgiD}j_Xw3PL&oV6%3 z9QyB$uH2$s2CIbYPDfYP4J?H6b!R>NAVOAYZa&@RC9(e>7-}9xxRD~vts{nRXXV_1 zCoAtfwzjxO=QHhxN&HnGF$%giq`9vL751xdhj?@z=?}L-Wx`7umbC=$LH-tmik^g` z5-!xR3Q*BF7C;+Q{nVcQhXj>sfD*};qu58=$SBq{=C0@UqvxIf4c#nJ?fet9TO!L6 z7DRdLya1YINs~WCWV!xlC}h1SQc~hBkT?OkZaXQ4dlpe6Z2Og%ZMJ!Wg|-CiRy00K zREGFk1R@VRN2^sC;Gqal90@>xb)X>5VD%Cz$W6miO|xUCY(srSWi&Up=H}ASPytJK z3@XChl-Al<*mx32?NU;!25L0d(t|8j-_@ij^}ymP~3OUF+@!fagaDKpl!zPVR}6dlV&e zgOw!pMH0RxVVmUlA!7M*w`#wg#b1?!aBsgOMY}R!Zh3-!% zP6MR!a2s_8Iym-du9Lv6Mpm#dp5z>vHde4JpLttMTPx=&NQ&LQ=-f+psgV`5h?DF4 zeY1Aa@A<2y6+89F404t4kgFBF3_ER6=vB*!%zNw9c1(h3*UP8<%g4L77#5Ref{nW4 zd)AI}jo9K6my!0b249iYB5bjNDd=AidIt)|v9Y&M=hL|BxHVQUnLC@0U92h20mW!5 zSO_CJ{*fJ<@v+3S^l>5ro0bxcju4hUW`=~NTq$d^@`R;@iO?vVeIc?LmLA6bq(GEf zkG+1OsamTQG7IdR>C%(K(#p7*(nD{!OHZ=@KsM?120ceu;r1AX`3Sk(997D$ie8!K zYv9sukP$d6Z<~K0;BPgz!$z$=hNyF@m6m;9Py5zKFhmGar7!Q)VLaW{wP@+m+36T(EeZ%>yuJ{pVVt@gsW>$`k8ervJ#`mqk zIG{3ArDV$^AgW|efn1(eg6lJk`B+Kc1vkGM(jqeCNd2vgX=z=5OK7h0_4hA^t}@{h z%8TT&_m2o3V}-}h%`4&Y8s=P5*D!9)#K_%#l8stcX)7zIB{Z?}hH@xdsajUva?#VH z8e}l-*2lEtho8|EJnfdGzKK+~-J$_(B>2@uMmXuqbwc-Key}D0VMqDF2hO@`FZ?s5 zESCwP{n{|QX}9u*`4(}?7{VPUTa1u2so3H&}!YDq6$ZFpi#1>CCyo&IHF;U1u}SIp6C>2xs5WM%;8A`)))0 z;PWp&VEJCfbBG+HGcL_+6X+x)ob_XxkzZXrnS;)1AQC#C-j?1baGL?d`t|_C6qbI~ zTmbhp17J+*9+pqyr>?-5y3PWf!2N3VKB-5h9QP9L$Tq-vCPmz?Wg%77T}$+p&0AUw zgY=ieCxFe5aq4_sw1(sXl6*0OBx1^&Bo!uN1)oC#1pOTTXg@5_D8sGTJI=a=M??g( z-Os+%9l@anZi>pcwA!N!xrn`PA z{}FX|(?}<37eKFGid_W8{zT&z>Zf~HYL^0@w;Ls>pP(V8h&eKyqvgl-i?`q@#1rb` zt>E>1z7WsNt(-mRCtx6kt?@Fmi{p4MVlGd@t77GJfx}yQT#qXgk1r>vsWE~P)sgMtmn}9=}G+N6AN>*8;g^Gbn$wuwFC29w0%r!9LnFmehXY9p!LzT zS~@uBZcl<`N$^7m=2x3AhDF85hSX%m+d?qr9_j!s6rjGGf`6^8*nW$7PLM4P1 zs1y|)rQXB13M%o8Z?)lPs5BaipnPz589old`H!<&N2s)eJ>l?ofZIP|DSg#QREiOf zvdyf#kDj>#e}E4KI6o5flREZWsO-*trxg}hym&JDHS+j6tvh|n2gB`zpDQy zsrv@JA7MzlC&yIsDWnCTT=l8%hv;uI_~yV0P%bScQo2c$u5^>D{Op#I`PVbQ2>F~V zx%&sW_Pwe*3L!LwL^BOhy$05`D34IHm!6sEROV+HqOCzx_SCE0cnVK~eb+!7ckFwS zx?apVP#h#<^Oi_$x9^Ln0s~=AOdxAYW$#8%(uky`SGbpRzwLKIm|8fL%2IPN zZnU@S4{*2~XC0of1aXqOh2zNxV~>esANR4?JiQlf)qwVZ@0`b%nk;9$aLI^jVZfx- zyg@&42( zG@j}$wrPfnryfqdFM`gtjfhKJw_na)E$@K6aIIm2>O`{eG@qI-!+PI>cOndLXF(pA zy@{1mh;EXVH`x95=X6VI?2RbKyFt;feD&!Nt_jjB5#nM9f%=hDj$wVxuz?jk4ThSA zVTBjdWqXuX`f~$h_x9!`wHT>9HxO$Dpgnc#Ng}M5pSP&I7vGFCaZWGZegK6P7G1BY zMo}jF=>svTPm}db%{siMT2ikiYpi!DL60@Wo%qHB^qOi9jb}-tJE8SDhi`~bCvb}d zK9v(Em8sg>ktK0V4}@CcT2f49TY3Dxs(CmiG3)1uk_bY7zq%jPXpJk;Lqso#qxWpz ziq#Rcg^cN1Jf_*4X9Z_hU~q0EgG^!2)G+u_7}VDchM$=M7h=Mr642b2Q4e#8F3jWT z!K2^--(NVKXTU$X{R^v9lAG1X~zKaD78#p5r-{x}YuWIyjaPh!NmP0$) zaY(B<<W&KDA(T_QW z5MVb2pdPo~kCJCQ8SQeW0ix5mEXUQ9Yl-8dxL5^USA6e9{FkL7CUg{2#<$l==rCW^ zTVm_ABrlR=nji|e$q8cL%ExW#^;oGMCjtj?KR^W$g0|q=65LA?hXk`m{Z}#_DAdJ4 zV_auGR!6JUEmn%#z#kxdT@7#IjwGE}OSxq)BZ!v>Ygzth1#W4}c>f7%@-XqZLW{yCAlUf@JRF+6I_5_RM6Z~HJHXs@!1|KHe zUu$R!IpwRw7$dE|o`V?&W71E)tBvKQU*lQ3&xI!WBP0XE^%%F9xW~(0sOctqMv2(t zMsV?pvo1A~Lu3Hx)S!`jq)O8nFhLqiz7g(;-if#;7w+I#9ryw?j@(T-aJ^Wo7@sBs zbTMQ220*p{cprJb4joYH<#Ki+r!4=TjwtUrr7$nn3I)(Jr%M*mYxI3A*eDPqreGTE z+K@ySl4!PGD#!7A@M#L!i~{}v18PzC@yR1jJTb405XaDzoFO7kA5;=`NDj4&6i1fx z8Tclo)PR)29vHd2)2}w;G9DNTHW9o1%~u_6QeY<0Q4jI``eYA7x)n*UdCyf(ZwKZu zI_G?pJTA?|Um@hgTrn05)0UXCHRc^s)xD!LL%tn>t|E{xIShj%0&%a%o3ZGYhS;Iu z@&4IX9_M5YE3}7NW+{UXqJO2V?AJ5_%&*8%!Pl(SH4Rf;2)bDNzc5-)y-I-BM{)|eIrj(_Pq~_4{?Ee&HwmNt`wuQ72-KuCBvq0lJhxSsJLEeet0eRkm(m zrbwf{sU~wT5@l`z0y_xL6OkQ+M=18qj@SwCRMW0sPWo*KW)@kK<~ZZvUYN2~BIrCV zD4GGT_!jKnBxgROy(jf6otg}v!u&nf)^05TYE-CdN{<4+ngU@xZ4qKQqC*0Br?muc zOz}7_e!b`qTKs(2li##*eVblpPgJJFs(7ZvI;;L)NL#}-^SCZ-_Lt~brgs26v^)4r zwWE;lrK+bup_`^xOq(r&fN^YcKY3bO-$$sg-smPrs8q*U1b8n2)e?xC(HIo<#;W<+BWXQ66b^s8CgP9yrJ} zPbsgTNnHkWss>22CrY7+n&45>3Kk=kSNflV(gbooSbI|7j`R`nFc zE}^!Shdt1CnPqyJRjGv8(`42-%xneds@2!x04@S3`Bnr+|08DMgR~jib}J>yv(n%vH?13YlErQ&Sz^8m2Uslw`xE0=xpz zV)?~K#8_Np{XYsT=S|}(m05hzt&Cq2<|LLKC0yr7br4EL0D_lugC_n5CDeo>UB;PY zU51mdNmJJZcSO|GF`lq+I;yuErA|&CH#y;K<=H<{x^0y1#+CFknGbQhsFE>4GNdDV z3#M5Z6aR-K`kZ`Go`^Kii_@BZMOuxR?|$8DW(B#!myt7Kgwq}&GcW?ZQj)A~NSa9( zr^f6cxvg)IoGdHiG3jUY)AF6nNo6QAT@I!K?j*T;9CA2?5L>~jus@uj8vvdvr@O}= z!@DDKza{R4UR)mA!FIq9-%WsK8X(y-_7JG70@JZIcH(K!_MflQ<`VT?14_m&WQ2zW z;>vrmGoD@-xI_;EieYbe5RiUaG-Vpx_y^K{j3j8Z%089((!E_O2xu^ii8(xRe&U{b&FdHma13+6ZJne;ZLi3J-~h$`eTDd`!I7lhNYWAbo{tdl>!~jAGAxKQ zwUmm!bBtJC0cw)ia}Kcxr#BuLLx}qYBD@=8?reBzpd)Gi472ig>IwcPs2^AlPyv!7 z8Pz43UYb!NHHDF!=qGvc5iAnYEW!6wjO{3;Fiw5a`}GwjIbvZ#@KF|G`C4!U!6h&n zGE%&3xFsfsk8^vuCxn%_?SK=P8j(SkFi3_jGPrQRO6s^owQmEZa+1pH)+iJ$y7du4 zpG%tEBZO{=n`2R%DcV40u+RJ+$7&J9B#8gKOl|)=pj&g(D-dWw&hI(|c*jBWz@?C1 zvti@lbH@$W9jhdi)M13q4JN|JBBDv>KVjT4CJ5+kPM$bpkfWu>JZ>CmM@c$+B(Z|O zGmvo33xOmz*oQ38$(GvCp3tY38^zhhbSOVd%DKL7&$@LnI@}Sm=87k18~RDAYrrR$ zbwrZyNb=8vJm$w!c{r(>fLX&3yUOrSr$5=5Q1^%sPCvw)X;60~YFcH4yAWlVA^aK% zm!US=3#ciV3RcuKkr)lan$~hPU4`K#G#&a(Wtyf9tdxIGQu}0?*v$k9Nm`90>bjgF z-2#yUmwBbZ^dmH9A25hrE`D`^uy$=0t_6Bx@fVZ&C>#PpQDnV8$T88R~AphwgMRFePzj?QjKfN$O@upe`cPg$`1|*^u~E6Xk;| zU9i_W6`)b7nuzFoe<7SyYVH)4=a84+6P_ib+0~@MM>8kciOA-X(fe15euzetG&a2x z)>7!E6iH4koJN9wzX<=;9}kzXc}s^R2CaJffXdKr{(tR#dtg+>_5TgH@=#2C0X|t2 zNf3eok`NIjAq0~0T9Y97z>voVc1f~vvkO6^pb!;f6vbDyz8|$eQPFSlQQI1{7HV6I zw%?Z4s;IS{ZG6Pm2d%dGeLiRA-o1B|VEg?&|M*7Pd+(VuXU?2+=FFM7b7z?Cd1OOJ zA#u8JC(wsT4DT&pVDx}Z95R&Pq4PR9j6>j`E-45Ah_eIKYaatscv36)TH#;O1#F~8 zw#rxPduV6ps&7F=iPs=3JNrQu!=+M`F|7BUG};X&P~{XCF=B2b!)^H0b((e|mDg$$ zhDHX~_!vW2D^G~b*F?U29z<9!+g%rCG6yDtWdNpfhas=X3Tnr8R4dg^P*Gi&>cA%k z_S_2M>5?3{6<#<94OgpkkPo}_tyJy67r&vuv<3<`Rl z)3Ym^4vdd+PdCCQnVsx69Vm(oH?TS0=^tk-t#cgf8|(eL90^yCd1*93J>vr#;Jw=@d#GH|l#Z~EB*@zOqA{__EH**6;a z<4Gj(C>Xk`;%qTs5$+Q5t`M#ik5qT z7QMj300t8`<%7BKT6Od@u-}R9Lhu=(sX&w9tWzI9EjAuk_dP2&t?G8%fFcW$cI@dd zIZNw(Y5Okq^v`d(^)wbQZ3XF;x^P)$BS~k2|0HSPaJ)LxP2T(^JUl z>6^JzGNkngtaGkoozv0ZgZ)R)-0-!2m}{w@4M=@FZ@h0?fa=;~WvM3{oH*XUu&_y< z!tizcV<>_C*H6Y$3&m(g%S?I)e#!Us92`py^ky?A7hRBu1IrC_sltc~>;w`&_|^5H zg*_WkPny)JOdS$lqy7LbN@lZC^$WqfK4Gh6jG3YC;Wlc?rb|hV`4Exh62>^}g>WXQ?1*c(OZc{VM-D@pO_KvM zW>X&^+vsGrB@U0X;@Uo)H=Cro#Ez|neUIs0u!zd`t-IdSlvu`QmhoLZvLcbO@llf9 zdFhQt-<#N$M8Gu47Tt)vF20U_x6^kWilDb{<5dm&AI8WWa&x<(Nel}sz6o@Aq70a) ze3wt)ExI9^Mm3WH|IO`5U2ZynaiuedgHP?mV~*|7vWLvgSq-ng2~$2x2|Of6cm)SV34iJ4RG=t{YKx#LCd5*zO$G;8@h4 zcSp098G5;$f5p5!_N8HuH@Xcx!f7+XH2 z_Ux~S)8n|(E^s9bCR{4gXDPR$6ny`Zu=!&6l@>cnm7u2)?P&ia9xKJMKUM}55#;$4 z*+VcW%|(IDTTaSv<{cJ>ZJQV z25SK|I-A}0Q1wlW7NrqLJ>%@Q@g>RMC+Sp)cH;=;sg_4)SxSX^dO z_c3)yc$K=A!+laRk;Ti1l_0&*>DOHf$CG{ompr=+aE>Y67~nMh*w+BXroQ1tK5GEv zRGXUnzSxwOM2<*8y|PW$dTcmbtUwF=L8t?=u)9(X2|qT?N8! z8`!1YPcedG+{u??1^ChoZDfOT*}_o6g|UUdq2lyCp2JiEYVCV2ZH^6J;!@u$6SVs7 z>C$_}EYPTq`Z#^0g~Ba7>8cCjlWf<)7dHK=?a7%`n*~zclfsJzK)Mb{ozg9`=|}I*R&*NS#VX4dl=1szoao!9Vrb?XN4?HmG&OM-i7fD9 zSTD9?7U%6Ba1O_Je~1mbX`Z^Kw0F3YC%!J{5jX&YISVukpP(5V7M5rhD6W3X93D`& z*j$=Mzn4{)k6FKuJC};Dxp zYB}VES^PW-u}b3UPV!{GEjrdViR6h7j<`k>{b~>T$Rv7?)I80eBEU!Uh-V4Jq6o&c z?ue%q&6MtB{(f6acJO!c=b{aSHfRb**d(x`n#|(>Y7=z$sWf27M>s|1fgP6$>4#JY zzUgh0WHXc_Iy4RDRMUC|<{9)f&1SPLV@~nZw8ymAQin_-%e$5GKqZHTGt_I}hQ2Wb z_N&JoXsLRhP}#)u=LR|?e6e~6P$8@B9TDbU$b=wcoCTEjan}K+Bh2$Zkb=@Tm%*Hp zXfufRmk#FCI^+rCsq!8QKS+81<}IlUXHDn3Bg{e)d5lDo4M8Hzy})FIdGW(ye0yDj z&=KYVX7WauLrw#(s}+3p5DjxLjzno=ojco`Sx@);N!zDnzhsZN^<&f9mt!_W?nkzL zlzs!3e=!xT^lxrrWIV2IPd2Os2kYW)qStBk7&ebG#Rt?|8shaEWV@X^I#Y*#?vrQV z0D0nJ;(y!+|ILB$XAu8WgMXsK)4K+eY&xEfOU%r>Zg2bVJ;s^d-o$>gLyK5K+Z6&Z zfyQE5aC$rU6i-_H9vps-eiTRfRnZJy+=B5IEC@qU(`i6gdba?j^4KD#qtFC{Fi;!R zwmtm@zEw1#uqeu=S3`QygV0-WCh7g@4ba=c@hul$w||Rw)VED0NHP--LgsADW#d(ktGExz+AP=GobW`LBP*%z$*s zYskXw*SNop5YT#n&}ZU2-%cTWj{Y9+)whumBGiL1U;H>0i*ckWmcmuzSY#Qn9>J#= za-QR6r?_SoH^Eb!fQGw@BRNxC6^aY{Kx!Wp=PAflS#^a3kC*%o7Gs2QS4U6;Ze)@ex0TgX9BAHEg{U%mICkaOI8VRBcPl#!6HzpPyg0%|w&^}`&Jwj)W7 zU83NghZIF{SEVq=6R$)UXl`Tr6;ysZhS4Dcoen;`7B zJr^EjxuN5`{Kmg(*8kTy;l$sP!ySesaZ zEsLZh`UEW=yKPZMrvG%A4x=%c&W4k{{ZNec9=)o zjG#Nw7-s8GbF_ZE(MxaV>;q?*aIq3s@&T{++TPocJb|o0 z8MC`qcL2}h+xF-je6!GfHXxJQ_Gt(@P`z(lQQL_cf)3Wg!Rnh1%+UwTvbjSx-=}Pz z+azMq#~HepO#heo6>ePo3NIdhrA8iprB2-E?(6v7OMZv-<(JKw^QkzF1+fX%ILKOe zEH~i&E;t6hK(Iqs3Eoaq$J`C`7!n?*4#N#kVYd&WgEjGtQ@-#n#42UP;5}UDkOvbY z^QKA-cX2-Rv+4>U1ds}rAx~XsA(*1i7BnXkeE&G!@B4g z_PWecvxNKeBzu-xLf~fKvQ&d1+@~5+()XmK zkME>dveY!2^Pd4=N&?rHu_S(TMzOr2olFczxn`*!n1_rcasbHP5n?WPV=hR+gy_c; z6K4qFu&FCW?y)JPxzaq0gQ7q-i@hP^pwYTpwBw++-o;Sf95gGRO6bOtB{l;KI}ZHH zP%CxO-3D?Z{i8kLsrrjRj2k=wpJyb-ZFGYEwEeYjF^HVnPZ&+`LW$!uMQ zytcrE!il8%>IN1hOE%@B4!^v}+2S6u{>?nd(1r;4oifHSAA_8BlKzWIDw_SxI6D zON9IJWU=RRLUir8Yp4e!Q|b>4*01rKQa@Cmel`s|taWJSIJoo1+nt>O7R0ek8a5d# z#RJ%fCGJ=GoEP6BFSbjuq&e|hM93fqZ(fTn)@ATAj)Rw-gmcX^)0~Z|3LLTw0xC90 zA<~)Z$`@&fw=*Rl?PtJSGS8KL@-z>a=Syj)el-(zMIVwB^647VPdU3yo>_hJOdK%J zHj`(V$ukCe(DixIaC;D0vvNEa)yeac$segn3Ly!Fs}A z+P_BaCDFBCooUb~L6LUh*vHqd-1{^=i1nbAi?65F#u-Y>oXkfVNC_Y-d+|rNBTEgB ze+70513%sX90X!VQN7j+fo$fNF6al_jUD4ys!lQEK<~~%6o#kOxX{D-y&i7X zH26mzo8eUW6dMWKjUU5^v_o6}rmk@~_vsd(!|Nmk%|Ba;M9#@6k( z!p(=!ol{JsP20ytamIk2zD&#bLc@eJL<_uW57CO*$UnQpJwy}GuK_~c?5$EZ!^3-d zUkPp!A8}H}F70;H3k1o`S*GaarJMydL$%-j-Y#|?i@n@atbnS##g6DxY+@UVU58>> z$dkmT!u~{s*?in-LuGlKON~>2LT~i7YFs-7g>ZST$jx{>t`re<2hdARQ7ZiV7imr>}$17*5`nNGEduuUAkdKU^;&r;#TSHH;n?G*P01fZ<Js8PtjFOx)rEhp;WQPW=lr_b`Nuaw8ZRQICzWqpYK)dT zcIv#thCWKDaUfr}45A^tv{aUV3w~jM-fZ~l2;0`kbtr{{Lil!^Vek`~zMwxtOfKZj z8Wv-^Y(-`h8?%ve7e{1z;m6%8uehr!5V$4rI5b4%Uz=y8_E^yw&i?Xjn+tw zc5o)`5hqkx&kB{Sbyw)md;V7{^wNYr6Q_mdSf`8Q?mCTRotzeSXnbOSvbc)*&h+GaYd7=hF6V3Hi_by+ zb!DV)-lFw+P_xlHLm`NS&K5yua%RMUrc{;%$xCOQlEb|G>1%wWkRx#_BNS6b%Cy+_ zmbwpS;bQtXQaUHZAXWGJY=Qa!<@)STZwEar5_L?H^yVb#xead{$^EP)g`7a229)F; zBDu{%&hGR_#Iuv+JT3DU(raT*z3Ti{WX3U1j?Q_Om))0mTEK10Se(qbf*HM`K*#j} zRkJw;+4RwiU@?$!s1*i+%_SwK>E8!vS$bOj9pgdNah?S)!+HLQT|VYf(%boxyn8(E zCoyFI0Pd|D1HJ>NVPg%Z9FBWzM>zp+DK`9$eBDn$dIIUK8qzlcYrhf-XPy_ROHZE1 zG^C$Ai%p)cK6xG=Fb|KBXF1oIJjwX9#6S)jpJMA!-9&T`JkR8j;QNpy0oyWCM@kI7 ziH;Nkf#u` z@<+F7IYnUVS}9LPHDrb1!U=*GylzLM&$4;-MBG8JfL;U06$EcUGZN;xc3YdJg6W$% z@^bj7v7uZJ{a;dKGaG-SNX>-6V<2IMdvg(vQHi6vMLwqo)CelE$gRXvZBCfsXvS}j z8iD_2iW&iWg`&I<%u zqj3#jo2%m8A9lWoOq!Su5onc++nm_)BW6vk0SE_0{}G-eM0Oz47u$j7m`mj`||uLF`I?1@SOZa^9b^sLiaOb&(YY0+Ia}*3{%u3 z6eV9@It3-CM20*^!+G`xFyrB?xjS@Xgb)(D0WEw3@)eYO*1E@O*( zzQXV<0zQGd<0_fdsoNh>yPdudK$K?vdtO!OQcA95tJD7IBkub?i?`owjT{b+&Jm96 zMK;;#?fF!IgENXa*&1hb7E-p9Tq7svumy4LRS;=7knsCFSeu*?ybl%P6sSGiQTHIZ zH?J6sslvGMrNCD)Dx{}rtE2{fKTn#U5OEzvafvtQ7Tk%uLx8$IQvBmjZD%jZ9Z2R! ziocHW1()#D8@~qE+qvvqf8<1AWTP9y{{LXD)cNwr9uY`2HaZqOj>TrOSZBERv**Qv zvS8IeM&i33sd0z-#20AS_R<&3v0@L7l_(Z(;2uZT#FL&36PV%0o(%XPKwiC4hpw-v zMs%UF{d~#w-N*1+@It9Ak_(*n7ejL_x!tMBBo?$n3M$0AyZvc2PLI=v|NEY+YH5if znp0ZRK@S#UaoVRQH_8~1mv;YK^|GKp;F_t?al3|O=*YJxX_Q= z0Y6C2<&kG-8KQmM?RT^>lZ^bL9u)1bC?J%`ihleJ)pbA>GCB1_h+WW< z8m2SuL+VD4PkG>d7#_w!@+qUd-3HHCOz~R45nQW{RaL?-#AWL;R4yu77ye>#1*?9W|s6qUMKraWhcdtX$ zpUl+6Ov`j8ek1|i&E(cnT)%iRD#~@Lc^kozQ%nnUoaV`KR{G}G_zKfVGPW{_y_VQt z)Cp6D{){-@z-FkApGo1rm8d_{s7d|>`a?juL-Yal9jHh44X;-VFNar~Nm3)9(<1p6 zNQ$=gi(x3o*0!kj1Y}SPK!9o|u?umpei0Es4+&k6%G1r{sUVdnfu1frh0kHWTd3mH z1${TuOQzb$hWCt(a2XJ7=BJG|t1M}ov<1pF#xxTR+PC&Ww8ZsJt4zKO$*_pg zdg0jUq`lx+VJlIkQ)w^A3rpfKaW7L!B&910eU+rph@3`+*W9)dd4rb{`e+8zx~hD0 z-$2uW+vc+SXVD<>s?|g~%Q2A{t_2toMhDW|`?#$C4{1;Mq;<>*(mHn}?vWw)Xcf=| z(>Gtl&N!9mU_CoYYD3c7RyD#eR0@k8m{oRiFId>5h zlbMNC&pl}qtg;Edjq*vbjIEPF!>b}uJ^pjAIk@>@c*rHFAML^(9wrBJ7lE{0tRA+= z*kd$ze(At>76COA7%b^7+OUq5yrZzMDCgRXklInW8VzqpH#TthqWqI6g&Ktc7utn@ zvR%1cc{qTPHncF_gF)O;?EWYI z0okG=eotKvV_l9EI-`{Z2K&J|oH!p|Nba%K7QzL4Gf^}UZavEZU2oo*<#324d%<&G zhggU$H}2f&a)=_bzx>dy;24&08%hw7X@`i-Hf)D@3X>aTrL)J1Tlrg=L+#%L-F->hI-(sFQr9w()!V&7?R5-?@4jwGE+J-!8QT)vjbG0 ze?^W;?xnYS1V6sDU%+)?{}l)02~7W>WQkbngerr`M{xf4V-P||$-UB^T$|47y+<7L zqR<%!L+B)G8p3=sbLIIYZ43Rxc%~!pAHz`H0?$HOB(wrod&QXZjZADC==QkSfLfd= z$|>Pyn#kebM8~cn zi9ovnWk{bDw$xC}gphW&rXAzP7O1D2y(lS(wK(i~b%JFnIw;XPN#Fckyk1RmvWfX4 zn9|9XKT}_+YSZGf}-NGV9C5w<4waO_%k`J+q*izC3 zF1t{A`esCyR1Y7(>8&KQ_go`Lra#;_eTSXiu?P*FdudCyZxXzTuId~;pxOVdT|-H4 zM|x7Y0;)HZ&MQ50S8R5YjoZjZnb7MRYDe5RI^-ld-zJCJB(m9lbuD5iCh6QkI%%d5 zT|)u=d8vaA?(Zbl8vwCKoLbG!$o61&F{z8#E^{5~Fe1s1Avswu0bOs1ZE9wNLhHi2 z2Ml#{*ib*?w1p$^dssjf3rK$&uE5xh@t^lHaZXC<*FIxQRg%x}lrEqQDSb2=^mLr= zl`QLilKX3=R0bmotkT}2idRaL$5v_TEZm{>bEW|+g5VC5V-344|6Ch`VebjjdqC5p zmLv@5e%fYFlD8r`DI5V^43OT6#!csf6gm%h>6G@RGePK#4i8bKO>Uj-AX|s)L^Vqr zhAHVuCVf(&HGK*$_9)QRnQ%a;-o=7j3>=Hg;7#9p|I1$WEf#^!L~YYIJ?dJ0qv$Zd zqKTokm|<(UR!wiDTop+D2j?~HJ^JDtx9<;#m@`z~-;m9*wcTW{63iug%ah|+y`7;J zKFof|llAWhFtm7y_B6&*`JaPy9s)-F5>1pu?fIVZ-zHxfYWqXHj#i)1RAIs=(wwdq3G7#xT1H|ID1C>N_(B%$ z8KZyk9B-0|Dl*~r91nljHX=!1fb^sh322gJ>GGdfx@9P+^S$JylxC+dtw#^b_Tvld zb6E5N^;HAT-rEV=RTq${yoUKu>u9JI8b#;1595DAj^~sHBPuh*_d8rDa``f-CAkpL z!vIO=0O$FLG#E4F*uCor6xZ*&5g(m&>a=vvUJSOX0LEZTrdijpexN#2KR!l{;*q;2 zV2<^d=8@-rt# zK*~03wc4SvTbGG>VCUuCR*Y+tZ|-Ihm6OqY^Jq95h9Ps}DmoEibd#YmOZ~D9jRY-2 z7YCpG4@!J~02Oh)fP0WCd^1E9zJu*@)LV#Gx@TxwpJ{=`CSt}-lb1TE^X`TXM7JX-I{2elRd@qUqy(EwB4MHnSob!M$kG+LE;%nDFbo5IF1T%vD! z^fu;Sp-Etd+-ck=VrZ3Ew*>T34;_+}6-Y6M4jr~t2rB!~A%-uG{C(gtjBiKSj7?l~ zGAW-#${qH}LqnW#;(y);e5?<0;g2Eyhl>SY0?dvPzbZx;;e6y1Q1>twwg7>LLNy@A zy`C{pG0mq_wpIXqE<~c=nN55ZM$B!&_ri!JIiMZ@W7t3m1nCo6H?eN|!$qe8nPlif zGGtz5(RR~&cjD!KFHVm5a21q%Y^nKX%{e^c*8l_93M8>G+1wAG-u&rHyt5vyo?)&b z;ZZ6?mBR-dSWSFeXn8DCEgGoI_5GJwBW2n&W{}2%q=C^5MiyWjhAYtP0c9{Ts|7~J zO_J4@kN|{&5S3qcB*&9q&}{pW<=a2gvXmT2aaKZ10rl=Z(zHycRzyBdG<@h+2YGsE z+edR-bZPR!$UO&GiFrO-a~=A9l6x8{%JTF}vw%8wi0IHy?bK*xceL}#ZKs9EfuZeg zNq}q+VmhkQhk62FGGPu__UF134ml9cR9^*AfIvcY(VZhsx`O$+#4tXRZ=Ga{2*K1& zN>hC_6q+v58485N1ofOlV!S5t?#6?Wc$6d%HaZ*)3y)Pf+Ja71nYdvGcD7Qu(=UG} z-K%}ZQ+La?)M@9nRK^Vp#3+)Tsz9#*6fb`q8w?V)j;Q_G{bv~T^<(#M0o=P&q<@)u zjSupUXc1YHmoPU%^t8B9!dj2&g)HPP#Dg-5blyV1OFCR%Mpl0N4dGhe4kd@pX>q)T z%231iBi^V-jss|Iv$0MF(PM_n`2(N<1FZlQQ;QkuctW{N5^)#k{GYxL*mwiW*RaBGR=5Jx2La_ExzL*v!qr5MVa8U!?hkCMT!N|Sbmk16jI2f|ty zr0qod4UybyXa%|pP%e6{MC>G6x*!`%8xiMcE-o66lg2h;>xHfb$iQi&1Kt^eQ^2!K zGGZ3Cv;6>OAmI@iE@5hZaXR(J)tie;#9%4-LV4!?~ zjsz5{B7<+AlfvLnnC-K9tcHt0fxbTuQ!b4d%kTpW$Y{+~&PS|t z6OzM6BKupDjp$y7TMrKdL$XD3qMvQSIA$~x5Y)BIzP*K5|qN1FGRT+n)Qa!WntkakkE#oC~RIUg_ z*1`F{^F7@_I!A0M0AbGQ`|fgJEe`BP2e!_Ebvm#M9M}~OEYpFlaA3s_tlEK%GO&)4 z0>n-e@PrA|9JT5WxVR4A71zTQJ4ej1GqzjkgaLS9yk(se2p_6u15e${$(PO%xf)B| zs2{WSBYL;IHza+W4FG5d0tC#M90`!x{woM5@2%;$mD%?6r+pJ|FfMr~Ev?g6jbahj z`tG|~Uq9ZZuR{oj3!>`}yoX+DOZ$N@$e}L{9D+gIoq+f6f$$-{J0+z@T@v^RsMt0vmFuCk*pM1P zz|{>*#`PE5^z|fDqddZ;Mx)i`_!hp@snHoy57wv*>p%Lh(J5qXwq`6@BY{rQjG;!w z{nY4GW;|49Ox8%C2MRqky8kA`>SMvhJ;DX~dG1ur54!?P=&Kd!=n6W0+dtP;``{*h zozbPQ<%Aoh-T6+kif+|RB0pm8M?v^N3g<1NlV|;iXYbF|uO)XWlpP)Zu#>>jb-(GT3Z8 zegk%QD8L2^h}v|?>Ag63`3l+>EIOK!xaJO=ler2x2gR|Gq$l5H*FcL4kusawOY3diZ&@V|CnN`ZL0&8x5i~@1GiFBKt?TQUZ+Xto)K6;F< zM}X*AX`Q8=$DR(}%6510ePH06@}dCz(fPLn54Le>X)gxssZ<`(RQBsO>ncM1K~L_- z@EuJ%lSNHqk`Mk37_sOSz8J%-C7nE0VUkTCXU7lW*@207!Au`Mug>hl=To<7KFj*$ z(;}a4;)lw?gj}O9<>8fW02^Dejb3&0m%WLG{z@I$x73-Y)argqy>`3ExF6~KSigM0 zM-CntU|m^%GI;Bdeq_)IKc1qi$8Xg#=%1Uf9vz6Ag8sRYRaS1HX^jN> z->gq*G#X98K0on*3wzUn=J;V48paO{O8kfPr2Xf*Fu{p#yNpc-VkTEw;cQd80pd2&Uu<1=MASblL%5AJ=K-LM-~3ajCS-;=#1K2)+Cij!^z$kLGbkP{h3 z$D0mRBa7L!s$e4;*dKqt#|R$$x!cSKh`33g^UQFHU1K@c z(#-2 zZp4R|@OEiN>88JDU`I)A>yUVw(ZjBHhm@whhQ0+WIA8Q@meloIzwDJYubUEwly1RU z&7Howu@a`Ka=z!sI78^+o&2W1k={L|S1Y3h+u3~cU(^uGDd3O`>}1U=)H$N%o?@t{f!Od!`tqMKe->AtZMZPP0UGFGf5t% zInPrD9~>M$B-_fZcoA-JOFKIS%XG1)c51GWktx3b3npclN!e|4g$?lLK7>H&LViZl zzSn`PFVMFFdWIMJ4xnlYCEn?~bquvSTD75f1DQXtlk4=IKAO-$s-DnX^>+=uQg8>W z0HKBISq+T{^eA<-CK#2+@#+wH6lRj4)5kcnBE|5>+<+2k&+nr-sOL1z3L$cqdI68> zAq~4kV8hg-`Z1=9#UOG7r$0IoY?9|A@P_^?_7Iq_F@T|}TLUzwBf^KN-)X=a!8j~@ zxcZ3(1P#$N^{fWe8ybVuw>6;F00t}Ui^Eb@3V^3W<6AufE)>9F;o*vlrvNxt0O{dF zRILV78X7)@c|BsBBLF{4u}A|n(XrtXvN%G?@`O&GX7_0I9r#yu1D$NAFDzNds9OlT zRKv6+@L>^Qt2FFM!CR;r_2WnKI6+-Rl(`x<*iQlGt8WmNqhY5B>}-`!*ohjpL}0Vk zDTEExuuBBCP#rB6cNuGbXy(P{00FJDoDWjn#ZR*^S zVpE4&;9kPCP^Z#L795vz~{+I~tiZQH`iw(otx zCXQzF%zX|l$>(2>>0|q+I(+_|d_G|5LL5@6aBM2%D5k^rew&~S=DfOZEAcS|w9yf~+UOXMq2KWR zP@@-OC@KYg!Ec#5eaDL(VOFzU9F+F4x5F19ZIGm4?$Vvsrqkx5Ky(k@w3RyT6`URi z=i^PIe*!gs`eaE4xD*k7m67X=fhv4C>v*D5xw_u423f+nRzI!?g#S#o( zp()}XBF;ztw6;HNAcZpwg{zn_S(rN+ui`jU@Y@Z8@ZOW$9FDuAaOaB;LMi;>HgN_^ z;miEqowR3Ln3U1mqH=9Sd}cFNAO9I|W7pperF4wAqZTGQVNdCn_AZ!*diY5M(0MPv zGR#uP;ucIjh?Nupc<9@95MQtY;W~8$1dGo-3B-=@0wV{?s zRMMKGk=kG#F#WaF4GmUoeRI&iDqbC}^9Q3*;Dnm$g022YJm!zo`=ixOtAYTnt!@a_ z`HPDxO04Q=w0gZC<%U)@H3pkvCR=f7xi{0YK9D)*RhD>hMhtI^)WsWuGyK+w;SHfC z-jpt>sI-<=mMyHXikB>0SW;YBwq$XIRZ&@9ws?Mpl|6Mz?)2P(Y5BPYR`!`wr%szT zeQM6M{DQpP>C^KHate@XamA8_B~}hdTG{{RpEa*+VM&EmS+cxxZuz;^!m^6W3ahBR ztg_T9DKB4AUSawDt3#-CmNmng;J4ORM?=*$4MBgVmFaH^t_?>0@s?m6u+~*an?g;i zfY?k~;jY@>5{vQ%!i)zYK|tz5t-(6Kh|~%;)infLTKw~tl=~YZk!CAY2l0mLLm(Q9 zL;!1A1;U~wKj==tzs8WJomrack3{{M%QGEN3)CC5;!U*;5pZP6wn7aJ!By1_{@T^m z(dyb*Flrg5oD!PijWzBP-OtrgSVJ_3{2JQgZ;HhHE%D~&NHm6OXD(VYcj>~COnwcV+ zImu6&l+uh@t`wUBDpDVbH`Q5<@rGEaxnVt8Q9Vqu&Y#o+>RuazI*~)a2 z%ADY$+p@kXR^4jU6>6eLqEIiIs+D<}3oq1E8)((p9K_ZSu*J$OFR5Hw zzSxsF7F-2wMPPaL4Uu&gen1LF)*PXkI&kVK*c6Gcf{eW=(cr333k;#dydCr{1GvyxTuhqU&poBSw_tXQcT78Nb8D51<_B{toL6Mj7F@obG^PG zbICldok_0xK_9`|hU%zS3*xgJb4uz&;G(qwKc;r zGzRGzL?bRSx1eF@%0rY%E^QO=*HpKJYPB?V>qzwuD_jh?ST_XbEP>lDTI|sc{FmJd zjk4el8|pMplX09{nMOO7Xh(NwlF)!=0Y{{fMAaUA&2L=@T^ZY^_O#;Xk~M6Mx5WIb ztI_Hk;NlznIfj~p;cc(3s%7aGI{_wATH)>0}wYBUh*+AiRqK(12P<1Tm zaA;hTQT)Ym#4fNJw;y*=X2;r>3Gz_w5M-y}YP-qYslF~hFK=2NI|;g#3z{M*c~#R2 z=t?|*SWq>aNl;teK#1Zh+-L)|Jk#c>C1fctDO%`qD=q%ahEPpas3{c7^rKJlXQGdw ziQ@^uANrzTbS)YNm@r+M?Krew(=Ie=a1?)CFxZSR2i--T9XB{S${fcY7oF_5l7$rr z0oc*Km$8!GWx4imXF;%m@DXDXwJ5;+L3XhTrdMTM}7Mwggkh1Pr2`q7kH85~x_~qL30g zTY1vqv%_#S*bu2jUyLrtY6)F}zFnN=DtK4+nn`Q66YW;o;!P&I#)~@~v`AF%Jo;zG zXu`3x(fXR>F(-(Ep~j3`6Bh;}ImMbBsmYmconloK!`DvCKK+c#$4{PgR$JBumtHjM z)R||`n6Tn99phUyhzy#nn)OyKEY=e1U^i~nMXX>0AovN@Gi7o)td8Lli$|NR*yvh$Ci7cbAB$V61T(#yE?nO)XwD&5EuCBxIGJyQsD7!f8{j z$u*EBfcd#LFhAD{6jhd1SY->XK>3pSmWfeX)}wJY!VYvWR_H7yurMnNTNH9#Q^El^`!9rOs_ z0cF;NVl4nl;;Ptcj6a&J#_CoKdurD}Va;n8lLD{4A;vPJFrk)aNY@%?Sgx)EcW5A1 z3-9RaLv$C|3Rtr!Y4M*3;d;&!n__f69WWZd@ zh}5c;d(pq8WxkfyAa*61wIUcr!9+|a0Cj6$Y#A?%`ZP9&fV#?WWm*0#EsP0PpadLG zj-lnk5UXR=(0vO`HKgx@a><>WS5%OLzbX8|U#`BLhdEC#eLWMxd zlzDTCa!PV?=H%v_Sv+^@lsN@CQ*w)WmzSGgkbma%X;X8i=S-iPKQDheey8Nmotl$B z4c8L1(YnDXPp7D=jWc$P?s%A$!;yk&(6<9OPoAa z(wr0xs%yXitjVftXj$J#jny@1`0|2$t7y?&G&*ULR?)c&E6YnTQBYA?gponXViZ?} zfpl$SvsHyg!gf%FQGG4iPZhjimBgdwf)3ZJV)LqsMq)Y}(ZsZ?*i88|#ij!^O&B-q z%dINi&s4z^)45g!TM4uq6-pEO@I{zBh=OiQ1fy7@)MH?aUwUx)4dGIahFn$O60gy} z1W6rqldWQ#t&)aZB`vvFY!+Q?c1vuHm5nal%0{EXPXs?rk=oUO!oaO;2Hm(chia{C zMDS=_==UwZRkQ|;!oNh?hTkUVUyBA{Wy6z9@aIg=ZmeFPJvC?Q6ss8iCmLF{8q+Pc z6Z}(irW6Q#lE0`a1}Y06zsOo^X-oAgOdL7HW;Rx1xUD;#vz@Nde?g>~oiSnvh?l)~ z%L+?(oBmmLmyn+eGEFV;k}k;nrDd+CxeFI+&ko#@R;Y3z-8>#Dme^R+rlwK>#6<;9 z4i(%dso()roIXdVBp;bcd!*J&r%al9S!=7mF;t7`ya+TMfx@FLx(h+^n2u@9UNo&Q zLLVv2fNrQs|4b)tINL9O0Mh#+8QS*Gq>nZ!k_<6o#y|%)7**G<@k8v3*yFVLvzBRJ zILR;KndEnBK|iZ4#XmC>8mXyW7p=}DU6`;;rA67xV``{&b+C2~{bQDi7g{Ds*o=$J zQ3hKkfmZ*2oNAopM-)Fv#uHMgm}DwCra&X>FtrA2MVOAj96^kKO>q4>bZ;#dScUQW zXC`NWv;g#&)DOYeNtg_y((YX1JwLohO{9Uj(H8u$$8aP%8U11;D%mMG(+jwR!YoHd zG!J2!vEo7Hj&VJuZiKFlV**3(1qLJ`g{BqxI$BHqHCphC)`ixxvc+?kEUUm2>Efl! z;f)uT%_%Q~Pc9BDt)ja$SGY_+TrYHmezql8%ZspP+3i)LFngMNqkYq>|2CMbdB@aa zp3@Cp&+K~n`=@iY^Y?%4nXTdD3j4pNrtg1Av_S3{P*?$tONpGM>qvs ziBH}3;JHvfdDGyU7mu(4cwXs(T@F~Y>)9cIo2>?Zx4CXN*B_eeE9UxZbN!>aer~Qq zL7RWan5*AhC!6a`b1gMjLB`Mjt8$xC_(*-eHYGjv*|HXtlrJt>IBn`=c0>3pLEI7G zyCj6C`l)g?r<|BJKWHbF2CJJ1;k5|9w$|Lwiw1*)1G6$zyQUa3?=kaS5vwbek-T|^ zqreP69XgU=5kTcAV;%>8_*;hYchEc(^F4=?u^6oAB<5LysLsxV5{u(eyc>(n4IxyD sMWXA8VlAyGDNojJ5vql-Vos!$iHj=EEiSLLYtG(@IsW_a|DFW?C#n&382|tP literal 307200 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 z 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 K|NXy{!2ba{ciGVZ diff --git a/programs/develop/oberon07/LICENSE b/programs/develop/oberon07/LICENSE index e56a7ff740..7fd6e69d3a 100644 --- a/programs/develop/oberon07/LICENSE +++ b/programs/develop/oberon07/LICENSE @@ -1,6 +1,6 @@ BSD 2-Clause License -Copyright (c) 2018-2020, Anton Krotov +Copyright (c) 2018-2021, Anton Krotov All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/programs/develop/oberon07/Lib/KolibriOS/RTL.ob07 b/programs/develop/oberon07/Lib/KolibriOS/RTL.ob07 deleted file mode 100644 index 5f9e168085..0000000000 --- a/programs/develop/oberon07/Lib/KolibriOS/RTL.ob07 +++ /dev/null @@ -1,520 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018-2020, Anton Krotov - All rights reserved. -*) - -MODULE RTL; - -IMPORT SYSTEM, API; - - -CONST - - bit_depth* = 32; - maxint* = 7FFFFFFFH; - minint* = 80000000H; - - WORD = bit_depth DIV 8; - MAX_SET = bit_depth - 1; - - -VAR - - name: INTEGER; - types: INTEGER; - - -PROCEDURE [stdcall] _move* (bytes, dest, source: INTEGER); -BEGIN - SYSTEM.CODE( - 08BH, 045H, 008H, (* mov eax, dword [ebp + 8] *) - 085H, 0C0H, (* test eax, eax *) - 07EH, 019H, (* jle L *) - 0FCH, (* cld *) - 057H, (* push edi *) - 056H, (* push esi *) - 08BH, 075H, 010H, (* mov esi, dword [ebp + 16] *) - 08BH, 07DH, 00CH, (* mov edi, dword [ebp + 12] *) - 089H, 0C1H, (* mov ecx, eax *) - 0C1H, 0E9H, 002H, (* shr ecx, 2 *) - 0F3H, 0A5H, (* rep movsd *) - 089H, 0C1H, (* mov ecx, eax *) - 083H, 0E1H, 003H, (* and ecx, 3 *) - 0F3H, 0A4H, (* rep movsb *) - 05EH, (* pop esi *) - 05FH (* pop edi *) - (* L: *) - ) -END _move; - - -PROCEDURE [stdcall] _arrcpy* (base_size, len_dst, dst, len_src, src: INTEGER): BOOLEAN; -VAR - res: BOOLEAN; - -BEGIN - IF len_src > len_dst THEN - res := FALSE - ELSE - _move(len_src * base_size, dst, src); - res := TRUE - END - - RETURN res -END _arrcpy; - - -PROCEDURE [stdcall] _strcpy* (chr_size, len_src, src, len_dst, dst: INTEGER); -BEGIN - _move(MIN(len_dst, len_src) * chr_size, dst, src) -END _strcpy; - - -PROCEDURE [stdcall] _rot* (VAR A: ARRAY OF INTEGER); -VAR - i, n, k: INTEGER; - -BEGIN - k := LEN(A) - 1; - n := A[0]; - i := 0; - WHILE i < k DO - A[i] := A[i + 1]; - INC(i) - END; - A[k] := n -END _rot; - - -PROCEDURE [stdcall] _set* (b, a: INTEGER): INTEGER; -BEGIN - IF (a <= b) & (a <= MAX_SET) & (b >= 0) THEN - IF b > MAX_SET THEN - b := MAX_SET - END; - IF a < 0 THEN - a := 0 - END; - a := LSR(ASR(minint, b - a), MAX_SET - b) - ELSE - a := 0 - END - - RETURN a -END _set; - - -PROCEDURE [stdcall] _set1* (a: INTEGER); (* {a} -> eax *) -BEGIN - SYSTEM.CODE( - 031H, 0C0H, (* xor eax, eax *) - 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 8] *) (* ecx <- a *) - 083H, 0F9H, 01FH, (* cmp ecx, 31 *) - 077H, 003H, (* ja L *) - 00FH, 0ABH, 0C8H (* bts eax, ecx *) - (* L: *) - ) -END _set1; - - -PROCEDURE [stdcall] _divmod* (y, x: INTEGER); (* (x div y) -> eax; (x mod y) -> edx *) -BEGIN - SYSTEM.CODE( - 053H, (* push ebx *) - 08BH, 045H, 00CH, (* mov eax, dword [ebp + 12] *) (* eax <- x *) - 031H, 0D2H, (* xor edx, edx *) - 085H, 0C0H, (* test eax, eax *) - 074H, 018H, (* je L2 *) - 07FH, 002H, (* jg L1 *) - 0F7H, 0D2H, (* not edx *) - (* L1: *) - 089H, 0C3H, (* mov ebx, eax *) - 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 8] *) (* ecx <- y *) - 0F7H, 0F9H, (* idiv ecx *) - 085H, 0D2H, (* test edx, edx *) - 074H, 009H, (* je L2 *) - 031H, 0CBH, (* xor ebx, ecx *) - 085H, 0DBH, (* test ebx, ebx *) - 07DH, 003H, (* jge L2 *) - 048H, (* dec eax *) - 001H, 0CAH, (* add edx, ecx *) - (* L2: *) - 05BH (* pop ebx *) - ) -END _divmod; - - -PROCEDURE [stdcall] _new* (t, size: INTEGER; VAR ptr: INTEGER); -BEGIN - ptr := API._NEW(size); - IF ptr # 0 THEN - SYSTEM.PUT(ptr, t); - INC(ptr, WORD) - END -END _new; - - -PROCEDURE [stdcall] _dispose* (VAR ptr: INTEGER); -BEGIN - IF ptr # 0 THEN - ptr := API._DISPOSE(ptr - WORD) - END -END _dispose; - - -PROCEDURE [stdcall] _length* (len, str: INTEGER); -BEGIN - SYSTEM.CODE( - 08BH, 045H, 00CH, (* mov eax, dword [ebp + 0Ch] *) - 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 08h] *) - 048H, (* dec eax *) - (* L1: *) - 040H, (* inc eax *) - 080H, 038H, 000H, (* cmp byte [eax], 0 *) - 074H, 003H, (* jz L2 *) - 0E2H, 0F8H, (* loop L1 *) - 040H, (* inc eax *) - (* L2: *) - 02BH, 045H, 00CH (* sub eax, dword [ebp + 0Ch] *) - ) -END _length; - - -PROCEDURE [stdcall] _lengthw* (len, str: INTEGER); -BEGIN - SYSTEM.CODE( - 08BH, 045H, 00CH, (* mov eax, dword [ebp + 0Ch] *) - 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 08h] *) - 048H, (* dec eax *) - 048H, (* dec eax *) - (* L1: *) - 040H, (* inc eax *) - 040H, (* inc eax *) - 066H, 083H, 038H, 000H, (* cmp word [eax], 0 *) - 074H, 004H, (* jz L2 *) - 0E2H, 0F6H, (* loop L1 *) - 040H, (* inc eax *) - 040H, (* inc eax *) - (* L2: *) - 02BH, 045H, 00CH, (* sub eax, dword [ebp + 0Ch] *) - 0D1H, 0E8H (* shr eax, 1 *) - ) -END _lengthw; - - -PROCEDURE [stdcall] strncmp (a, b, n: INTEGER): INTEGER; -BEGIN - SYSTEM.CODE( - 056H, (* push esi *) - 057H, (* push edi *) - 053H, (* push ebx *) - 08BH, 075H, 008H, (* mov esi, dword[ebp + 8]; esi <- a *) - 08BH, 07DH, 00CH, (* mov edi, dword[ebp + 12]; edi <- b *) - 08BH, 05DH, 010H, (* mov ebx, dword[ebp + 16]; ebx <- n *) - 031H, 0C9H, (* xor ecx, ecx *) - 031H, 0D2H, (* xor edx, edx *) - 0B8H, - 000H, 000H, 000H, 080H, (* mov eax, minint *) - (* L1: *) - 085H, 0DBH, (* test ebx, ebx *) - 07EH, 017H, (* jle L3 *) - 08AH, 00EH, (* mov cl, byte[esi] *) - 08AH, 017H, (* mov dl, byte[edi] *) - 046H, (* inc esi *) - 047H, (* inc edi *) - 04BH, (* dec ebx *) - 039H, 0D1H, (* cmp ecx, edx *) - 074H, 006H, (* je L2 *) - 089H, 0C8H, (* mov eax, ecx *) - 029H, 0D0H, (* sub eax, edx *) - 0EBH, 006H, (* jmp L3 *) - (* L2: *) - 085H, 0C9H, (* test ecx, ecx *) - 075H, 0E7H, (* jne L1 *) - 031H, 0C0H, (* xor eax, eax *) - (* L3: *) - 05BH, (* pop ebx *) - 05FH, (* pop edi *) - 05EH, (* pop esi *) - 05DH, (* pop ebp *) - 0C2H, 00CH, 000H (* ret 12 *) - ) - RETURN 0 -END strncmp; - - -PROCEDURE [stdcall] strncmpw (a, b, n: INTEGER): INTEGER; -BEGIN - SYSTEM.CODE( - 056H, (* push esi *) - 057H, (* push edi *) - 053H, (* push ebx *) - 08BH, 075H, 008H, (* mov esi, dword[ebp + 8]; esi <- a *) - 08BH, 07DH, 00CH, (* mov edi, dword[ebp + 12]; edi <- b *) - 08BH, 05DH, 010H, (* mov ebx, dword[ebp + 16]; ebx <- n *) - 031H, 0C9H, (* xor ecx, ecx *) - 031H, 0D2H, (* xor edx, edx *) - 0B8H, - 000H, 000H, 000H, 080H, (* mov eax, minint *) - (* L1: *) - 085H, 0DBH, (* test ebx, ebx *) - 07EH, 01BH, (* jle L3 *) - 066H, 08BH, 00EH, (* mov cx, word[esi] *) - 066H, 08BH, 017H, (* mov dx, word[edi] *) - 046H, (* inc esi *) - 046H, (* inc esi *) - 047H, (* inc edi *) - 047H, (* inc edi *) - 04BH, (* dec ebx *) - 039H, 0D1H, (* cmp ecx, edx *) - 074H, 006H, (* je L2 *) - 089H, 0C8H, (* mov eax, ecx *) - 029H, 0D0H, (* sub eax, edx *) - 0EBH, 006H, (* jmp L3 *) - (* L2: *) - 085H, 0C9H, (* test ecx, ecx *) - 075H, 0E3H, (* jne L1 *) - 031H, 0C0H, (* xor eax, eax *) - (* L3: *) - 05BH, (* pop ebx *) - 05FH, (* pop edi *) - 05EH, (* pop esi *) - 05DH, (* pop ebp *) - 0C2H, 00CH, 000H (* ret 12 *) - ) - RETURN 0 -END strncmpw; - - -PROCEDURE [stdcall] _strcmp* (op, len2, str2, len1, str1: INTEGER): BOOLEAN; -VAR - res: INTEGER; - bRes: BOOLEAN; - c: CHAR; - -BEGIN - res := strncmp(str1, str2, MIN(len1, len2)); - IF res = minint THEN - IF len1 > len2 THEN - SYSTEM.GET(str1 + len2, c); - res := ORD(c) - ELSIF len1 < len2 THEN - SYSTEM.GET(str2 + len1, c); - res := -ORD(c) - ELSE - res := 0 - END - END; - - CASE op OF - |0: bRes := res = 0 - |1: bRes := res # 0 - |2: bRes := res < 0 - |3: bRes := res <= 0 - |4: bRes := res > 0 - |5: bRes := res >= 0 - END - - RETURN bRes -END _strcmp; - - -PROCEDURE [stdcall] _strcmpw* (op, len2, str2, len1, str1: INTEGER): BOOLEAN; -VAR - res: INTEGER; - bRes: BOOLEAN; - c: WCHAR; - -BEGIN - res := strncmpw(str1, str2, MIN(len1, len2)); - IF res = minint THEN - IF len1 > len2 THEN - SYSTEM.GET(str1 + len2 * 2, c); - res := ORD(c) - ELSIF len1 < len2 THEN - SYSTEM.GET(str2 + len1 * 2, c); - res := -ORD(c) - ELSE - res := 0 - END - END; - - CASE op OF - |0: bRes := res = 0 - |1: bRes := res # 0 - |2: bRes := res < 0 - |3: bRes := res <= 0 - |4: bRes := res > 0 - |5: bRes := res >= 0 - END - - RETURN bRes -END _strcmpw; - - -PROCEDURE PCharToStr (pchar: INTEGER; VAR s: ARRAY OF CHAR); -VAR - c: CHAR; - i: INTEGER; - -BEGIN - i := 0; - REPEAT - SYSTEM.GET(pchar, c); - s[i] := c; - INC(pchar); - INC(i) - UNTIL c = 0X -END PCharToStr; - - -PROCEDURE IntToStr (x: INTEGER; VAR str: ARRAY OF CHAR); -VAR - i, a: INTEGER; - -BEGIN - i := 0; - a := x; - REPEAT - INC(i); - a := a DIV 10 - UNTIL a = 0; - - str[i] := 0X; - - REPEAT - DEC(i); - str[i] := CHR(x MOD 10 + ORD("0")); - x := x DIV 10 - UNTIL x = 0 -END IntToStr; - - -PROCEDURE append (VAR s1: ARRAY OF CHAR; s2: ARRAY OF CHAR); -VAR - n1, n2: INTEGER; - -BEGIN - n1 := LENGTH(s1); - n2 := LENGTH(s2); - - ASSERT(n1 + n2 < LEN(s1)); - - SYSTEM.MOVE(SYSTEM.ADR(s2[0]), SYSTEM.ADR(s1[n1]), n2); - s1[n1 + n2] := 0X -END append; - - -PROCEDURE [stdcall] _error* (modnum, _module, err, line: INTEGER); -VAR - s, temp: ARRAY 1024 OF CHAR; - -BEGIN - CASE err OF - | 1: s := "assertion failure" - | 2: s := "NIL dereference" - | 3: s := "bad divisor" - | 4: s := "NIL procedure call" - | 5: s := "type guard error" - | 6: s := "index out of range" - | 7: s := "invalid CASE" - | 8: s := "array assignment error" - | 9: s := "CHR out of range" - |10: s := "WCHR out of range" - |11: s := "BYTE out of range" - END; - - append(s, API.eol + "module: "); PCharToStr(_module, temp); append(s, temp); - append(s, API.eol + "line: "); IntToStr(line, temp); append(s, temp); - - API.DebugMsg(SYSTEM.ADR(s[0]), name); - - API.exit_thread(0) -END _error; - - -PROCEDURE [stdcall] _isrec* (t0, t1, r: INTEGER): INTEGER; -BEGIN - SYSTEM.GET(t0 + t1 + types, t0) - RETURN t0 MOD 2 -END _isrec; - - -PROCEDURE [stdcall] _is* (t0, p: INTEGER): INTEGER; -BEGIN - IF p # 0 THEN - SYSTEM.GET(p - WORD, p); - SYSTEM.GET(t0 + p + types, p) - END - - RETURN p MOD 2 -END _is; - - -PROCEDURE [stdcall] _guardrec* (t0, t1: INTEGER): INTEGER; -BEGIN - SYSTEM.GET(t0 + t1 + types, t0) - RETURN t0 MOD 2 -END _guardrec; - - -PROCEDURE [stdcall] _guard* (t0, p: INTEGER): INTEGER; -BEGIN - SYSTEM.GET(p, p); - IF p # 0 THEN - SYSTEM.GET(p - WORD, p); - SYSTEM.GET(t0 + p + types, p) - ELSE - p := 1 - END - - RETURN p MOD 2 -END _guard; - - -PROCEDURE [stdcall] _dllentry* (hinstDLL, fdwReason, lpvReserved: INTEGER): INTEGER; - RETURN API.dllentry(hinstDLL, fdwReason, lpvReserved) -END _dllentry; - - -PROCEDURE [stdcall] _sofinit*; -BEGIN - API.sofinit -END _sofinit; - - -PROCEDURE [stdcall] _exit* (code: INTEGER); -BEGIN - API.exit(code) -END _exit; - - -PROCEDURE [stdcall] _init* (modname: INTEGER; tcount, _types: INTEGER; code, param: INTEGER); -VAR - t0, t1, i, j: INTEGER; - -BEGIN - SYSTEM.CODE(09BH, 0DBH, 0E3H); (* finit *) - API.init(param, code); - - types := API._NEW(tcount * tcount + SYSTEM.SIZE(INTEGER)); - ASSERT(types # 0); - FOR i := 0 TO tcount - 1 DO - FOR j := 0 TO tcount - 1 DO - t0 := i; t1 := j; - - WHILE (t1 # 0) & (t1 # t0) DO - SYSTEM.GET(_types + t1 * WORD, t1) - END; - - SYSTEM.PUT8(i * tcount + j + types, ORD(t0 = t1)) - END - END; - - name := modname -END _init; - - -END RTL. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux32/API.ob07 b/programs/develop/oberon07/Lib/Linux32/API.ob07 deleted file mode 100644 index 754147401f..0000000000 --- a/programs/develop/oberon07/Lib/Linux32/API.ob07 +++ /dev/null @@ -1,123 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2019-2020, Anton Krotov - All rights reserved. -*) - -MODULE API; - -IMPORT SYSTEM; - - -CONST - - eol* = 0AX; - - BIT_DEPTH* = 32; - - RTLD_LAZY = 1; - - -TYPE - - SOFINI = PROCEDURE; - - -VAR - - MainParam*, libc*: INTEGER; - - dlopen* : PROCEDURE [linux] (filename, flag: INTEGER): INTEGER; - dlsym* : PROCEDURE [linux] (handle, symbol: INTEGER): INTEGER; - - exit*, - exit_thread* : PROCEDURE [linux] (code: INTEGER); - puts : PROCEDURE [linux] (pStr: INTEGER); - malloc : PROCEDURE [linux] (size: INTEGER): INTEGER; - free : PROCEDURE [linux] (ptr: INTEGER); - - fini: SOFINI; - - -PROCEDURE DebugMsg* (lpText, lpCaption: INTEGER); -BEGIN - puts(lpCaption); - puts(lpText) -END DebugMsg; - - -PROCEDURE _NEW* (size: INTEGER): INTEGER; -VAR - res, ptr, words: INTEGER; - -BEGIN - res := malloc(size); - IF res # 0 THEN - ptr := res; - words := size DIV SYSTEM.SIZE(INTEGER); - WHILE words > 0 DO - SYSTEM.PUT(ptr, 0); - INC(ptr, SYSTEM.SIZE(INTEGER)); - DEC(words) - END - END - - RETURN res -END _NEW; - - -PROCEDURE _DISPOSE* (p: INTEGER): INTEGER; -BEGIN - free(p) - RETURN 0 -END _DISPOSE; - - -PROCEDURE GetSym (lib: INTEGER; name: ARRAY OF CHAR; VarAdr: INTEGER); -VAR - sym: INTEGER; - -BEGIN - sym := dlsym(lib, SYSTEM.ADR(name[0])); - ASSERT(sym # 0); - SYSTEM.PUT(VarAdr, sym) -END GetSym; - - -PROCEDURE init* (sp, code: INTEGER); -BEGIN - fini := NIL; - SYSTEM.GET(code - 1000H - SYSTEM.SIZE(INTEGER) * 2, dlopen); - SYSTEM.GET(code - 1000H - SYSTEM.SIZE(INTEGER), dlsym); - MainParam := sp; - - libc := dlopen(SYSTEM.SADR("libc.so.6"), RTLD_LAZY); - GetSym(libc, "exit", SYSTEM.ADR(exit_thread)); - exit := exit_thread; - GetSym(libc, "puts", SYSTEM.ADR(puts)); - GetSym(libc, "malloc", SYSTEM.ADR(malloc)); - GetSym(libc, "free", SYSTEM.ADR(free)); -END init; - - -PROCEDURE dllentry* (hinstDLL, fdwReason, lpvReserved: INTEGER): INTEGER; - RETURN 0 -END dllentry; - - -PROCEDURE sofinit*; -BEGIN - IF fini # NIL THEN - fini - END -END sofinit; - - -PROCEDURE SetFini* (ProcFini: SOFINI); -BEGIN - fini := ProcFini -END SetFini; - - -END API. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux32/Args.ob07 b/programs/develop/oberon07/Lib/Linux32/Args.ob07 deleted file mode 100644 index cb3379a784..0000000000 --- a/programs/develop/oberon07/Lib/Linux32/Args.ob07 +++ /dev/null @@ -1,70 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2020, Anton Krotov - All rights reserved. -*) - -MODULE Args; - -IMPORT SYSTEM, API; - - -VAR - - argc*, envc*: INTEGER; - - -PROCEDURE GetArg* (n: INTEGER; VAR s: ARRAY OF CHAR); -VAR - i, len, ptr: INTEGER; - c: CHAR; - -BEGIN - i := 0; - len := LEN(s) - 1; - IF (0 <= n) & (n <= argc + envc) & (n # argc) & (len > 0) THEN - SYSTEM.GET(API.MainParam + (n + 1) * SYSTEM.SIZE(INTEGER), ptr); - REPEAT - SYSTEM.GET(ptr, c); - s[i] := c; - INC(i); - INC(ptr) - UNTIL (c = 0X) OR (i = len) - END; - s[i] := 0X -END GetArg; - - -PROCEDURE GetEnv* (n: INTEGER; VAR s: ARRAY OF CHAR); -BEGIN - IF (0 <= n) & (n < envc) THEN - GetArg(n + argc + 1, s) - ELSE - s[0] := 0X - END -END GetEnv; - - -PROCEDURE init; -VAR - ptr: INTEGER; - -BEGIN - IF API.MainParam # 0 THEN - envc := -1; - SYSTEM.GET(API.MainParam, argc); - REPEAT - SYSTEM.GET(API.MainParam + (envc + argc + 3) * SYSTEM.SIZE(INTEGER), ptr); - INC(envc) - UNTIL ptr = 0 - ELSE - envc := 0; - argc := 0 - END -END init; - - -BEGIN - init -END Args. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux32/File.ob07 b/programs/develop/oberon07/Lib/Linux32/File.ob07 deleted file mode 100644 index f200014f51..0000000000 --- a/programs/develop/oberon07/Lib/Linux32/File.ob07 +++ /dev/null @@ -1,132 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2020, Anton Krotov - All rights reserved. -*) - -MODULE File; - -IMPORT SYSTEM, Libdl, API; - - -CONST - - OPEN_R* = "rb"; OPEN_W* = "wb"; OPEN_RW* = "r+b"; - SEEK_BEG* = 0; SEEK_CUR* = 1; SEEK_END* = 2; - - -VAR - - fwrite, - fread : PROCEDURE [linux] (buffer, bytes, blocks, file: INTEGER): INTEGER; - fseek : PROCEDURE [linux] (file, offset, origin: INTEGER): INTEGER; - ftell : PROCEDURE [linux] (file: INTEGER): INTEGER; - fopen : PROCEDURE [linux] (fname, fmode: INTEGER): INTEGER; - fclose : PROCEDURE [linux] (file: INTEGER): INTEGER; - remove : PROCEDURE [linux] (fname: INTEGER): INTEGER; - - -PROCEDURE GetSym (lib: INTEGER; name: ARRAY OF CHAR; VarAdr: INTEGER); -VAR - sym: INTEGER; - -BEGIN - sym := Libdl.sym(lib, name); - ASSERT(sym # 0); - SYSTEM.PUT(VarAdr, sym) -END GetSym; - - -PROCEDURE init; -VAR - libc: INTEGER; - -BEGIN - libc := Libdl.open("libc.so.6", Libdl.LAZY); - ASSERT(libc # 0); - - GetSym(libc, "fread", SYSTEM.ADR(fread)); - GetSym(libc, "fwrite", SYSTEM.ADR(fwrite)); - GetSym(libc, "fseek", SYSTEM.ADR(fseek)); - GetSym(libc, "ftell", SYSTEM.ADR(ftell)); - GetSym(libc, "fopen", SYSTEM.ADR(fopen)); - GetSym(libc, "fclose", SYSTEM.ADR(fclose)); - GetSym(libc, "remove", SYSTEM.ADR(remove)); -END init; - - -PROCEDURE Delete* (FName: ARRAY OF CHAR): BOOLEAN; - RETURN remove(SYSTEM.ADR(FName[0])) = 0 -END Delete; - - -PROCEDURE Close* (F: INTEGER); -BEGIN - F := fclose(F) -END Close; - - -PROCEDURE Open* (FName, Mode: ARRAY OF CHAR): INTEGER; - RETURN fopen(SYSTEM.ADR(FName[0]), SYSTEM.ADR(Mode[0])) -END Open; - - -PROCEDURE Create* (FName: ARRAY OF CHAR): INTEGER; - RETURN Open(FName, OPEN_W) -END Create; - - -PROCEDURE Seek* (F, Offset, Origin: INTEGER): INTEGER; -VAR - res: INTEGER; - -BEGIN - IF fseek(F, Offset, Origin) = 0 THEN - res := ftell(F) - ELSE - res := -1 - END - - RETURN res -END Seek; - - -PROCEDURE Write* (F, Buffer, Count: INTEGER): INTEGER; - RETURN fwrite(Buffer, 1, Count, F) -END Write; - - -PROCEDURE Read* (F, Buffer, Count: INTEGER): INTEGER; - RETURN fread(Buffer, 1, Count, F) -END Read; - - -PROCEDURE Load* (FName: ARRAY OF CHAR; VAR Size: INTEGER): INTEGER; -VAR - res, n, F: INTEGER; - -BEGIN - res := 0; - F := Open(FName, OPEN_R); - - IF F > 0 THEN - Size := Seek(F, 0, SEEK_END); - n := Seek(F, 0, SEEK_BEG); - res := API._NEW(Size); - IF (res = 0) OR (Read(F, res, Size) # Size) THEN - IF res # 0 THEN - res := API._DISPOSE(res); - Size := 0 - END - END; - Close(F) - END - - RETURN res -END Load; - - -BEGIN - init -END File. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux32/HOST.ob07 b/programs/develop/oberon07/Lib/Linux32/HOST.ob07 deleted file mode 100644 index 53676801f7..0000000000 --- a/programs/develop/oberon07/Lib/Linux32/HOST.ob07 +++ /dev/null @@ -1,248 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2019-2020, Anton Krotov - All rights reserved. -*) - -MODULE HOST; - -IMPORT SYSTEM, API, RTL; - - -CONST - - slash* = "/"; - eol* = 0AX; - - bit_depth* = RTL.bit_depth; - maxint* = RTL.maxint; - minint* = RTL.minint; - - RTLD_LAZY = 1; - - -TYPE - - TP = ARRAY 2 OF INTEGER; - - -VAR - - maxreal*: REAL; - - argc: INTEGER; - - libc, librt: INTEGER; - - stdout: INTEGER; - - fread, fwrite : PROCEDURE [linux] (buffer, bytes, blocks, file: INTEGER): INTEGER; - fopen : PROCEDURE [linux] (fname, fmode: INTEGER): INTEGER; - fclose : PROCEDURE [linux] (file: INTEGER): INTEGER; - _chmod : PROCEDURE [linux] (fname: INTEGER; mode: SET): INTEGER; - time : PROCEDURE [linux] (ptr: INTEGER): INTEGER; - clock_gettime : PROCEDURE [linux] (clock_id: INTEGER; VAR tp: TP): INTEGER; - exit : PROCEDURE [linux] (code: INTEGER); - - -PROCEDURE ExitProcess* (code: INTEGER); -BEGIN - exit(code) -END ExitProcess; - - -PROCEDURE GetArg* (n: INTEGER; VAR s: ARRAY OF CHAR); -VAR - i, len, ptr: INTEGER; - c: CHAR; - -BEGIN - i := 0; - len := LEN(s) - 1; - IF (n < argc) & (len > 0) THEN - SYSTEM.GET(API.MainParam + (n + 1) * SYSTEM.SIZE(INTEGER), ptr); - REPEAT - SYSTEM.GET(ptr, c); - s[i] := c; - INC(i); - INC(ptr) - UNTIL (c = 0X) OR (i = len) - END; - s[i] := 0X -END GetArg; - - -PROCEDURE GetCurrentDirectory* (VAR path: ARRAY OF CHAR); -VAR - n: INTEGER; - -BEGIN - GetArg(0, path); - n := LENGTH(path) - 1; - WHILE path[n] # slash DO - DEC(n) - END; - path[n + 1] := 0X -END GetCurrentDirectory; - - -PROCEDURE FileRead* (F: INTEGER; VAR Buffer: ARRAY OF CHAR; bytes: INTEGER): INTEGER; -VAR - res: INTEGER; - -BEGIN - res := fread(SYSTEM.ADR(Buffer[0]), 1, bytes, F); - IF res <= 0 THEN - res := -1 - END - - RETURN res -END FileRead; - - -PROCEDURE FileWrite* (F: INTEGER; Buffer: ARRAY OF BYTE; bytes: INTEGER): INTEGER; -VAR - res: INTEGER; - -BEGIN - res := fwrite(SYSTEM.ADR(Buffer[0]), 1, bytes, F); - IF res <= 0 THEN - res := -1 - END - - RETURN res -END FileWrite; - - -PROCEDURE FileCreate* (FName: ARRAY OF CHAR): INTEGER; - RETURN fopen(SYSTEM.ADR(FName[0]), SYSTEM.SADR("wb")) -END FileCreate; - - -PROCEDURE FileClose* (File: INTEGER); -BEGIN - File := fclose(File) -END FileClose; - - -PROCEDURE chmod* (FName: ARRAY OF CHAR); -VAR - res: INTEGER; -BEGIN - res := _chmod(SYSTEM.ADR(FName[0]), {0, 2..8}) (* rwxrwxr-x *) -END chmod; - - -PROCEDURE FileOpen* (FName: ARRAY OF CHAR): INTEGER; - RETURN fopen(SYSTEM.ADR(FName[0]), SYSTEM.SADR("rb")) -END FileOpen; - - -PROCEDURE OutChar* (c: CHAR); -VAR - res: INTEGER; - -BEGIN - res := fwrite(SYSTEM.ADR(c), 1, 1, stdout) -END OutChar; - - -PROCEDURE GetTickCount* (): INTEGER; -VAR - tp: TP; - res: INTEGER; - -BEGIN - IF clock_gettime(0, tp) = 0 THEN - res := tp[0] * 100 + tp[1] DIV 10000000 - ELSE - res := 0 - END - - RETURN res -END GetTickCount; - - -PROCEDURE isRelative* (path: ARRAY OF CHAR): BOOLEAN; - RETURN path[0] # slash -END isRelative; - - -PROCEDURE UnixTime* (): INTEGER; - RETURN time(0) -END UnixTime; - - -PROCEDURE splitf* (x: REAL; VAR a, b: INTEGER): INTEGER; -BEGIN - SYSTEM.GET32(SYSTEM.ADR(x), a); - SYSTEM.GET32(SYSTEM.ADR(x) + 4, b) - RETURN a -END splitf; - - -PROCEDURE d2s* (x: REAL): INTEGER; -VAR - h, l, s, e: INTEGER; - -BEGIN - e := splitf(x, l, h); - - s := ASR(h, 31) MOD 2; - e := (h DIV 100000H) MOD 2048; - IF e <= 896 THEN - h := (h MOD 100000H) * 8 + (l DIV 20000000H) MOD 8 + 800000H; - REPEAT - h := h DIV 2; - INC(e) - UNTIL e = 897; - e := 896; - l := (h MOD 8) * 20000000H; - h := h DIV 8 - ELSIF (1151 <= e) & (e < 2047) THEN - e := 1151; - h := 0; - l := 0 - ELSIF e = 2047 THEN - e := 1151; - IF (h MOD 100000H # 0) OR (BITS(l) * {0..31} # {}) THEN - h := 80000H; - l := 0 - END - END; - DEC(e, 896) - - RETURN LSL(s, 31) + LSL(e, 23) + (h MOD 100000H) * 8 + (l DIV 20000000H) MOD 8 -END d2s; - - -PROCEDURE GetSym (lib: INTEGER; name: ARRAY OF CHAR; VarAdr: INTEGER); -VAR - sym: INTEGER; - -BEGIN - sym := API.dlsym(lib, SYSTEM.ADR(name[0])); - ASSERT(sym # 0); - SYSTEM.PUT(VarAdr, sym) -END GetSym; - - -BEGIN - maxreal := 1.9; - PACK(maxreal, 1023); - SYSTEM.GET(API.MainParam, argc); - - libc := API.libc; - GetSym(libc, "fread", SYSTEM.ADR(fread)); - GetSym(libc, "fwrite", SYSTEM.ADR(fwrite)); - GetSym(libc, "fopen", SYSTEM.ADR(fopen)); - GetSym(libc, "fclose", SYSTEM.ADR(fclose)); - GetSym(libc, "chmod", SYSTEM.ADR(_chmod)); - GetSym(libc, "time", SYSTEM.ADR(time)); - GetSym(libc, "exit", SYSTEM.ADR(exit)); - GetSym(libc, "stdout", SYSTEM.ADR(stdout)); SYSTEM.GET(stdout - SYSTEM.SIZE(INTEGER), stdout); - - librt := API.dlopen(SYSTEM.SADR("librt.so.1"), RTLD_LAZY); - GetSym(librt, "clock_gettime", SYSTEM.ADR(clock_gettime)) -END HOST. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux32/In.ob07 b/programs/develop/oberon07/Lib/Linux32/In.ob07 deleted file mode 100644 index f5b487754c..0000000000 --- a/programs/develop/oberon07/Lib/Linux32/In.ob07 +++ /dev/null @@ -1,85 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2020, Anton Krotov - All rights reserved. -*) - -MODULE In; - -IMPORT SYSTEM, Libdl; - - -CONST - - MAX_LEN = 10240; - - -VAR - - Done*: BOOLEAN; - s: ARRAY MAX_LEN + 4 OF CHAR; - - sscanf: PROCEDURE [linux] (buf: INTEGER; fmt: INTEGER; adr: INTEGER): INTEGER; - gets: PROCEDURE [linux] (buf: INTEGER); - - -PROCEDURE String* (VAR str: ARRAY OF CHAR); -BEGIN - gets(SYSTEM.ADR(s[0])); - COPY(s, str); - str[LEN(str) - 1] := 0X; - Done := TRUE -END String; - - -PROCEDURE Int* (VAR x: INTEGER); -BEGIN - String(s); - Done := sscanf(SYSTEM.ADR(s[0]), SYSTEM.SADR("%d"), SYSTEM.ADR(x)) = 1 -END Int; - - -PROCEDURE Real* (VAR x: REAL); -BEGIN - String(s); - Done := sscanf(SYSTEM.ADR(s[0]), SYSTEM.SADR("%lf"), SYSTEM.ADR(x)) = 1 -END Real; - - -PROCEDURE Char* (VAR x: CHAR); -BEGIN - String(s); - x := s[0] -END Char; - - -PROCEDURE Ln*; -BEGIN - String(s) -END Ln; - - -PROCEDURE Open*; -BEGIN - Done := TRUE -END Open; - - -PROCEDURE init; -VAR - libc: INTEGER; - -BEGIN - libc := Libdl.open("libc.so.6", Libdl.LAZY); - ASSERT(libc # 0); - SYSTEM.PUT(SYSTEM.ADR(sscanf), Libdl.sym(libc, "sscanf")); - ASSERT(sscanf # NIL); - SYSTEM.PUT(SYSTEM.ADR(gets), Libdl.sym(libc, "gets")); - ASSERT(gets # NIL); -END init; - - -BEGIN - init -END In. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux32/LINAPI.ob07 b/programs/develop/oberon07/Lib/Linux32/LINAPI.ob07 deleted file mode 100644 index 497660a264..0000000000 --- a/programs/develop/oberon07/Lib/Linux32/LINAPI.ob07 +++ /dev/null @@ -1,106 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2019-2020, Anton Krotov - All rights reserved. -*) - -MODULE LINAPI; - -IMPORT SYSTEM, API, Libdl; - - -TYPE - - TP* = ARRAY 2 OF INTEGER; - SOFINI* = PROCEDURE; - - -VAR - - libc*, librt*: INTEGER; - - stdout*, - stdin*, - stderr* : INTEGER; - - malloc* : PROCEDURE [linux] (size: INTEGER): INTEGER; - free* : PROCEDURE [linux] (ptr: INTEGER); - exit* : PROCEDURE [linux] (code: INTEGER); - puts* : PROCEDURE [linux] (pStr: INTEGER); - fwrite*, - fread* : PROCEDURE [linux] (buffer, bytes, blocks, file: INTEGER): INTEGER; - fopen* : PROCEDURE [linux] (fname, fmode: INTEGER): INTEGER; - fclose* : PROCEDURE [linux] (file: INTEGER): INTEGER; - time* : PROCEDURE [linux] (ptr: INTEGER): INTEGER; - - clock_gettime* : PROCEDURE [linux] (clock_id: INTEGER; VAR tp: TP): INTEGER; - - -PROCEDURE SetFini* (ProcFini: SOFINI); -BEGIN - API.SetFini(ProcFini) -END SetFini; - - -PROCEDURE GetSym (lib: INTEGER; name: ARRAY OF CHAR; VarAdr: INTEGER); -VAR - sym: INTEGER; - -BEGIN - sym := Libdl.sym(lib, name); - ASSERT(sym # 0); - SYSTEM.PUT(VarAdr, sym) -END GetSym; - - -PROCEDURE init; -BEGIN - libc := API.libc; - - GetSym(libc, "exit", SYSTEM.ADR(exit)); - GetSym(libc, "puts", SYSTEM.ADR(puts)); - GetSym(libc, "malloc", SYSTEM.ADR(malloc)); - GetSym(libc, "free", SYSTEM.ADR(free)); - GetSym(libc, "fread", SYSTEM.ADR(fread)); - GetSym(libc, "fwrite", SYSTEM.ADR(fwrite)); - GetSym(libc, "fopen", SYSTEM.ADR(fopen)); - GetSym(libc, "fclose", SYSTEM.ADR(fclose)); - GetSym(libc, "time", SYSTEM.ADR(time)); - - GetSym(libc, "stdout", SYSTEM.ADR(stdout)); SYSTEM.GET(stdout - SYSTEM.SIZE(INTEGER), stdout); - GetSym(libc, "stdin", SYSTEM.ADR(stdin)); SYSTEM.GET(stdin - SYSTEM.SIZE(INTEGER), stdin); - GetSym(libc, "stderr", SYSTEM.ADR(stderr)); SYSTEM.GET(stderr - SYSTEM.SIZE(INTEGER), stderr); - - librt := Libdl.open("librt.so.1", Libdl.LAZY); - - GetSym(librt, "clock_gettime", SYSTEM.ADR(clock_gettime)) -END init; - - -PROCEDURE [stdcall-] syscall* (eax, ebx, ecx, edx, esi, edi: INTEGER): INTEGER; -BEGIN - SYSTEM.CODE( - 053H, (* push ebx *) - 056H, (* push esi *) - 057H, (* push edi *) - 08BH, 045H, 008H, (* mov eax, dword [ebp + 8] *) - 08BH, 05DH, 00CH, (* mov ebx, dword [ebp + 12] *) - 08BH, 04DH, 010H, (* mov ecx, dword [ebp + 16] *) - 08BH, 055H, 014H, (* mov edx, dword [ebp + 20] *) - 08BH, 075H, 018H, (* mov esi, dword [ebp + 24] *) - 08BH, 07DH, 01CH, (* mov edi, dword [ebp + 28] *) - 0CDH, 080H, (* int 128 *) - 05FH, (* pop edi *) - 05EH, (* pop esi *) - 05BH, (* pop ebx *) - 0C9H, (* leave *) - 0C2H, 018H, 000H (* ret 24 *) - ) - RETURN 0 -END syscall; - - -BEGIN - init -END LINAPI. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux32/Libdl.ob07 b/programs/develop/oberon07/Lib/Linux32/Libdl.ob07 deleted file mode 100644 index f8a5781d87..0000000000 --- a/programs/develop/oberon07/Lib/Linux32/Libdl.ob07 +++ /dev/null @@ -1,65 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2019, Anton Krotov - All rights reserved. -*) - -MODULE Libdl; - -IMPORT SYSTEM, API; - - -CONST - - LAZY* = 1; - NOW* = 2; - BINDING_MASK* = 3; - NOLOAD* = 4; - LOCAL* = 0; - GLOBAL* = 256; - NODELETE* = 4096; - - -VAR - - _close: PROCEDURE [linux] (handle: INTEGER): INTEGER; - _error: PROCEDURE [linux] (): INTEGER; - - -PROCEDURE open* (file: ARRAY OF CHAR; mode: INTEGER): INTEGER; - RETURN API.dlopen(SYSTEM.ADR(file[0]), mode) -END open; - - -PROCEDURE sym* (handle: INTEGER; name: ARRAY OF CHAR): INTEGER; - RETURN API.dlsym(handle, SYSTEM.ADR(name[0])) -END sym; - - -PROCEDURE close* (handle: INTEGER): INTEGER; - RETURN _close(handle) -END close; - - -PROCEDURE error* (): INTEGER; - RETURN _error() -END error; - - -PROCEDURE init; -VAR - lib: INTEGER; - -BEGIN - lib := open("libdl.so.2", LAZY); - SYSTEM.PUT(SYSTEM.ADR(_close), sym(lib, "dlclose")); - ASSERT(_close # NIL); - SYSTEM.PUT(SYSTEM.ADR(_error), sym(lib, "dlerror")); - ASSERT(_error # NIL) -END init; - - -BEGIN - init -END Libdl. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux32/Math.ob07 b/programs/develop/oberon07/Lib/Linux32/Math.ob07 deleted file mode 100644 index beb3bb884c..0000000000 --- a/programs/develop/oberon07/Lib/Linux32/Math.ob07 +++ /dev/null @@ -1,450 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2013-2014, 2018-2020 Anton Krotov - All rights reserved. -*) - -MODULE Math; - -IMPORT SYSTEM; - - -CONST - - pi* = 3.141592653589793; - e* = 2.718281828459045; - - -PROCEDURE IsNan* (x: REAL): BOOLEAN; -VAR - h, l: SET; - -BEGIN - SYSTEM.GET(SYSTEM.ADR(x), l); - SYSTEM.GET(SYSTEM.ADR(x) + 4, h) - RETURN (h * {20..30} = {20..30}) & ((h * {0..19} # {}) OR (l * {0..31} # {})) -END IsNan; - - -PROCEDURE IsInf* (x: REAL): BOOLEAN; - RETURN ABS(x) = SYSTEM.INF() -END IsInf; - - -PROCEDURE Max (a, b: REAL): REAL; -VAR - res: REAL; - -BEGIN - IF a > b THEN - res := a - ELSE - res := b - END - RETURN res -END Max; - - -PROCEDURE Min (a, b: REAL): REAL; -VAR - res: REAL; - -BEGIN - IF a < b THEN - res := a - ELSE - res := b - END - RETURN res -END Min; - - -PROCEDURE SameValue (a, b: REAL): BOOLEAN; -VAR - eps: REAL; - res: BOOLEAN; - -BEGIN - eps := Max(Min(ABS(a), ABS(b)) * 1.0E-12, 1.0E-12); - IF a > b THEN - res := (a - b) <= eps - ELSE - res := (b - a) <= eps - END - RETURN res -END SameValue; - - -PROCEDURE IsZero (x: REAL): BOOLEAN; - RETURN ABS(x) <= 1.0E-12 -END IsZero; - - -PROCEDURE [stdcall] sqrt* (x: REAL): REAL; -BEGIN - SYSTEM.CODE( - 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) - 0D9H, 0FAH, (* fsqrt *) - 0C9H, (* leave *) - 0C2H, 008H, 000H (* ret 08h *) - ) - RETURN 0.0 -END sqrt; - - -PROCEDURE [stdcall] sin* (x: REAL): REAL; -BEGIN - SYSTEM.CODE( - 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) - 0D9H, 0FEH, (* fsin *) - 0C9H, (* leave *) - 0C2H, 008H, 000H (* ret 08h *) - ) - RETURN 0.0 -END sin; - - -PROCEDURE [stdcall] cos* (x: REAL): REAL; -BEGIN - SYSTEM.CODE( - 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) - 0D9H, 0FFH, (* fcos *) - 0C9H, (* leave *) - 0C2H, 008H, 000H (* ret 08h *) - ) - RETURN 0.0 -END cos; - - -PROCEDURE [stdcall] tan* (x: REAL): REAL; -BEGIN - SYSTEM.CODE( - 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) - 0D9H, 0FBH, (* fsincos *) - 0DEH, 0F9H, (* fdivp st1, st *) - 0C9H, (* leave *) - 0C2H, 008H, 000H (* ret 08h *) - ) - RETURN 0.0 -END tan; - - -PROCEDURE [stdcall] arctan2* (y, x: REAL): REAL; -BEGIN - SYSTEM.CODE( - 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) - 0DDH, 045H, 010H, (* fld qword [ebp + 10h] *) - 0D9H, 0F3H, (* fpatan *) - 0C9H, (* leave *) - 0C2H, 010H, 000H (* ret 10h *) - ) - RETURN 0.0 -END arctan2; - - -PROCEDURE [stdcall] ln* (x: REAL): REAL; -BEGIN - SYSTEM.CODE( - 0D9H, 0EDH, (* fldln2 *) - 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) - 0D9H, 0F1H, (* fyl2x *) - 0C9H, (* leave *) - 0C2H, 008H, 000H (* ret 08h *) - ) - RETURN 0.0 -END ln; - - -PROCEDURE [stdcall] log* (base, x: REAL): REAL; -BEGIN - SYSTEM.CODE( - 0D9H, 0E8H, (* fld1 *) - 0DDH, 045H, 010H, (* fld qword [ebp + 10h] *) - 0D9H, 0F1H, (* fyl2x *) - 0D9H, 0E8H, (* fld1 *) - 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) - 0D9H, 0F1H, (* fyl2x *) - 0DEH, 0F9H, (* fdivp st1, st *) - 0C9H, (* leave *) - 0C2H, 010H, 000H (* ret 10h *) - ) - RETURN 0.0 -END log; - - -PROCEDURE [stdcall] exp* (x: REAL): REAL; -BEGIN - SYSTEM.CODE( - 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) - 0D9H, 0EAH, (* fldl2e *) - 0DEH, 0C9H, 0D9H, 0C0H, - 0D9H, 0FCH, 0DCH, 0E9H, - 0D9H, 0C9H, 0D9H, 0F0H, - 0D9H, 0E8H, 0DEH, 0C1H, - 0D9H, 0FDH, 0DDH, 0D9H, - 0C9H, (* leave *) - 0C2H, 008H, 000H (* ret 08h *) - ) - RETURN 0.0 -END exp; - - -PROCEDURE [stdcall] round* (x: REAL): REAL; -BEGIN - SYSTEM.CODE( - 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) - 0D9H, 07DH, 0F4H, 0D9H, - 07DH, 0F6H, 066H, 081H, - 04DH, 0F6H, 000H, 003H, - 0D9H, 06DH, 0F6H, 0D9H, - 0FCH, 0D9H, 06DH, 0F4H, - 0C9H, (* leave *) - 0C2H, 008H, 000H (* ret 08h *) - ) - RETURN 0.0 -END round; - - -PROCEDURE [stdcall] frac* (x: REAL): REAL; -BEGIN - SYSTEM.CODE( - 050H, - 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) - 0D9H, 0C0H, 0D9H, 03CH, - 024H, 0D9H, 07CH, 024H, - 002H, 066H, 081H, 04CH, - 024H, 002H, 000H, 00FH, - 0D9H, 06CH, 024H, 002H, - 0D9H, 0FCH, 0D9H, 02CH, - 024H, 0DEH, 0E9H, - 0C9H, (* leave *) - 0C2H, 008H, 000H (* ret 08h *) - ) - RETURN 0.0 -END frac; - - -PROCEDURE sqri* (x: INTEGER): INTEGER; - RETURN x * x -END sqri; - - -PROCEDURE sqrr* (x: REAL): REAL; - RETURN x * x -END sqrr; - - -PROCEDURE arcsin* (x: REAL): REAL; - RETURN arctan2(x, sqrt(1.0 - x * x)) -END arcsin; - - -PROCEDURE arccos* (x: REAL): REAL; - RETURN arctan2(sqrt(1.0 - x * x), x) -END arccos; - - -PROCEDURE arctan* (x: REAL): REAL; - RETURN arctan2(x, 1.0) -END arctan; - - -PROCEDURE sinh* (x: REAL): REAL; -BEGIN - x := exp(x) - RETURN (x - 1.0 / x) * 0.5 -END sinh; - - -PROCEDURE cosh* (x: REAL): REAL; -BEGIN - x := exp(x) - RETURN (x + 1.0 / x) * 0.5 -END cosh; - - -PROCEDURE tanh* (x: REAL): REAL; -BEGIN - IF x > 15.0 THEN - x := 1.0 - ELSIF x < -15.0 THEN - x := -1.0 - ELSE - x := exp(2.0 * x); - x := (x - 1.0) / (x + 1.0) - END - - RETURN x -END tanh; - - -PROCEDURE arsinh* (x: REAL): REAL; - RETURN ln(x + sqrt(x * x + 1.0)) -END arsinh; - - -PROCEDURE arcosh* (x: REAL): REAL; - RETURN ln(x + sqrt(x * x - 1.0)) -END arcosh; - - -PROCEDURE artanh* (x: REAL): REAL; -VAR - res: REAL; - -BEGIN - IF SameValue(x, 1.0) THEN - res := SYSTEM.INF() - ELSIF SameValue(x, -1.0) THEN - res := -SYSTEM.INF() - ELSE - res := 0.5 * ln((1.0 + x) / (1.0 - x)) - END - RETURN res -END artanh; - - -PROCEDURE floor* (x: REAL): REAL; -VAR - f: REAL; - -BEGIN - f := frac(x); - x := x - f; - IF f < 0.0 THEN - x := x - 1.0 - END - RETURN x -END floor; - - -PROCEDURE ceil* (x: REAL): REAL; -VAR - f: REAL; - -BEGIN - f := frac(x); - x := x - f; - IF f > 0.0 THEN - x := x + 1.0 - END - RETURN x -END ceil; - - -PROCEDURE power* (base, exponent: REAL): REAL; -VAR - res: REAL; - -BEGIN - IF exponent = 0.0 THEN - res := 1.0 - ELSIF (base = 0.0) & (exponent > 0.0) THEN - res := 0.0 - ELSE - res := exp(exponent * ln(base)) - END - RETURN res -END power; - - -PROCEDURE ipower* (base: REAL; exponent: INTEGER): REAL; -VAR - i: INTEGER; - a: REAL; - -BEGIN - a := 1.0; - - IF base # 0.0 THEN - IF exponent # 0 THEN - IF exponent < 0 THEN - base := 1.0 / base - END; - i := ABS(exponent); - WHILE i > 0 DO - WHILE ~ODD(i) DO - i := LSR(i, 1); - base := sqrr(base) - END; - DEC(i); - a := a * base - END - ELSE - a := 1.0 - END - ELSE - ASSERT(exponent > 0); - a := 0.0 - END - - RETURN a -END ipower; - - -PROCEDURE sgn* (x: REAL): INTEGER; -VAR - res: INTEGER; - -BEGIN - IF x > 0.0 THEN - res := 1 - ELSIF x < 0.0 THEN - res := -1 - ELSE - res := 0 - END - - RETURN res -END sgn; - - -PROCEDURE fact* (n: INTEGER): REAL; -VAR - res: REAL; - -BEGIN - res := 1.0; - WHILE n > 1 DO - res := res * FLT(n); - DEC(n) - END - - RETURN res -END fact; - - -PROCEDURE DegToRad* (x: REAL): REAL; - RETURN x * (pi / 180.0) -END DegToRad; - - -PROCEDURE RadToDeg* (x: REAL): REAL; - RETURN x * (180.0 / pi) -END RadToDeg; - - -(* Return hypotenuse of triangle *) -PROCEDURE hypot* (x, y: REAL): REAL; -VAR - a: REAL; - -BEGIN - x := ABS(x); - y := ABS(y); - IF x > y THEN - a := x * sqrt(1.0 + sqrr(y / x)) - ELSE - IF x > 0.0 THEN - a := y * sqrt(1.0 + sqrr(x / y)) - ELSE - a := y - END - END - - RETURN a -END hypot; - - -END Math. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux32/Out.ob07 b/programs/develop/oberon07/Lib/Linux32/Out.ob07 deleted file mode 100644 index c723cf0e5f..0000000000 --- a/programs/develop/oberon07/Lib/Linux32/Out.ob07 +++ /dev/null @@ -1,77 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2020, Anton Krotov - All rights reserved. -*) - -MODULE Out; - -IMPORT SYSTEM, Libdl; - - -VAR - - printf1: PROCEDURE [linux] (fmt: INTEGER; x: INTEGER); - printf2: PROCEDURE [linux] (fmt: INTEGER; width, x: INTEGER); - printf3: PROCEDURE [linux] (fmt: INTEGER; width, precision: INTEGER; x: REAL); - - -PROCEDURE Char* (x: CHAR); -BEGIN - printf1(SYSTEM.SADR("%c"), ORD(x)) -END Char; - - -PROCEDURE String* (s: ARRAY OF CHAR); -BEGIN - printf2(SYSTEM.SADR("%.*s"), LENGTH(s), SYSTEM.ADR(s[0])) -END String; - - -PROCEDURE Ln*; -BEGIN - printf1(SYSTEM.SADR("%s"), SYSTEM.SADR(0AX)) -END Ln; - - -PROCEDURE Int* (x, width: INTEGER); -BEGIN - printf2(SYSTEM.SADR("%*d"), width, x) -END Int; - - -PROCEDURE Real* (x: REAL; width: INTEGER); -BEGIN - printf3(SYSTEM.SADR("%*.*E"), width, MAX(MIN(width - 8, 15), 1), x) -END Real; - - -PROCEDURE FixReal* (x: REAL; width, precision: INTEGER); -BEGIN - printf3(SYSTEM.SADR("%*.*f"), width, precision, x) -END FixReal; - - -PROCEDURE Open*; -END Open; - - -PROCEDURE init; -VAR - libc, printf: INTEGER; - -BEGIN - libc := Libdl.open("libc.so.6", Libdl.LAZY); - ASSERT(libc # 0); - printf := Libdl.sym(libc, "printf"); - ASSERT(printf # 0); - SYSTEM.PUT(SYSTEM.ADR(printf1), printf); - SYSTEM.PUT(SYSTEM.ADR(printf2), printf); - SYSTEM.PUT(SYSTEM.ADR(printf3), printf); -END init; - - -BEGIN - init -END Out. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux64/API.ob07 b/programs/develop/oberon07/Lib/Linux64/API.ob07 deleted file mode 100644 index fb0a96bfa4..0000000000 --- a/programs/develop/oberon07/Lib/Linux64/API.ob07 +++ /dev/null @@ -1,123 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2019-2020, Anton Krotov - All rights reserved. -*) - -MODULE API; - -IMPORT SYSTEM; - - -CONST - - eol* = 0AX; - - BIT_DEPTH* = 64; - - RTLD_LAZY = 1; - - -TYPE - - SOFINI = PROCEDURE; - - -VAR - - MainParam*, libc*: INTEGER; - - dlopen* : PROCEDURE [linux] (filename, flag: INTEGER): INTEGER; - dlsym* : PROCEDURE [linux] (handle, symbol: INTEGER): INTEGER; - - exit*, - exit_thread* : PROCEDURE [linux] (code: INTEGER); - puts : PROCEDURE [linux] (pStr: INTEGER); - malloc : PROCEDURE [linux] (size: INTEGER): INTEGER; - free : PROCEDURE [linux] (ptr: INTEGER); - - fini: SOFINI; - - -PROCEDURE DebugMsg* (lpText, lpCaption: INTEGER); -BEGIN - puts(lpCaption); - puts(lpText) -END DebugMsg; - - -PROCEDURE _NEW* (size: INTEGER): INTEGER; -VAR - res, ptr, words: INTEGER; - -BEGIN - res := malloc(size); - IF res # 0 THEN - ptr := res; - words := size DIV SYSTEM.SIZE(INTEGER); - WHILE words > 0 DO - SYSTEM.PUT(ptr, 0); - INC(ptr, SYSTEM.SIZE(INTEGER)); - DEC(words) - END - END - - RETURN res -END _NEW; - - -PROCEDURE _DISPOSE* (p: INTEGER): INTEGER; -BEGIN - free(p) - RETURN 0 -END _DISPOSE; - - -PROCEDURE GetSym (lib: INTEGER; name: ARRAY OF CHAR; VarAdr: INTEGER); -VAR - sym: INTEGER; - -BEGIN - sym := dlsym(lib, SYSTEM.ADR(name[0])); - ASSERT(sym # 0); - SYSTEM.PUT(VarAdr, sym) -END GetSym; - - -PROCEDURE init* (sp, code: INTEGER); -BEGIN - fini := NIL; - SYSTEM.GET(code - 1000H - SYSTEM.SIZE(INTEGER) * 2, dlopen); - SYSTEM.GET(code - 1000H - SYSTEM.SIZE(INTEGER), dlsym); - MainParam := sp; - - libc := dlopen(SYSTEM.SADR("libc.so.6"), RTLD_LAZY); - GetSym(libc, "exit", SYSTEM.ADR(exit_thread)); - exit := exit_thread; - GetSym(libc, "puts", SYSTEM.ADR(puts)); - GetSym(libc, "malloc", SYSTEM.ADR(malloc)); - GetSym(libc, "free", SYSTEM.ADR(free)); -END init; - - -PROCEDURE dllentry* (hinstDLL, fdwReason, lpvReserved: INTEGER): INTEGER; - RETURN 0 -END dllentry; - - -PROCEDURE sofinit*; -BEGIN - IF fini # NIL THEN - fini - END -END sofinit; - - -PROCEDURE SetFini* (ProcFini: SOFINI); -BEGIN - fini := ProcFini -END SetFini; - - -END API. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux64/Args.ob07 b/programs/develop/oberon07/Lib/Linux64/Args.ob07 deleted file mode 100644 index cb3379a784..0000000000 --- a/programs/develop/oberon07/Lib/Linux64/Args.ob07 +++ /dev/null @@ -1,70 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2020, Anton Krotov - All rights reserved. -*) - -MODULE Args; - -IMPORT SYSTEM, API; - - -VAR - - argc*, envc*: INTEGER; - - -PROCEDURE GetArg* (n: INTEGER; VAR s: ARRAY OF CHAR); -VAR - i, len, ptr: INTEGER; - c: CHAR; - -BEGIN - i := 0; - len := LEN(s) - 1; - IF (0 <= n) & (n <= argc + envc) & (n # argc) & (len > 0) THEN - SYSTEM.GET(API.MainParam + (n + 1) * SYSTEM.SIZE(INTEGER), ptr); - REPEAT - SYSTEM.GET(ptr, c); - s[i] := c; - INC(i); - INC(ptr) - UNTIL (c = 0X) OR (i = len) - END; - s[i] := 0X -END GetArg; - - -PROCEDURE GetEnv* (n: INTEGER; VAR s: ARRAY OF CHAR); -BEGIN - IF (0 <= n) & (n < envc) THEN - GetArg(n + argc + 1, s) - ELSE - s[0] := 0X - END -END GetEnv; - - -PROCEDURE init; -VAR - ptr: INTEGER; - -BEGIN - IF API.MainParam # 0 THEN - envc := -1; - SYSTEM.GET(API.MainParam, argc); - REPEAT - SYSTEM.GET(API.MainParam + (envc + argc + 3) * SYSTEM.SIZE(INTEGER), ptr); - INC(envc) - UNTIL ptr = 0 - ELSE - envc := 0; - argc := 0 - END -END init; - - -BEGIN - init -END Args. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux64/File.ob07 b/programs/develop/oberon07/Lib/Linux64/File.ob07 deleted file mode 100644 index f200014f51..0000000000 --- a/programs/develop/oberon07/Lib/Linux64/File.ob07 +++ /dev/null @@ -1,132 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2020, Anton Krotov - All rights reserved. -*) - -MODULE File; - -IMPORT SYSTEM, Libdl, API; - - -CONST - - OPEN_R* = "rb"; OPEN_W* = "wb"; OPEN_RW* = "r+b"; - SEEK_BEG* = 0; SEEK_CUR* = 1; SEEK_END* = 2; - - -VAR - - fwrite, - fread : PROCEDURE [linux] (buffer, bytes, blocks, file: INTEGER): INTEGER; - fseek : PROCEDURE [linux] (file, offset, origin: INTEGER): INTEGER; - ftell : PROCEDURE [linux] (file: INTEGER): INTEGER; - fopen : PROCEDURE [linux] (fname, fmode: INTEGER): INTEGER; - fclose : PROCEDURE [linux] (file: INTEGER): INTEGER; - remove : PROCEDURE [linux] (fname: INTEGER): INTEGER; - - -PROCEDURE GetSym (lib: INTEGER; name: ARRAY OF CHAR; VarAdr: INTEGER); -VAR - sym: INTEGER; - -BEGIN - sym := Libdl.sym(lib, name); - ASSERT(sym # 0); - SYSTEM.PUT(VarAdr, sym) -END GetSym; - - -PROCEDURE init; -VAR - libc: INTEGER; - -BEGIN - libc := Libdl.open("libc.so.6", Libdl.LAZY); - ASSERT(libc # 0); - - GetSym(libc, "fread", SYSTEM.ADR(fread)); - GetSym(libc, "fwrite", SYSTEM.ADR(fwrite)); - GetSym(libc, "fseek", SYSTEM.ADR(fseek)); - GetSym(libc, "ftell", SYSTEM.ADR(ftell)); - GetSym(libc, "fopen", SYSTEM.ADR(fopen)); - GetSym(libc, "fclose", SYSTEM.ADR(fclose)); - GetSym(libc, "remove", SYSTEM.ADR(remove)); -END init; - - -PROCEDURE Delete* (FName: ARRAY OF CHAR): BOOLEAN; - RETURN remove(SYSTEM.ADR(FName[0])) = 0 -END Delete; - - -PROCEDURE Close* (F: INTEGER); -BEGIN - F := fclose(F) -END Close; - - -PROCEDURE Open* (FName, Mode: ARRAY OF CHAR): INTEGER; - RETURN fopen(SYSTEM.ADR(FName[0]), SYSTEM.ADR(Mode[0])) -END Open; - - -PROCEDURE Create* (FName: ARRAY OF CHAR): INTEGER; - RETURN Open(FName, OPEN_W) -END Create; - - -PROCEDURE Seek* (F, Offset, Origin: INTEGER): INTEGER; -VAR - res: INTEGER; - -BEGIN - IF fseek(F, Offset, Origin) = 0 THEN - res := ftell(F) - ELSE - res := -1 - END - - RETURN res -END Seek; - - -PROCEDURE Write* (F, Buffer, Count: INTEGER): INTEGER; - RETURN fwrite(Buffer, 1, Count, F) -END Write; - - -PROCEDURE Read* (F, Buffer, Count: INTEGER): INTEGER; - RETURN fread(Buffer, 1, Count, F) -END Read; - - -PROCEDURE Load* (FName: ARRAY OF CHAR; VAR Size: INTEGER): INTEGER; -VAR - res, n, F: INTEGER; - -BEGIN - res := 0; - F := Open(FName, OPEN_R); - - IF F > 0 THEN - Size := Seek(F, 0, SEEK_END); - n := Seek(F, 0, SEEK_BEG); - res := API._NEW(Size); - IF (res = 0) OR (Read(F, res, Size) # Size) THEN - IF res # 0 THEN - res := API._DISPOSE(res); - Size := 0 - END - END; - Close(F) - END - - RETURN res -END Load; - - -BEGIN - init -END File. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux64/HOST.ob07 b/programs/develop/oberon07/Lib/Linux64/HOST.ob07 deleted file mode 100644 index 66ab8b6989..0000000000 --- a/programs/develop/oberon07/Lib/Linux64/HOST.ob07 +++ /dev/null @@ -1,254 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2019-2020, Anton Krotov - All rights reserved. -*) - -MODULE HOST; - -IMPORT SYSTEM, API, RTL; - - -CONST - - slash* = "/"; - eol* = 0AX; - - bit_depth* = RTL.bit_depth; - maxint* = RTL.maxint; - minint* = RTL.minint; - - RTLD_LAZY = 1; - - -TYPE - - TP = ARRAY 2 OF INTEGER; - - -VAR - - maxreal*: REAL; - - argc: INTEGER; - - libc, librt: INTEGER; - - stdout: INTEGER; - - fread, fwrite : PROCEDURE [linux] (buffer, bytes, blocks, file: INTEGER): INTEGER; - fopen : PROCEDURE [linux] (fname, fmode: INTEGER): INTEGER; - fclose : PROCEDURE [linux] (file: INTEGER): INTEGER; - _chmod : PROCEDURE [linux] (fname: INTEGER; mode: SET): INTEGER; - time : PROCEDURE [linux] (ptr: INTEGER): INTEGER; - clock_gettime : PROCEDURE [linux] (clock_id: INTEGER; VAR tp: TP): INTEGER; - exit : PROCEDURE [linux] (code: INTEGER); - - -PROCEDURE ExitProcess* (code: INTEGER); -BEGIN - exit(code) -END ExitProcess; - - -PROCEDURE GetArg* (n: INTEGER; VAR s: ARRAY OF CHAR); -VAR - i, len, ptr: INTEGER; - c: CHAR; - -BEGIN - i := 0; - len := LEN(s) - 1; - IF (n < argc) & (len > 0) THEN - SYSTEM.GET(API.MainParam + (n + 1) * SYSTEM.SIZE(INTEGER), ptr); - REPEAT - SYSTEM.GET(ptr, c); - s[i] := c; - INC(i); - INC(ptr) - UNTIL (c = 0X) OR (i = len) - END; - s[i] := 0X -END GetArg; - - -PROCEDURE GetCurrentDirectory* (VAR path: ARRAY OF CHAR); -VAR - n: INTEGER; - -BEGIN - GetArg(0, path); - n := LENGTH(path) - 1; - WHILE path[n] # slash DO - DEC(n) - END; - path[n + 1] := 0X -END GetCurrentDirectory; - - -PROCEDURE FileRead* (F: INTEGER; VAR Buffer: ARRAY OF CHAR; bytes: INTEGER): INTEGER; -VAR - res: INTEGER; - -BEGIN - res := fread(SYSTEM.ADR(Buffer[0]), 1, bytes, F); - IF res <= 0 THEN - res := -1 - END - - RETURN res -END FileRead; - - -PROCEDURE FileWrite* (F: INTEGER; Buffer: ARRAY OF BYTE; bytes: INTEGER): INTEGER; -VAR - res: INTEGER; - -BEGIN - res := fwrite(SYSTEM.ADR(Buffer[0]), 1, bytes, F); - IF res <= 0 THEN - res := -1 - END - - RETURN res -END FileWrite; - - -PROCEDURE FileCreate* (FName: ARRAY OF CHAR): INTEGER; - RETURN fopen(SYSTEM.ADR(FName[0]), SYSTEM.SADR("wb")) -END FileCreate; - - -PROCEDURE FileClose* (File: INTEGER); -BEGIN - File := fclose(File) -END FileClose; - - -PROCEDURE chmod* (FName: ARRAY OF CHAR); -VAR - res: INTEGER; -BEGIN - res := _chmod(SYSTEM.ADR(FName[0]), {0, 2..8}) (* rwxrwxr-x *) -END chmod; - - -PROCEDURE FileOpen* (FName: ARRAY OF CHAR): INTEGER; - RETURN fopen(SYSTEM.ADR(FName[0]), SYSTEM.SADR("rb")) -END FileOpen; - - -PROCEDURE OutChar* (c: CHAR); -VAR - res: INTEGER; - -BEGIN - res := fwrite(SYSTEM.ADR(c), 1, 1, stdout) -END OutChar; - - -PROCEDURE GetTickCount* (): INTEGER; -VAR - tp: TP; - res: INTEGER; - -BEGIN - IF clock_gettime(0, tp) = 0 THEN - res := tp[0] * 100 + tp[1] DIV 10000000 - ELSE - res := 0 - END - - RETURN res -END GetTickCount; - - -PROCEDURE isRelative* (path: ARRAY OF CHAR): BOOLEAN; - RETURN path[0] # slash -END isRelative; - - -PROCEDURE UnixTime* (): INTEGER; - RETURN time(0) -END UnixTime; - - -PROCEDURE splitf* (x: REAL; VAR a, b: INTEGER): INTEGER; -VAR - res: INTEGER; - -BEGIN - a := 0; - b := 0; - SYSTEM.GET32(SYSTEM.ADR(x), a); - SYSTEM.GET32(SYSTEM.ADR(x) + 4, b); - SYSTEM.GET(SYSTEM.ADR(x), res) - RETURN res -END splitf; - - -PROCEDURE d2s* (x: REAL): INTEGER; -VAR - h, l, s, e: INTEGER; - -BEGIN - e := splitf(x, l, h); - - s := ASR(h, 31) MOD 2; - e := (h DIV 100000H) MOD 2048; - IF e <= 896 THEN - h := (h MOD 100000H) * 8 + (l DIV 20000000H) MOD 8 + 800000H; - REPEAT - h := h DIV 2; - INC(e) - UNTIL e = 897; - e := 896; - l := (h MOD 8) * 20000000H; - h := h DIV 8 - ELSIF (1151 <= e) & (e < 2047) THEN - e := 1151; - h := 0; - l := 0 - ELSIF e = 2047 THEN - e := 1151; - IF (h MOD 100000H # 0) OR (BITS(l) * {0..31} # {}) THEN - h := 80000H; - l := 0 - END - END; - DEC(e, 896) - - RETURN LSL(s, 31) + LSL(e, 23) + (h MOD 100000H) * 8 + (l DIV 20000000H) MOD 8 -END d2s; - - -PROCEDURE GetSym (lib: INTEGER; name: ARRAY OF CHAR; VarAdr: INTEGER); -VAR - sym: INTEGER; - -BEGIN - sym := API.dlsym(lib, SYSTEM.ADR(name[0])); - ASSERT(sym # 0); - SYSTEM.PUT(VarAdr, sym) -END GetSym; - - -BEGIN - maxreal := 1.9; - PACK(maxreal, 1023); - SYSTEM.GET(API.MainParam, argc); - - libc := API.libc; - GetSym(libc, "fread", SYSTEM.ADR(fread)); - GetSym(libc, "fwrite", SYSTEM.ADR(fwrite)); - GetSym(libc, "fopen", SYSTEM.ADR(fopen)); - GetSym(libc, "fclose", SYSTEM.ADR(fclose)); - GetSym(libc, "chmod", SYSTEM.ADR(_chmod)); - GetSym(libc, "time", SYSTEM.ADR(time)); - GetSym(libc, "exit", SYSTEM.ADR(exit)); - GetSym(libc, "stdout", SYSTEM.ADR(stdout)); SYSTEM.GET(stdout - SYSTEM.SIZE(INTEGER), stdout); - - librt := API.dlopen(SYSTEM.SADR("librt.so.1"), RTLD_LAZY); - GetSym(librt, "clock_gettime", SYSTEM.ADR(clock_gettime)) -END HOST. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux64/In.ob07 b/programs/develop/oberon07/Lib/Linux64/In.ob07 deleted file mode 100644 index 73fa891d05..0000000000 --- a/programs/develop/oberon07/Lib/Linux64/In.ob07 +++ /dev/null @@ -1,85 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2020, Anton Krotov - All rights reserved. -*) - -MODULE In; - -IMPORT SYSTEM, Libdl; - - -CONST - - MAX_LEN = 10240; - - -VAR - - Done*: BOOLEAN; - s: ARRAY MAX_LEN + 4 OF CHAR; - - sscanf: PROCEDURE [linux] (buf: INTEGER; fmt: INTEGER; adr: INTEGER): INTEGER; - gets: PROCEDURE [linux] (buf: INTEGER); - - -PROCEDURE String* (VAR str: ARRAY OF CHAR); -BEGIN - gets(SYSTEM.ADR(s[0])); - COPY(s, str); - str[LEN(str) - 1] := 0X; - Done := TRUE -END String; - - -PROCEDURE Int* (VAR x: INTEGER); -BEGIN - String(s); - Done := sscanf(SYSTEM.ADR(s[0]), SYSTEM.SADR("%lld"), SYSTEM.ADR(x)) = 1 -END Int; - - -PROCEDURE Real* (VAR x: REAL); -BEGIN - String(s); - Done := sscanf(SYSTEM.ADR(s[0]), SYSTEM.SADR("%lf"), SYSTEM.ADR(x)) = 1 -END Real; - - -PROCEDURE Char* (VAR x: CHAR); -BEGIN - String(s); - x := s[0] -END Char; - - -PROCEDURE Ln*; -BEGIN - String(s) -END Ln; - - -PROCEDURE Open*; -BEGIN - Done := TRUE -END Open; - - -PROCEDURE init; -VAR - libc: INTEGER; - -BEGIN - libc := Libdl.open("libc.so.6", Libdl.LAZY); - ASSERT(libc # 0); - SYSTEM.PUT(SYSTEM.ADR(sscanf), Libdl.sym(libc, "sscanf")); - ASSERT(sscanf # NIL); - SYSTEM.PUT(SYSTEM.ADR(gets), Libdl.sym(libc, "gets")); - ASSERT(gets # NIL); -END init; - - -BEGIN - init -END In. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux64/LINAPI.ob07 b/programs/develop/oberon07/Lib/Linux64/LINAPI.ob07 deleted file mode 100644 index 98e6019266..0000000000 --- a/programs/develop/oberon07/Lib/Linux64/LINAPI.ob07 +++ /dev/null @@ -1,101 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2019-2020, Anton Krotov - All rights reserved. -*) - -MODULE LINAPI; - -IMPORT SYSTEM, API, Libdl; - - -TYPE - - TP* = ARRAY 2 OF INTEGER; - SOFINI* = PROCEDURE; - - -VAR - - libc*, librt*: INTEGER; - - stdout*, - stdin*, - stderr* : INTEGER; - - malloc* : PROCEDURE [linux] (size: INTEGER): INTEGER; - free* : PROCEDURE [linux] (ptr: INTEGER); - exit* : PROCEDURE [linux] (code: INTEGER); - puts* : PROCEDURE [linux] (pStr: INTEGER); - fwrite*, - fread* : PROCEDURE [linux] (buffer, bytes, blocks, file: INTEGER): INTEGER; - fopen* : PROCEDURE [linux] (fname, fmode: INTEGER): INTEGER; - fclose* : PROCEDURE [linux] (file: INTEGER): INTEGER; - time* : PROCEDURE [linux] (ptr: INTEGER): INTEGER; - - clock_gettime* : PROCEDURE [linux] (clock_id: INTEGER; VAR tp: TP): INTEGER; - - -PROCEDURE SetFini* (ProcFini: SOFINI); -BEGIN - API.SetFini(ProcFini) -END SetFini; - - -PROCEDURE GetSym (lib: INTEGER; name: ARRAY OF CHAR; VarAdr: INTEGER); -VAR - sym: INTEGER; - -BEGIN - sym := Libdl.sym(lib, name); - ASSERT(sym # 0); - SYSTEM.PUT(VarAdr, sym) -END GetSym; - - -PROCEDURE init; -BEGIN - libc := API.libc; - - GetSym(libc, "exit", SYSTEM.ADR(exit)); - GetSym(libc, "puts", SYSTEM.ADR(puts)); - GetSym(libc, "malloc", SYSTEM.ADR(malloc)); - GetSym(libc, "free", SYSTEM.ADR(free)); - GetSym(libc, "fread", SYSTEM.ADR(fread)); - GetSym(libc, "fwrite", SYSTEM.ADR(fwrite)); - GetSym(libc, "fopen", SYSTEM.ADR(fopen)); - GetSym(libc, "fclose", SYSTEM.ADR(fclose)); - GetSym(libc, "time", SYSTEM.ADR(time)); - - GetSym(libc, "stdout", SYSTEM.ADR(stdout)); SYSTEM.GET(stdout - SYSTEM.SIZE(INTEGER), stdout); - GetSym(libc, "stdin", SYSTEM.ADR(stdin)); SYSTEM.GET(stdin - SYSTEM.SIZE(INTEGER), stdin); - GetSym(libc, "stderr", SYSTEM.ADR(stderr)); SYSTEM.GET(stderr - SYSTEM.SIZE(INTEGER), stderr); - - librt := Libdl.open("librt.so.1", Libdl.LAZY); - - GetSym(librt, "clock_gettime", SYSTEM.ADR(clock_gettime)) -END init; - - -PROCEDURE [stdcall64-] syscall* (rax, rdi, rsi, rdx, r10, r8, r9: INTEGER): INTEGER; -BEGIN - SYSTEM.CODE( - 048H, 08BH, 045H, 010H, (* mov rax, qword [rbp + 16] *) - 048H, 08BH, 07DH, 018H, (* mov rdi, qword [rbp + 24] *) - 048H, 08BH, 075H, 020H, (* mov rsi, qword [rbp + 32] *) - 048H, 08BH, 055H, 028H, (* mov rdx, qword [rbp + 40] *) - 04CH, 08BH, 055H, 030H, (* mov r10, qword [rbp + 48] *) - 04CH, 08BH, 045H, 038H, (* mov r8, qword [rbp + 56] *) - 04CH, 08BH, 04DH, 040H, (* mov r9, qword [rbp + 64] *) - 00FH, 005H, (* syscall *) - 0C9H, (* leave *) - 0C2H, 038H, 000H (* ret 56 *) - ) - RETURN 0 -END syscall; - - -BEGIN - init -END LINAPI. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux64/Libdl.ob07 b/programs/develop/oberon07/Lib/Linux64/Libdl.ob07 deleted file mode 100644 index f8a5781d87..0000000000 --- a/programs/develop/oberon07/Lib/Linux64/Libdl.ob07 +++ /dev/null @@ -1,65 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2019, Anton Krotov - All rights reserved. -*) - -MODULE Libdl; - -IMPORT SYSTEM, API; - - -CONST - - LAZY* = 1; - NOW* = 2; - BINDING_MASK* = 3; - NOLOAD* = 4; - LOCAL* = 0; - GLOBAL* = 256; - NODELETE* = 4096; - - -VAR - - _close: PROCEDURE [linux] (handle: INTEGER): INTEGER; - _error: PROCEDURE [linux] (): INTEGER; - - -PROCEDURE open* (file: ARRAY OF CHAR; mode: INTEGER): INTEGER; - RETURN API.dlopen(SYSTEM.ADR(file[0]), mode) -END open; - - -PROCEDURE sym* (handle: INTEGER; name: ARRAY OF CHAR): INTEGER; - RETURN API.dlsym(handle, SYSTEM.ADR(name[0])) -END sym; - - -PROCEDURE close* (handle: INTEGER): INTEGER; - RETURN _close(handle) -END close; - - -PROCEDURE error* (): INTEGER; - RETURN _error() -END error; - - -PROCEDURE init; -VAR - lib: INTEGER; - -BEGIN - lib := open("libdl.so.2", LAZY); - SYSTEM.PUT(SYSTEM.ADR(_close), sym(lib, "dlclose")); - ASSERT(_close # NIL); - SYSTEM.PUT(SYSTEM.ADR(_error), sym(lib, "dlerror")); - ASSERT(_error # NIL) -END init; - - -BEGIN - init -END Libdl. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux64/Math.ob07 b/programs/develop/oberon07/Lib/Linux64/Math.ob07 deleted file mode 100644 index 42a5de5e7e..0000000000 --- a/programs/develop/oberon07/Lib/Linux64/Math.ob07 +++ /dev/null @@ -1,480 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2019-2020, Anton Krotov - All rights reserved. -*) - -MODULE Math; - -IMPORT SYSTEM; - - -CONST - - pi* = 3.1415926535897932384626433832795028841972E0; - e* = 2.7182818284590452353602874713526624977572E0; - - ZERO = 0.0E0; - ONE = 1.0E0; - HALF = 0.5E0; - TWO = 2.0E0; - sqrtHalf = 0.70710678118654752440E0; - eps = 5.5511151E-17; - ln2Inv = 1.44269504088896340735992468100189213E0; - piInv = ONE / pi; - Limit = 1.0536712E-8; - piByTwo = pi / TWO; - - expoMax = 1023; - expoMin = 1 - expoMax; - - -VAR - - LnInfinity, LnSmall, large, miny: REAL; - - -PROCEDURE [stdcall64] sqrt* (x: REAL): REAL; -BEGIN - ASSERT(x >= ZERO); - SYSTEM.CODE( - 0F2H, 0FH, 51H, 45H, 10H, (* sqrtsd xmm0, qword[rbp + 10h] *) - 05DH, (* pop rbp *) - 0C2H, 08H, 00H (* ret 8 *) - ) - - RETURN 0.0 -END sqrt; - - -PROCEDURE sqri* (x: INTEGER): INTEGER; - RETURN x * x -END sqri; - - -PROCEDURE sqrr* (x: REAL): REAL; - RETURN x * x -END sqrr; - - -PROCEDURE exp* (x: REAL): REAL; -CONST - c1 = 0.693359375E0; - c2 = -2.1219444005469058277E-4; - P0 = 0.249999999999999993E+0; - P1 = 0.694360001511792852E-2; - P2 = 0.165203300268279130E-4; - Q1 = 0.555538666969001188E-1; - Q2 = 0.495862884905441294E-3; - -VAR - xn, g, p, q, z: REAL; - n: INTEGER; - -BEGIN - IF x > LnInfinity THEN - x := SYSTEM.INF() - ELSIF x < LnSmall THEN - x := ZERO - ELSIF ABS(x) < eps THEN - x := ONE - ELSE - IF x >= ZERO THEN - n := FLOOR(ln2Inv * x + HALF) - ELSE - n := FLOOR(ln2Inv * x - HALF) - END; - - xn := FLT(n); - g := (x - xn * c1) - xn * c2; - z := g * g; - p := ((P2 * z + P1) * z + P0) * g; - q := (Q2 * z + Q1) * z + HALF; - x := HALF + p / (q - p); - PACK(x, n + 1) - END - - RETURN x -END exp; - - -PROCEDURE ln* (x: REAL): REAL; -CONST - c1 = 355.0E0 / 512.0E0; - c2 = -2.121944400546905827679E-4; - P0 = -0.64124943423745581147E+2; - P1 = 0.16383943563021534222E+2; - P2 = -0.78956112887491257267E+0; - Q0 = -0.76949932108494879777E+3; - Q1 = 0.31203222091924532844E+3; - Q2 = -0.35667977739034646171E+2; - -VAR - zn, zd, r, z, w, p, q, xn: REAL; - n: INTEGER; - -BEGIN - ASSERT(x > ZERO); - - UNPK(x, n); - x := x * HALF; - - IF x > sqrtHalf THEN - zn := x - ONE; - zd := x * HALF + HALF; - INC(n) - ELSE - zn := x - HALF; - zd := zn * HALF + HALF - END; - - z := zn / zd; - w := z * z; - q := ((w + Q2) * w + Q1) * w + Q0; - p := w * ((P2 * w + P1) * w + P0); - r := z + z * (p / q); - xn := FLT(n) - - RETURN (xn * c2 + r) + xn * c1 -END ln; - - -PROCEDURE power* (base, exponent: REAL): REAL; -BEGIN - ASSERT(base > ZERO) - RETURN exp(exponent * ln(base)) -END power; - - -PROCEDURE ipower* (base: REAL; exponent: INTEGER): REAL; -VAR - i: INTEGER; - a: REAL; - -BEGIN - a := 1.0; - - IF base # 0.0 THEN - IF exponent # 0 THEN - IF exponent < 0 THEN - base := 1.0 / base - END; - i := ABS(exponent); - WHILE i > 0 DO - WHILE ~ODD(i) DO - i := LSR(i, 1); - base := sqrr(base) - END; - DEC(i); - a := a * base - END - ELSE - a := 1.0 - END - ELSE - ASSERT(exponent > 0); - a := 0.0 - END - - RETURN a -END ipower; - - -PROCEDURE log* (base, x: REAL): REAL; -BEGIN - ASSERT(base > ZERO); - ASSERT(x > ZERO) - RETURN ln(x) / ln(base) -END log; - - -PROCEDURE SinCos (x, y, sign: REAL): REAL; -CONST - ymax = 210828714; - c1 = 3.1416015625E0; - c2 = -8.908910206761537356617E-6; - r1 = -0.16666666666666665052E+0; - r2 = 0.83333333333331650314E-2; - r3 = -0.19841269841201840457E-3; - r4 = 0.27557319210152756119E-5; - r5 = -0.25052106798274584544E-7; - r6 = 0.16058936490371589114E-9; - r7 = -0.76429178068910467734E-12; - r8 = 0.27204790957888846175E-14; - -VAR - n: INTEGER; - xn, f, x1, g: REAL; - -BEGIN - ASSERT(y < FLT(ymax)); - - n := FLOOR(y * piInv + HALF); - xn := FLT(n); - IF ODD(n) THEN - sign := -sign - END; - x := ABS(x); - IF x # y THEN - xn := xn - HALF - END; - - x1 := FLT(FLOOR(x)); - f := ((x1 - xn * c1) + (x - x1)) - xn * c2; - - IF ABS(f) < Limit THEN - x := sign * f - ELSE - g := f * f; - g := (((((((r8 * g + r7) * g + r6) * g + r5) * g + r4) * g + r3) * g + r2) * g + r1) * g; - g := f + f * g; - x := sign * g - END - - RETURN x -END SinCos; - - -PROCEDURE sin* (x: REAL): REAL; -BEGIN - IF x < ZERO THEN - x := SinCos(x, -x, -ONE) - ELSE - x := SinCos(x, x, ONE) - END - - RETURN x -END sin; - - -PROCEDURE cos* (x: REAL): REAL; - RETURN SinCos(x, ABS(x) + piByTwo, ONE) -END cos; - - -PROCEDURE tan* (x: REAL): REAL; -VAR - s, c: REAL; - -BEGIN - s := sin(x); - c := sqrt(ONE - s * s); - x := ABS(x) / (TWO * pi); - x := x - FLT(FLOOR(x)); - IF (0.25 < x) & (x < 0.75) THEN - c := -c - END - - RETURN s / c -END tan; - - -PROCEDURE arctan2* (y, x: REAL): REAL; -CONST - P0 = 0.216062307897242551884E+3; P1 = 0.3226620700132512059245E+3; - P2 = 0.13270239816397674701E+3; P3 = 0.1288838303415727934E+2; - Q0 = 0.2160623078972426128957E+3; Q1 = 0.3946828393122829592162E+3; - Q2 = 0.221050883028417680623E+3; Q3 = 0.3850148650835119501E+2; - Sqrt3 = 1.7320508075688772935E0; - -VAR - atan, z, z2, p, q: REAL; - yExp, xExp, Quadrant: INTEGER; - -BEGIN - IF ABS(x) < miny THEN - ASSERT(ABS(y) >= miny); - atan := piByTwo - ELSE - z := y; - UNPK(z, yExp); - z := x; - UNPK(z, xExp); - - IF yExp - xExp >= expoMax - 3 THEN - atan := piByTwo - ELSIF yExp - xExp < expoMin + 3 THEN - atan := ZERO - ELSE - IF ABS(y) > ABS(x) THEN - z := ABS(x / y); - Quadrant := 2 - ELSE - z := ABS(y / x); - Quadrant := 0 - END; - - IF z > TWO - Sqrt3 THEN - z := (z * Sqrt3 - ONE) / (Sqrt3 + z); - INC(Quadrant) - END; - - IF ABS(z) < Limit THEN - atan := z - ELSE - z2 := z * z; - p := (((P3 * z2 + P2) * z2 + P1) * z2 + P0) * z; - q := (((z2 + Q3) * z2 + Q2) * z2 + Q1) * z2 + Q0; - atan := p / q - END; - - CASE Quadrant OF - |0: - |1: atan := atan + pi / 6.0 - |2: atan := piByTwo - atan - |3: atan := pi / 3.0 - atan - END - END; - - IF x < ZERO THEN - atan := pi - atan - END - END; - - IF y < ZERO THEN - atan := -atan - END - - RETURN atan -END arctan2; - - -PROCEDURE arcsin* (x: REAL): REAL; -BEGIN - ASSERT(ABS(x) <= ONE) - RETURN arctan2(x, sqrt(ONE - x * x)) -END arcsin; - - -PROCEDURE arccos* (x: REAL): REAL; -BEGIN - ASSERT(ABS(x) <= ONE) - RETURN arctan2(sqrt(ONE - x * x), x) -END arccos; - - -PROCEDURE arctan* (x: REAL): REAL; - RETURN arctan2(x, ONE) -END arctan; - - -PROCEDURE sinh* (x: REAL): REAL; -BEGIN - x := exp(x) - RETURN (x - ONE / x) * HALF -END sinh; - - -PROCEDURE cosh* (x: REAL): REAL; -BEGIN - x := exp(x) - RETURN (x + ONE / x) * HALF -END cosh; - - -PROCEDURE tanh* (x: REAL): REAL; -BEGIN - IF x > 15.0 THEN - x := ONE - ELSIF x < -15.0 THEN - x := -ONE - ELSE - x := exp(TWO * x); - x := (x - ONE) / (x + ONE) - END - - RETURN x -END tanh; - - -PROCEDURE arsinh* (x: REAL): REAL; - RETURN ln(x + sqrt(x * x + ONE)) -END arsinh; - - -PROCEDURE arcosh* (x: REAL): REAL; -BEGIN - ASSERT(x >= ONE) - RETURN ln(x + sqrt(x * x - ONE)) -END arcosh; - - -PROCEDURE artanh* (x: REAL): REAL; -BEGIN - ASSERT(ABS(x) < ONE) - RETURN HALF * ln((ONE + x) / (ONE - x)) -END artanh; - - -PROCEDURE sgn* (x: REAL): INTEGER; -VAR - res: INTEGER; - -BEGIN - IF x > ZERO THEN - res := 1 - ELSIF x < ZERO THEN - res := -1 - ELSE - res := 0 - END - - RETURN res -END sgn; - - -PROCEDURE fact* (n: INTEGER): REAL; -VAR - res: REAL; - -BEGIN - res := ONE; - WHILE n > 1 DO - res := res * FLT(n); - DEC(n) - END - - RETURN res -END fact; - - -PROCEDURE DegToRad* (x: REAL): REAL; - RETURN x * (pi / 180.0) -END DegToRad; - - -PROCEDURE RadToDeg* (x: REAL): REAL; - RETURN x * (180.0 / pi) -END RadToDeg; - - -(* Return hypotenuse of triangle *) -PROCEDURE hypot* (x, y: REAL): REAL; -VAR - a: REAL; - -BEGIN - x := ABS(x); - y := ABS(y); - IF x > y THEN - a := x * sqrt(1.0 + sqrr(y / x)) - ELSE - IF x > 0.0 THEN - a := y * sqrt(1.0 + sqrr(x / y)) - ELSE - a := y - END - END - - RETURN a -END hypot; - - -BEGIN - large := 1.9; - PACK(large, expoMax); - miny := ONE / large; - LnInfinity := ln(large); - LnSmall := ln(miny); -END Math. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux64/Out.ob07 b/programs/develop/oberon07/Lib/Linux64/Out.ob07 deleted file mode 100644 index 6876dd4cd9..0000000000 --- a/programs/develop/oberon07/Lib/Linux64/Out.ob07 +++ /dev/null @@ -1,87 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2020, Anton Krotov - All rights reserved. -*) - -MODULE Out; - -IMPORT SYSTEM, Libdl; - - -VAR - - printf1: PROCEDURE [linux] (fmt: INTEGER; x: INTEGER); - printf2: PROCEDURE [linux] (fmt: INTEGER; width, x: INTEGER); - printf3: PROCEDURE [linux] (fmt: INTEGER; width, precision, x: INTEGER); - - -PROCEDURE Char* (x: CHAR); -BEGIN - printf1(SYSTEM.SADR("%c"), ORD(x)) -END Char; - - -PROCEDURE String* (s: ARRAY OF CHAR); -BEGIN - printf2(SYSTEM.SADR("%.*s"), LENGTH(s), SYSTEM.ADR(s[0])) -END String; - - -PROCEDURE Ln*; -BEGIN - printf1(SYSTEM.SADR("%s"), SYSTEM.SADR(0AX)) -END Ln; - - -PROCEDURE Int* (x, width: INTEGER); -BEGIN - printf2(SYSTEM.SADR("%*lld"), width, x) -END Int; - - -PROCEDURE intval (x: REAL): INTEGER; -VAR - i: INTEGER; - -BEGIN - SYSTEM.GET(SYSTEM.ADR(x), i) - RETURN i -END intval; - - -PROCEDURE Real* (x: REAL; width: INTEGER); -BEGIN - printf3(SYSTEM.SADR("%*.*E"), width, MAX(MIN(width - 8, 15), 1), intval(x)) -END Real; - - -PROCEDURE FixReal* (x: REAL; width, precision: INTEGER); -BEGIN - printf3(SYSTEM.SADR("%*.*f"), width, precision, intval(x)) -END FixReal; - - -PROCEDURE Open*; -END Open; - - -PROCEDURE init; -VAR - libc, printf: INTEGER; - -BEGIN - libc := Libdl.open("libc.so.6", Libdl.LAZY); - ASSERT(libc # 0); - printf := Libdl.sym(libc, "printf"); - ASSERT(printf # 0); - SYSTEM.PUT(SYSTEM.ADR(printf1), printf); - SYSTEM.PUT(SYSTEM.ADR(printf2), printf); - SYSTEM.PUT(SYSTEM.ADR(printf3), printf); -END init; - - -BEGIN - init -END Out. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Linux64/RTL.ob07 b/programs/develop/oberon07/Lib/Linux64/RTL.ob07 deleted file mode 100644 index 7b6bbfb6a7..0000000000 --- a/programs/develop/oberon07/Lib/Linux64/RTL.ob07 +++ /dev/null @@ -1,503 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018-2020, Anton Krotov - All rights reserved. -*) - -MODULE RTL; - -IMPORT SYSTEM, API; - - -CONST - - bit_depth* = 64; - maxint* = 7FFFFFFFFFFFFFFFH; - minint* = 8000000000000000H; - - WORD = bit_depth DIV 8; - MAX_SET = bit_depth - 1; - - -VAR - - name: INTEGER; - types: INTEGER; - sets: ARRAY (MAX_SET + 1) * (MAX_SET + 1) OF INTEGER; - - -PROCEDURE [stdcall64] _move* (bytes, dest, source: INTEGER); -BEGIN - SYSTEM.CODE( - 048H, 08BH, 045H, 010H, (* mov rax, qword [rbp + 16] *) - 048H, 085H, 0C0H, (* test rax, rax *) - 07EH, 020H, (* jle L *) - 0FCH, (* cld *) - 057H, (* push rdi *) - 056H, (* push rsi *) - 048H, 08BH, 075H, 020H, (* mov rsi, qword [rbp + 32] *) - 048H, 08BH, 07DH, 018H, (* mov rdi, qword [rbp + 24] *) - 048H, 089H, 0C1H, (* mov rcx, rax *) - 048H, 0C1H, 0E9H, 003H, (* shr rcx, 3 *) - 0F3H, 048H, 0A5H, (* rep movsd *) - 048H, 089H, 0C1H, (* mov rcx, rax *) - 048H, 083H, 0E1H, 007H, (* and rcx, 7 *) - 0F3H, 0A4H, (* rep movsb *) - 05EH, (* pop rsi *) - 05FH (* pop rdi *) - (* L: *) - ) -END _move; - - -PROCEDURE [stdcall64] _arrcpy* (base_size, len_dst, dst, len_src, src: INTEGER): BOOLEAN; -VAR - res: BOOLEAN; - -BEGIN - IF len_src > len_dst THEN - res := FALSE - ELSE - _move(len_src * base_size, dst, src); - res := TRUE - END - - RETURN res -END _arrcpy; - - -PROCEDURE [stdcall64] _strcpy* (chr_size, len_src, src, len_dst, dst: INTEGER); -BEGIN - _move(MIN(len_dst, len_src) * chr_size, dst, src) -END _strcpy; - - -PROCEDURE [stdcall64] _rot* (VAR A: ARRAY OF INTEGER); -VAR - i, n, k: INTEGER; - -BEGIN - k := LEN(A) - 1; - n := A[0]; - i := 0; - WHILE i < k DO - A[i] := A[i + 1]; - INC(i) - END; - A[k] := n -END _rot; - - -PROCEDURE [stdcall64] _set* (b, a: INTEGER): INTEGER; -BEGIN - IF (a <= b) & (a <= MAX_SET) & (b >= 0) THEN - SYSTEM.GET((MIN(b, MAX_SET) * (MAX_SET + 1) + MAX(a, 0)) * WORD + SYSTEM.ADR(sets[0]), a) - ELSE - a := 0 - END - - RETURN a -END _set; - - -PROCEDURE [stdcall64] _set1* (a: INTEGER); (* {a} -> rax *) -BEGIN - SYSTEM.CODE( - 048H, 031H, 0C0H, (* xor rax, rax *) - 048H, 08BH, 04DH, 010H, (* mov rcx, qword [rbp + 16] *) (* rcx <- a *) - 048H, 083H, 0F9H, 03FH, (* cmp rcx, 63 *) - 077H, 004H, (* ja L *) - 048H, 00FH, 0ABH, 0C8H (* bts rax, rcx *) - (* L: *) - ) -END _set1; - - -PROCEDURE [stdcall64] _divmod* (y, x: INTEGER); (* (x div y) -> rax; (x mod y) -> rdx *) -BEGIN - SYSTEM.CODE( - 048H, 08BH, 045H, 018H, (* mov rax, qword [rbp + 24] *) (* rax <- x *) - 048H, 031H, 0D2H, (* xor rdx, rdx *) - 048H, 085H, 0C0H, (* test rax, rax *) - 074H, 022H, (* je L2 *) - 07FH, 003H, (* jg L1 *) - 048H, 0F7H, 0D2H, (* not rdx *) - (* L1: *) - 049H, 089H, 0C0H, (* mov r8, rax *) - 048H, 08BH, 04DH, 010H, (* mov rcx, qword [rbp + 16] *) (* rcx <- y *) - 048H, 0F7H, 0F9H, (* idiv rcx *) - 048H, 085H, 0D2H, (* test rdx, rdx *) - 074H, 00EH, (* je L2 *) - 049H, 031H, 0C8H, (* xor r8, rcx *) - 04DH, 085H, 0C0H, (* test r8, r8 *) - 07DH, 006H, (* jge L2 *) - 048H, 0FFH, 0C8H, (* dec rax *) - 048H, 001H, 0CAH (* add rdx, rcx *) - (* L2: *) - ) -END _divmod; - - -PROCEDURE [stdcall64] _new* (t, size: INTEGER; VAR ptr: INTEGER); -BEGIN - ptr := API._NEW(size); - IF ptr # 0 THEN - SYSTEM.PUT(ptr, t); - INC(ptr, WORD) - END -END _new; - - -PROCEDURE [stdcall64] _dispose* (VAR ptr: INTEGER); -BEGIN - IF ptr # 0 THEN - ptr := API._DISPOSE(ptr - WORD) - END -END _dispose; - - -PROCEDURE [stdcall64] _length* (len, str: INTEGER); -BEGIN - SYSTEM.CODE( - 048H, 08BH, 045H, 018H, (* mov rax, qword [rbp + 24] *) - 048H, 08BH, 04DH, 010H, (* mov rcx, qword [rbp + 16] *) - 048H, 0FFH, 0C8H, (* dec rax *) - (* L1: *) - 048H, 0FFH, 0C0H, (* inc rax *) - 080H, 038H, 000H, (* cmp byte [rax], 0 *) - 074H, 005H, (* jz L2 *) - 0E2H, 0F6H, (* loop L1 *) - 048H, 0FFH, 0C0H, (* inc rax *) - (* L2: *) - 048H, 02BH, 045H, 018H (* sub rax, qword [rbp + 24] *) - ) -END _length; - - -PROCEDURE [stdcall64] _lengthw* (len, str: INTEGER); -BEGIN - SYSTEM.CODE( - 048H, 08BH, 045H, 018H, (* mov rax, qword [rbp + 24] *) - 048H, 08BH, 04DH, 010H, (* mov rcx, qword [rbp + 16] *) - 048H, 083H, 0E8H, 002H, (* sub rax, 2 *) - (* L1: *) - 048H, 083H, 0C0H, 002H, (* add rax, 2 *) - 066H, 083H, 038H, 000H, (* cmp word [rax], 0 *) - 074H, 006H, (* jz L2 *) - 0E2H, 0F4H, (* loop L1 *) - 048H, 083H, 0C0H, 002H, (* add rax, 2 *) - (* L2: *) - 048H, 02BH, 045H, 018H, (* sub rax, qword [rbp + 24] *) - 048H, 0D1H, 0E8H (* shr rax, 1 *) - ) -END _lengthw; - - -PROCEDURE [stdcall64] strncmp (a, b, n: INTEGER): INTEGER; -BEGIN - SYSTEM.CODE( - 048H, 08BH, 04DH, 010H, (* mov rcx, qword[rbp + 16]; rcx <- a *) - 048H, 08BH, 055H, 018H, (* mov rdx, qword[rbp + 24]; rdx <- b *) - 04CH, 08BH, 045H, 020H, (* mov r8, qword[rbp + 32]; r8 <- n *) - 04DH, 031H, 0C9H, (* xor r9, r9 *) - 04DH, 031H, 0D2H, (* xor r10, r10 *) - 048H, 0B8H, 000H, 000H, - 000H, 000H, 000H, 000H, - 000H, 080H, (* movabs rax, minint *) - (* L1: *) - 04DH, 085H, 0C0H, (* test r8, r8 *) - 07EH, 024H, (* jle L3 *) - 044H, 08AH, 009H, (* mov r9b, byte[rcx] *) - 044H, 08AH, 012H, (* mov r10b, byte[rdx] *) - 048H, 0FFH, 0C1H, (* inc rcx *) - 048H, 0FFH, 0C2H, (* inc rdx *) - 049H, 0FFH, 0C8H, (* dec r8 *) - 04DH, 039H, 0D1H, (* cmp r9, r10 *) - 074H, 008H, (* je L2 *) - 04CH, 089H, 0C8H, (* mov rax, r9 *) - 04CH, 029H, 0D0H, (* sub rax, r10 *) - 0EBH, 008H, (* jmp L3 *) - (* L2: *) - 04DH, 085H, 0C9H, (* test r9, r9 *) - 075H, 0DAH, (* jne L1 *) - 048H, 031H, 0C0H, (* xor rax, rax *) - (* L3: *) - 05DH, (* pop rbp *) - 0C2H, 018H, 000H (* ret 24 *) - ) - RETURN 0 -END strncmp; - - -PROCEDURE [stdcall64] strncmpw (a, b, n: INTEGER): INTEGER; -BEGIN - SYSTEM.CODE( - 048H, 08BH, 04DH, 010H, (* mov rcx, qword[rbp + 16]; rcx <- a *) - 048H, 08BH, 055H, 018H, (* mov rdx, qword[rbp + 24]; rdx <- b *) - 04CH, 08BH, 045H, 020H, (* mov r8, qword[rbp + 32]; r8 <- n *) - 04DH, 031H, 0C9H, (* xor r9, r9 *) - 04DH, 031H, 0D2H, (* xor r10, r10 *) - 048H, 0B8H, 000H, 000H, - 000H, 000H, 000H, 000H, - 000H, 080H, (* movabs rax, minint *) - (* L1: *) - 04DH, 085H, 0C0H, (* test r8, r8 *) - 07EH, 028H, (* jle L3 *) - 066H, 044H, 08BH, 009H, (* mov r9w, word[rcx] *) - 066H, 044H, 08BH, 012H, (* mov r10w, word[rdx] *) - 048H, 083H, 0C1H, 002H, (* add rcx, 2 *) - 048H, 083H, 0C2H, 002H, (* add rdx, 2 *) - 049H, 0FFH, 0C8H, (* dec r8 *) - 04DH, 039H, 0D1H, (* cmp r9, r10 *) - 074H, 008H, (* je L2 *) - 04CH, 089H, 0C8H, (* mov rax, r9 *) - 04CH, 029H, 0D0H, (* sub rax, r10 *) - 0EBH, 008H, (* jmp L3 *) - (* L2: *) - 04DH, 085H, 0C9H, (* test r9, r9 *) - 075H, 0D6H, (* jne L1 *) - 048H, 031H, 0C0H, (* xor rax, rax *) - (* L3: *) - 05DH, (* pop rbp *) - 0C2H, 018H, 000H (* ret 24 *) - ) - RETURN 0 -END strncmpw; - - -PROCEDURE [stdcall64] _strcmp* (op, len2, str2, len1, str1: INTEGER): BOOLEAN; -VAR - res: INTEGER; - bRes: BOOLEAN; - c: CHAR; - -BEGIN - res := strncmp(str1, str2, MIN(len1, len2)); - IF res = minint THEN - IF len1 > len2 THEN - SYSTEM.GET(str1 + len2, c); - res := ORD(c) - ELSIF len1 < len2 THEN - SYSTEM.GET(str2 + len1, c); - res := -ORD(c) - ELSE - res := 0 - END - END; - - CASE op OF - |0: bRes := res = 0 - |1: bRes := res # 0 - |2: bRes := res < 0 - |3: bRes := res <= 0 - |4: bRes := res > 0 - |5: bRes := res >= 0 - END - - RETURN bRes -END _strcmp; - - -PROCEDURE [stdcall64] _strcmpw* (op, len2, str2, len1, str1: INTEGER): BOOLEAN; -VAR - res: INTEGER; - bRes: BOOLEAN; - c: WCHAR; - -BEGIN - res := strncmpw(str1, str2, MIN(len1, len2)); - IF res = minint THEN - IF len1 > len2 THEN - SYSTEM.GET(str1 + len2 * 2, c); - res := ORD(c) - ELSIF len1 < len2 THEN - SYSTEM.GET(str2 + len1 * 2, c); - res := -ORD(c) - ELSE - res := 0 - END - END; - - CASE op OF - |0: bRes := res = 0 - |1: bRes := res # 0 - |2: bRes := res < 0 - |3: bRes := res <= 0 - |4: bRes := res > 0 - |5: bRes := res >= 0 - END - - RETURN bRes -END _strcmpw; - - -PROCEDURE PCharToStr (pchar: INTEGER; VAR s: ARRAY OF CHAR); -VAR - c: CHAR; - i: INTEGER; - -BEGIN - i := 0; - REPEAT - SYSTEM.GET(pchar, c); - s[i] := c; - INC(pchar); - INC(i) - UNTIL c = 0X -END PCharToStr; - - -PROCEDURE IntToStr (x: INTEGER; VAR str: ARRAY OF CHAR); -VAR - i, a: INTEGER; - -BEGIN - i := 0; - a := x; - REPEAT - INC(i); - a := a DIV 10 - UNTIL a = 0; - - str[i] := 0X; - - REPEAT - DEC(i); - str[i] := CHR(x MOD 10 + ORD("0")); - x := x DIV 10 - UNTIL x = 0 -END IntToStr; - - -PROCEDURE append (VAR s1: ARRAY OF CHAR; s2: ARRAY OF CHAR); -VAR - n1, n2: INTEGER; - -BEGIN - n1 := LENGTH(s1); - n2 := LENGTH(s2); - - ASSERT(n1 + n2 < LEN(s1)); - - SYSTEM.MOVE(SYSTEM.ADR(s2[0]), SYSTEM.ADR(s1[n1]), n2); - s1[n1 + n2] := 0X -END append; - - -PROCEDURE [stdcall64] _error* (modnum, _module, err, line: INTEGER); -VAR - s, temp: ARRAY 1024 OF CHAR; - -BEGIN - CASE err OF - | 1: s := "assertion failure" - | 2: s := "NIL dereference" - | 3: s := "bad divisor" - | 4: s := "NIL procedure call" - | 5: s := "type guard error" - | 6: s := "index out of range" - | 7: s := "invalid CASE" - | 8: s := "array assignment error" - | 9: s := "CHR out of range" - |10: s := "WCHR out of range" - |11: s := "BYTE out of range" - END; - - append(s, API.eol + "module: "); PCharToStr(_module, temp); append(s, temp); - append(s, API.eol + "line: "); IntToStr(line, temp); append(s, temp); - - API.DebugMsg(SYSTEM.ADR(s[0]), name); - - API.exit_thread(0) -END _error; - - -PROCEDURE [stdcall64] _isrec* (t0, t1, r: INTEGER): INTEGER; -BEGIN - SYSTEM.GET(t0 + t1 + types, t0) - RETURN t0 MOD 2 -END _isrec; - - -PROCEDURE [stdcall64] _is* (t0, p: INTEGER): INTEGER; -BEGIN - IF p # 0 THEN - SYSTEM.GET(p - WORD, p); - SYSTEM.GET(t0 + p + types, p) - END - - RETURN p MOD 2 -END _is; - - -PROCEDURE [stdcall64] _guardrec* (t0, t1: INTEGER): INTEGER; -BEGIN - SYSTEM.GET(t0 + t1 + types, t0) - RETURN t0 MOD 2 -END _guardrec; - - -PROCEDURE [stdcall64] _guard* (t0, p: INTEGER): INTEGER; -BEGIN - SYSTEM.GET(p, p); - IF p # 0 THEN - SYSTEM.GET(p - WORD, p); - SYSTEM.GET(t0 + p + types, p) - ELSE - p := 1 - END - - RETURN p MOD 2 -END _guard; - - -PROCEDURE [stdcall64] _dllentry* (hinstDLL, fdwReason, lpvReserved: INTEGER): INTEGER; - RETURN API.dllentry(hinstDLL, fdwReason, lpvReserved) -END _dllentry; - - -PROCEDURE [stdcall64] _sofinit*; -BEGIN - API.sofinit -END _sofinit; - - -PROCEDURE [stdcall64] _exit* (code: INTEGER); -BEGIN - API.exit(code) -END _exit; - - -PROCEDURE [stdcall64] _init* (modname: INTEGER; tcount, _types: INTEGER; code, param: INTEGER); -VAR - t0, t1, i, j: INTEGER; - -BEGIN - API.init(param, code); - - types := API._NEW(tcount * tcount + SYSTEM.SIZE(INTEGER)); - ASSERT(types # 0); - FOR i := 0 TO tcount - 1 DO - FOR j := 0 TO tcount - 1 DO - t0 := i; t1 := j; - - WHILE (t1 # 0) & (t1 # t0) DO - SYSTEM.GET(_types + t1 * WORD, t1) - END; - - SYSTEM.PUT8(i * tcount + j + types, ORD(t0 = t1)) - END - END; - - FOR i := 0 TO MAX_SET DO - FOR j := 0 TO i DO - sets[i * (MAX_SET + 1) + j] := LSR(ASR(minint, i - j), MAX_SET - i) - END - END; - - name := modname -END _init; - - -END RTL. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/MSP430/MSP430.ob07 b/programs/develop/oberon07/Lib/MSP430/MSP430.ob07 deleted file mode 100644 index 8cf8169b6f..0000000000 --- a/programs/develop/oberon07/Lib/MSP430/MSP430.ob07 +++ /dev/null @@ -1,125 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2019-2020, Anton Krotov - All rights reserved. -*) - -MODULE MSP430; - -IMPORT SYSTEM; - - -CONST - - iv = 0FFC0H; - - bsl = iv - 2; - sp = bsl - 2; - empty_proc = sp - 2; - free_size = empty_proc - 2; - free_adr = free_size - 2; - bits = free_adr - 272; - bits_offs = bits - 32; - types = bits_offs - 2; - - ram = 200H; - - trap = ram; - int = trap + 2; - - - GIE* = {3}; - CPUOFF* = {4}; - OSCOFF* = {5}; - SCG0* = {6}; - SCG1* = {7}; - - -TYPE - - TInterrupt* = RECORD priority*: INTEGER; sr*: SET; pc*: INTEGER END; - - TTrapProc* = PROCEDURE (modNum, modName, err, line: INTEGER); - - TIntProc* = PROCEDURE (priority: INTEGER; interrupt: TInterrupt); - - -PROCEDURE SetTrapProc* (TrapProc: TTrapProc); -BEGIN - SYSTEM.PUT(trap, TrapProc) -END SetTrapProc; - - -PROCEDURE SetIntProc* (IntProc: TIntProc); -BEGIN - SYSTEM.PUT(int, IntProc) -END SetIntProc; - - -PROCEDURE SetIntPC* (interrupt: TInterrupt; NewPC: INTEGER); -BEGIN - SYSTEM.PUT(SYSTEM.ADR(interrupt.pc), NewPC) -END SetIntPC; - - -PROCEDURE SetIntSR* (interrupt: TInterrupt; NewSR: SET); -BEGIN - SYSTEM.PUT(SYSTEM.ADR(interrupt.sr), NewSR) -END SetIntSR; - - -PROCEDURE [code] DInt* - 0C232H; (* BIC #8, SR *) - - -PROCEDURE [code] EInt* - 0D232H; (* BIS #8, SR *) - - -PROCEDURE [code] CpuOff* - 0D032H, 16; (* BIS #16, SR *) - - -PROCEDURE [code] Halt* - 4032H, 0F0H; (* MOV CPUOFF+OSCOFF+SCG0+SCG1, SR *) - - -PROCEDURE [code] Restart* - 4302H, (* MOV #0, SR *) - 4210H, 0FFFEH; (* MOV 0FFFEH(SR), PC *) - - -PROCEDURE [code] SetSR* (bits: SET) - 0D112H, 2; (* BIS 2(SP), SR *) - - -PROCEDURE [code] ClrSR* (bits: SET) - 0C112H, 2; (* BIC 2(SP), SR *) - - -PROCEDURE GetFreeFlash* (VAR address, size: INTEGER); -BEGIN - SYSTEM.GET(free_adr, address); - SYSTEM.GET(free_size, size) -END GetFreeFlash; - - -PROCEDURE [code] Delay* (n: INTEGER) - 4035H, 124, (* MOV #124, R5 *) - (* L2: *) - 4114H, 2, (* MOV 2(SP), R4 *) - 8324H, (* SUB #2, R4 *) - (* L1: *) - 4303H, (* NOP *) - 4303H, (* NOP *) - 4303H, (* NOP *) - 4303H, (* NOP *) - 4303H, (* NOP *) - 8314H, (* SUB #1, R4 *) - 3800H - 7, (* JGE L1 *) - 8315H, (* SUB #1, R5 *) - 3800H - 12; (* JGE L2 *) - - -END MSP430. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows32/API.ob07 b/programs/develop/oberon07/Lib/Windows32/API.ob07 deleted file mode 100644 index 437d08b893..0000000000 --- a/programs/develop/oberon07/Lib/Windows32/API.ob07 +++ /dev/null @@ -1,132 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018-2020, Anton Krotov - All rights reserved. -*) - -MODULE API; - -IMPORT SYSTEM; - - -CONST - - eol* = 0DX + 0AX; - - SectionAlignment = 1000H; - - DLL_PROCESS_ATTACH = 1; - DLL_THREAD_ATTACH = 2; - DLL_THREAD_DETACH = 3; - DLL_PROCESS_DETACH = 0; - - KERNEL = "kernel32.dll"; - USER = "user32.dll"; - - -TYPE - - DLL_ENTRY* = PROCEDURE (hinstDLL, fdwReason, lpvReserved: INTEGER); - - -VAR - - base*: INTEGER; - heap: INTEGER; - - process_detach, - thread_detach, - thread_attach: DLL_ENTRY; - - -PROCEDURE [windows-, KERNEL, ""] ExitProcess (code: INTEGER); -PROCEDURE [windows-, KERNEL, ""] ExitThread (code: INTEGER); -PROCEDURE [windows-, KERNEL, ""] GetProcessHeap (): INTEGER; -PROCEDURE [windows-, KERNEL, ""] HeapAlloc (hHeap, dwFlags, dwBytes: INTEGER): INTEGER; -PROCEDURE [windows-, KERNEL, ""] HeapFree (hHeap, dwFlags, lpMem: INTEGER); -PROCEDURE [windows-, USER, ""] MessageBoxA (hWnd, lpText, lpCaption, uType: INTEGER): INTEGER; - - -PROCEDURE DebugMsg* (lpText, lpCaption: INTEGER); -BEGIN - MessageBoxA(0, lpText, lpCaption, 16) -END DebugMsg; - - -PROCEDURE _NEW* (size: INTEGER): INTEGER; - RETURN HeapAlloc(heap, 8, size) -END _NEW; - - -PROCEDURE _DISPOSE* (p: INTEGER): INTEGER; -BEGIN - HeapFree(heap, 0, p) - RETURN 0 -END _DISPOSE; - - -PROCEDURE init* (reserved, code: INTEGER); -BEGIN - process_detach := NIL; - thread_detach := NIL; - thread_attach := NIL; - base := code - SectionAlignment; - heap := GetProcessHeap() -END init; - - -PROCEDURE exit* (code: INTEGER); -BEGIN - ExitProcess(code) -END exit; - - -PROCEDURE exit_thread* (code: INTEGER); -BEGIN - ExitThread(code) -END exit_thread; - - -PROCEDURE dllentry* (hinstDLL, fdwReason, lpvReserved: INTEGER): INTEGER; -VAR - res: INTEGER; - -BEGIN - res := 0; - - CASE fdwReason OF - |DLL_PROCESS_ATTACH: - res := 1 - |DLL_THREAD_ATTACH: - IF thread_attach # NIL THEN - thread_attach(hinstDLL, fdwReason, lpvReserved) - END - |DLL_THREAD_DETACH: - IF thread_detach # NIL THEN - thread_detach(hinstDLL, fdwReason, lpvReserved) - END - |DLL_PROCESS_DETACH: - IF process_detach # NIL THEN - process_detach(hinstDLL, fdwReason, lpvReserved) - END - ELSE - END - - RETURN res -END dllentry; - - -PROCEDURE sofinit*; -END sofinit; - - -PROCEDURE SetDll* (_process_detach, _thread_detach, _thread_attach: DLL_ENTRY); -BEGIN - process_detach := _process_detach; - thread_detach := _thread_detach; - thread_attach := _thread_attach -END SetDll; - - -END API. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows32/Args.ob07 b/programs/develop/oberon07/Lib/Windows32/Args.ob07 deleted file mode 100644 index fd56e3b975..0000000000 --- a/programs/develop/oberon07/Lib/Windows32/Args.ob07 +++ /dev/null @@ -1,101 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2019-2020, Anton Krotov - All rights reserved. -*) - -MODULE Args; - -IMPORT SYSTEM, WINAPI; - - -CONST - - MAX_PARAM = 1024; - - -VAR - - Params: ARRAY MAX_PARAM, 2 OF INTEGER; - argc*: INTEGER; - - -PROCEDURE GetChar (adr: INTEGER): CHAR; -VAR - res: CHAR; - -BEGIN - SYSTEM.GET(adr, res) - RETURN res -END GetChar; - - -PROCEDURE ParamParse; -VAR - p, count, cond: INTEGER; - c: CHAR; - - - PROCEDURE ChangeCond (A, B, C: INTEGER; VAR cond: INTEGER; c: CHAR): INTEGER; - BEGIN - IF (c <= 20X) & (c # 0X) THEN - cond := A - ELSIF c = 22X THEN - cond := B - ELSIF c = 0X THEN - cond := 6 - ELSE - cond := C - END - - RETURN cond - END ChangeCond; - - -BEGIN - p := WINAPI.GetCommandLineA(); - cond := 0; - count := 0; - WHILE (count < MAX_PARAM) & (cond # 6) DO - c := GetChar(p); - CASE cond OF - |0: IF ChangeCond(0, 4, 1, cond, c) = 1 THEN Params[count, 0] := p END - |1: IF ChangeCond(0, 3, 1, cond, c) IN {0, 6} THEN Params[count, 1] := p - 1; INC(count) END - |3: IF ChangeCond(3, 1, 3, cond, c) = 6 THEN Params[count, 1] := p - 1; INC(count) END - |4: IF ChangeCond(5, 0, 5, cond, c) = 5 THEN Params[count, 0] := p END - |5: IF ChangeCond(5, 1, 5, cond, c) = 6 THEN Params[count, 1] := p - 1; INC(count) END - |6: - END; - INC(p) - END; - argc := count -END ParamParse; - - -PROCEDURE GetArg* (n: INTEGER; VAR s: ARRAY OF CHAR); -VAR - i, j, len: INTEGER; - c: CHAR; - -BEGIN - j := 0; - IF n < argc THEN - i := Params[n, 0]; - len := LEN(s) - 1; - WHILE (j < len) & (i <= Params[n, 1]) DO - c := GetChar(i); - IF c # '"' THEN - s[j] := c; - INC(j) - END; - INC(i) - END - END; - s[j] := 0X -END GetArg; - - -BEGIN - ParamParse -END Args. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows32/Console.ob07 b/programs/develop/oberon07/Lib/Windows32/Console.ob07 deleted file mode 100644 index 83bf0f3825..0000000000 --- a/programs/develop/oberon07/Lib/Windows32/Console.ob07 +++ /dev/null @@ -1,100 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2019-2020, Anton Krotov - All rights reserved. -*) - -MODULE Console; - -IMPORT SYSTEM, WINAPI, In, Out; - - -CONST - - Black* = 0; Blue* = 1; Green* = 2; Cyan* = 3; - Red* = 4; Magenta* = 5; Brown* = 6; LightGray* = 7; - DarkGray* = 8; LightBlue* = 9; LightGreen* = 10; LightCyan* = 11; - LightRed* = 12; LightMagenta* = 13; Yellow* = 14; White* = 15; - - -VAR - - hConsoleOutput: INTEGER; - - -PROCEDURE SetCursor* (X, Y: INTEGER); -BEGIN - WINAPI.SetConsoleCursorPosition(hConsoleOutput, X + Y * 65536) -END SetCursor; - - -PROCEDURE GetCursor* (VAR X, Y: INTEGER); -VAR - ScrBufInfo: WINAPI.TConsoleScreenBufferInfo; - -BEGIN - WINAPI.GetConsoleScreenBufferInfo(hConsoleOutput, ScrBufInfo); - X := ORD(ScrBufInfo.dwCursorPosition.X); - Y := ORD(ScrBufInfo.dwCursorPosition.Y) -END GetCursor; - - -PROCEDURE Cls*; -VAR - fill: INTEGER; - ScrBufInfo: WINAPI.TConsoleScreenBufferInfo; - -BEGIN - WINAPI.GetConsoleScreenBufferInfo(hConsoleOutput, ScrBufInfo); - fill := ORD(ScrBufInfo.dwSize.X) * ORD(ScrBufInfo.dwSize.Y); - WINAPI.FillConsoleOutputCharacterA(hConsoleOutput, 20H, fill, 0, SYSTEM.ADR(fill)); - WINAPI.FillConsoleOutputAttribute(hConsoleOutput, ORD(ScrBufInfo.wAttributes), fill, 0, SYSTEM.ADR(fill)); - SetCursor(0, 0) -END Cls; - - -PROCEDURE SetColor* (FColor, BColor: INTEGER); -BEGIN - IF (FColor IN {0..15}) & (BColor IN {0..15}) THEN - WINAPI.SetConsoleTextAttribute(hConsoleOutput, LSL(BColor, 4) + FColor) - END -END SetColor; - - -PROCEDURE GetCursorX* (): INTEGER; -VAR - ScrBufInfo: WINAPI.TConsoleScreenBufferInfo; - -BEGIN - WINAPI.GetConsoleScreenBufferInfo(hConsoleOutput, ScrBufInfo) - RETURN ORD(ScrBufInfo.dwCursorPosition.X) -END GetCursorX; - - -PROCEDURE GetCursorY* (): INTEGER; -VAR - ScrBufInfo: WINAPI.TConsoleScreenBufferInfo; - -BEGIN - WINAPI.GetConsoleScreenBufferInfo(hConsoleOutput, ScrBufInfo) - RETURN ORD(ScrBufInfo.dwCursorPosition.Y) -END GetCursorY; - - -PROCEDURE open*; -BEGIN - WINAPI.AllocConsole; - hConsoleOutput := WINAPI.GetStdHandle(-11); - In.Open; - Out.Open -END open; - - -PROCEDURE exit* (b: BOOLEAN); -BEGIN - WINAPI.FreeConsole -END exit; - - -END Console. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows32/DateTime.ob07 b/programs/develop/oberon07/Lib/Windows32/DateTime.ob07 deleted file mode 100644 index 39bc641469..0000000000 --- a/programs/develop/oberon07/Lib/Windows32/DateTime.ob07 +++ /dev/null @@ -1,197 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2019-2020, Anton Krotov - All rights reserved. -*) - -MODULE DateTime; - -IMPORT WINAPI, SYSTEM; - - -CONST - - ERR* = -7.0E5; - - -VAR - - DateTable: ARRAY 120000, 3 OF INTEGER; - MonthsTable: ARRAY 13, 4 OF INTEGER; - - -PROCEDURE Encode* (Year, Month, Day, Hour, Min, Sec, MSec: INTEGER): REAL; -VAR - d, bis: INTEGER; - res: REAL; - -BEGIN - res := ERR; - IF (Year >= 1) & (Year <= 9999) & (Month >= 1) & (Month <= 12) & - (Day >= 1) & (Day <= 31) & (Hour >= 0) & (Hour <= 23) & - (Min >= 0) & (Min <= 59) & (Sec >= 0) & (Sec <= 59) & - (MSec >= 0) & (MSec <= 999) THEN - - bis := ORD((Year MOD 4 = 0) & (Year MOD 100 # 0) OR (Year MOD 400 = 0)); - - IF Day <= MonthsTable[Month][2 + bis] THEN - DEC(Year); - d := Year * 365 + (Year DIV 4) - (Year DIV 100) + (Year DIV 400) + - MonthsTable[Month][bis] + Day - 693594; - res := FLT(d) + FLT(Hour * 3600000 + Min * 60000 + Sec * 1000 + MSec) / 86400000.0 - END - END - RETURN res -END Encode; - - -PROCEDURE Decode* (Date: REAL; VAR Year, Month, Day, Hour, Min, Sec, MSec: INTEGER): BOOLEAN; -VAR - res: BOOLEAN; - d, t: INTEGER; - L, R, M: INTEGER; - -BEGIN - res := (Date >= -693593.0) & (Date < 2958466.0); - IF res THEN - d := FLOOR(Date); - t := FLOOR((Date - FLT(d)) * 86400000.0); - INC(d, 693593); - - L := 0; - R := LEN(DateTable) - 1; - M := (L + R) DIV 2; - - WHILE R - L > 1 DO - IF d > DateTable[M][0] THEN - L := M; - M := (L + R) DIV 2 - ELSIF d < DateTable[M][0] THEN - R := M; - M := (L + R) DIV 2 - ELSE - L := M; - R := M - END - END; - - Year := DateTable[L][1]; - Month := DateTable[L][2]; - Day := d - DateTable[L][0] + 1; - - Hour := t DIV 3600000; t := t MOD 3600000; - Min := t DIV 60000; t := t MOD 60000; - Sec := t DIV 1000; - MSec := t MOD 1000 - END - - RETURN res -END Decode; - - -PROCEDURE Now* (VAR Year, Month, Day, Hour, Min, Sec, MSec: INTEGER); -VAR - T: WINAPI.TSystemTime; - -BEGIN - WINAPI.GetLocalTime(T); - Year := ORD(T.Year); - Month := ORD(T.Month); - Day := ORD(T.Day); - Hour := ORD(T.Hour); - Min := ORD(T.Min); - Sec := ORD(T.Sec); - MSec := ORD(T.MSec) -END Now; - - -PROCEDURE NowEncode* (): REAL; -VAR - Year, Month, Day, Hour, Min, Sec, MSec: INTEGER; - -BEGIN - Now(Year, Month, Day, Hour, Min, Sec, MSec) - RETURN Encode(Year, Month, Day, Hour, Min, Sec, MSec) -END NowEncode; - - -PROCEDURE NowUnixTime* (): INTEGER; - RETURN WINAPI.time(0) -END NowUnixTime; - - -PROCEDURE UnixTime* (Year, Month, Day, Hour, Min, Sec: INTEGER): INTEGER; -VAR - t: WINAPI.tm; - -BEGIN - DEC(Year, 1900); - DEC(Month); - SYSTEM.GET(SYSTEM.ADR(Sec), t.sec); - SYSTEM.GET(SYSTEM.ADR(Min), t.min); - SYSTEM.GET(SYSTEM.ADR(Hour), t.hour); - SYSTEM.GET(SYSTEM.ADR(Day), t.mday); - SYSTEM.GET(SYSTEM.ADR(Month), t.mon); - SYSTEM.GET(SYSTEM.ADR(Year), t.year); - - RETURN WINAPI.mktime(t) -END UnixTime; - - -PROCEDURE init; -VAR - day, year, month, i: INTEGER; - Months: ARRAY 13 OF INTEGER; - -BEGIN - Months[1] := 31; Months[2] := 28; Months[3] := 31; Months[4] := 30; - Months[5] := 31; Months[6] := 30; Months[7] := 31; Months[8] := 31; - Months[9] := 30; Months[10] := 31; Months[11] := 30; Months[12] := 31; - - day := 0; - year := 1; - month := 1; - i := 0; - - WHILE year <= 10000 DO - DateTable[i][0] := day; - DateTable[i][1] := year; - DateTable[i][2] := month; - INC(day, Months[month]); - IF (month = 2) & ((year MOD 4 = 0) & (year MOD 100 # 0) OR (year MOD 400 = 0)) THEN - INC(day) - END; - INC(month); - IF month > 12 THEN - month := 1; - INC(year) - END; - INC(i) - END; - - MonthsTable[1][0] := 0; - FOR i := 2 TO 12 DO - MonthsTable[i][0] := MonthsTable[i - 1][0] + Months[i - 1] - END; - - FOR i := 1 TO 12 DO - MonthsTable[i][2] := Months[i] - END; - - Months[2] := 29; - MonthsTable[1][1] := 0; - FOR i := 2 TO 12 DO - MonthsTable[i][1] := MonthsTable[i - 1][1] + Months[i - 1] - END; - - FOR i := 1 TO 12 DO - MonthsTable[i][3] := Months[i] - END - -END init; - - -BEGIN - init -END DateTime. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows32/File.ob07 b/programs/develop/oberon07/Lib/Windows32/File.ob07 deleted file mode 100644 index b02f522a86..0000000000 --- a/programs/develop/oberon07/Lib/Windows32/File.ob07 +++ /dev/null @@ -1,139 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2019-2020, Anton Krotov - All rights reserved. -*) - -MODULE File; - -IMPORT SYSTEM, WINAPI, API; - - -CONST - - OPEN_R* = 0; OPEN_W* = 1; OPEN_RW* = 2; - SEEK_BEG* = 0; SEEK_CUR* = 1; SEEK_END* = 2; - - -PROCEDURE Exists* (FName: ARRAY OF CHAR): BOOLEAN; -VAR - FindData: WINAPI.TWin32FindData; - Handle: INTEGER; - attr: SET; - -BEGIN - Handle := WINAPI.FindFirstFileA(SYSTEM.ADR(FName[0]), FindData); - IF Handle # -1 THEN - WINAPI.FindClose(Handle); - SYSTEM.GET32(SYSTEM.ADR(FindData.dwFileAttributes), attr); - IF 4 IN attr THEN - Handle := -1 - END - END - - RETURN Handle # -1 -END Exists; - - -PROCEDURE Delete* (FName: ARRAY OF CHAR): BOOLEAN; - RETURN WINAPI.DeleteFileA(SYSTEM.ADR(FName[0])) # 0 -END Delete; - - -PROCEDURE Create* (FName: ARRAY OF CHAR): INTEGER; - RETURN WINAPI.CreateFileA(SYSTEM.ADR(FName[0]), 0C0000000H, 0, NIL, 2, 80H, 0) -END Create; - - -PROCEDURE Close* (F: INTEGER); -BEGIN - WINAPI.CloseHandle(F) -END Close; - - -PROCEDURE Open* (FName: ARRAY OF CHAR; Mode: INTEGER): INTEGER; -VAR - ofstr: WINAPI.OFSTRUCT; -BEGIN - RETURN WINAPI.OpenFile(SYSTEM.ADR(FName[0]), ofstr, Mode) -END Open; - - -PROCEDURE Seek* (F, Offset, Origin: INTEGER): INTEGER; - RETURN WINAPI.SetFilePointer(F, Offset, 0, Origin) -END Seek; - - -PROCEDURE Read* (F, Buffer, Count: INTEGER): INTEGER; -VAR - res: INTEGER; - -BEGIN - IF WINAPI.ReadFile(F, Buffer, Count, SYSTEM.ADR(res), NIL) = 0 THEN - res := -1 - END - - RETURN res -END Read; - - -PROCEDURE Write* (F, Buffer, Count: INTEGER): INTEGER; -VAR - res: INTEGER; - -BEGIN - IF WINAPI.WriteFile(F, Buffer, Count, SYSTEM.ADR(res), NIL) = 0 THEN - res := -1 - END - - RETURN res -END Write; - - -PROCEDURE Load* (FName: ARRAY OF CHAR; VAR Size: INTEGER): INTEGER; -VAR - res, n, F: INTEGER; - -BEGIN - res := 0; - F := Open(FName, OPEN_R); - - IF F # -1 THEN - Size := Seek(F, 0, SEEK_END); - n := Seek(F, 0, SEEK_BEG); - res := API._NEW(Size); - IF (res = 0) OR (Read(F, res, Size) # Size) THEN - IF res # 0 THEN - res := API._DISPOSE(res); - Size := 0 - END - END; - Close(F) - END - - RETURN res -END Load; - - -PROCEDURE RemoveDir* (DirName: ARRAY OF CHAR): BOOLEAN; - RETURN WINAPI.RemoveDirectoryA(SYSTEM.ADR(DirName[0])) # 0 -END RemoveDir; - - -PROCEDURE ExistsDir* (DirName: ARRAY OF CHAR): BOOLEAN; -VAR - Code: SET; - -BEGIN - Code := WINAPI.GetFileAttributesA(SYSTEM.ADR(DirName[0])) - RETURN (Code # {0..31}) & (4 IN Code) -END ExistsDir; - - -PROCEDURE CreateDir* (DirName: ARRAY OF CHAR): BOOLEAN; - RETURN WINAPI.CreateDirectoryA(SYSTEM.ADR(DirName[0]), NIL) # 0 -END CreateDir; - - -END File. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows32/HOST.ob07 b/programs/develop/oberon07/Lib/Windows32/HOST.ob07 deleted file mode 100644 index 045fce7ea5..0000000000 --- a/programs/develop/oberon07/Lib/Windows32/HOST.ob07 +++ /dev/null @@ -1,333 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018-2020, Anton Krotov - All rights reserved. -*) - -MODULE HOST; - -IMPORT SYSTEM, RTL; - - -CONST - - slash* = "\"; - eol* = 0DX + 0AX; - - bit_depth* = RTL.bit_depth; - maxint* = RTL.maxint; - minint* = RTL.minint; - - MAX_PARAM = 1024; - - OFS_MAXPATHNAME = 128; - - -TYPE - - POverlapped = POINTER TO OVERLAPPED; - - OVERLAPPED = RECORD - - Internal: INTEGER; - InternalHigh: INTEGER; - Offset: INTEGER; - OffsetHigh: INTEGER; - hEvent: INTEGER - - END; - - OFSTRUCT = RECORD - - cBytes: CHAR; - fFixedDisk: CHAR; - nErrCode: WCHAR; - Reserved1: WCHAR; - Reserved2: WCHAR; - szPathName: ARRAY OFS_MAXPATHNAME OF CHAR - - END; - - PSecurityAttributes = POINTER TO TSecurityAttributes; - - TSecurityAttributes = RECORD - - nLength: INTEGER; - lpSecurityDescriptor: INTEGER; - bInheritHandle: INTEGER - - END; - - -VAR - - hConsoleOutput: INTEGER; - - Params: ARRAY MAX_PARAM, 2 OF INTEGER; - argc: INTEGER; - - maxreal*: REAL; - - -PROCEDURE [windows-, "kernel32.dll", "GetTickCount"] - _GetTickCount (): INTEGER; - -PROCEDURE [windows-, "kernel32.dll", "GetStdHandle"] - _GetStdHandle (nStdHandle: INTEGER): INTEGER; - -PROCEDURE [windows-, "kernel32.dll", "GetCommandLineA"] - _GetCommandLine (): INTEGER; - -PROCEDURE [windows-, "kernel32.dll", "ReadFile"] - _ReadFile (hFile, Buffer, nNumberOfBytesToRW: INTEGER; VAR NumberOfBytesRW: INTEGER; lpOverlapped: POverlapped): INTEGER; - -PROCEDURE [windows-, "kernel32.dll", "WriteFile"] - _WriteFile (hFile, Buffer, nNumberOfBytesToRW: INTEGER; VAR NumberOfBytesRW: INTEGER; lpOverlapped: POverlapped): INTEGER; - -PROCEDURE [windows-, "kernel32.dll", "CloseHandle"] - _CloseHandle (hObject: INTEGER): INTEGER; - -PROCEDURE [windows-, "kernel32.dll", "CreateFileA"] - _CreateFile ( - lpFileName, dwDesiredAccess, dwShareMode: INTEGER; - lpSecurityAttributes: PSecurityAttributes; - dwCreationDisposition, dwFlagsAndAttributes, - hTemplateFile: INTEGER): INTEGER; - -PROCEDURE [windows-, "kernel32.dll", "OpenFile"] - _OpenFile (lpFileName: INTEGER; lpReOpenBuff: OFSTRUCT; uStyle: INTEGER): INTEGER; - -PROCEDURE [windows-, "kernel32.dll", "GetCurrentDirectoryA"] - _GetCurrentDirectory (nBufferLength, lpBuffer: INTEGER): INTEGER; - -PROCEDURE [windows-, "kernel32.dll", "ExitProcess"] - _ExitProcess (code: INTEGER); - -PROCEDURE [ccall, "msvcrt.dll", "time"] - _time (ptr: INTEGER): INTEGER; - - -PROCEDURE ExitProcess* (code: INTEGER); -BEGIN - _ExitProcess(code) -END ExitProcess; - - -PROCEDURE GetCurrentDirectory* (VAR path: ARRAY OF CHAR); -VAR - n: INTEGER; - -BEGIN - n := _GetCurrentDirectory(LEN(path), SYSTEM.ADR(path[0])); - path[n] := slash; - path[n + 1] := 0X -END GetCurrentDirectory; - - -PROCEDURE GetChar (adr: INTEGER): CHAR; -VAR - res: CHAR; - -BEGIN - SYSTEM.GET(adr, res) - RETURN res -END GetChar; - - -PROCEDURE ParamParse; -VAR - p, count, cond: INTEGER; - c: CHAR; - - - PROCEDURE ChangeCond (A, B, C: INTEGER; VAR cond: INTEGER; c: CHAR); - BEGIN - IF (c <= 20X) & (c # 0X) THEN - cond := A - ELSIF c = 22X THEN - cond := B - ELSIF c = 0X THEN - cond := 6 - ELSE - cond := C - END - END ChangeCond; - - -BEGIN - p := _GetCommandLine(); - cond := 0; - count := 0; - WHILE (count < MAX_PARAM) & (cond # 6) DO - c := GetChar(p); - CASE cond OF - |0: ChangeCond(0, 4, 1, cond, c); IF cond = 1 THEN Params[count, 0] := p END - |1: ChangeCond(0, 3, 1, cond, c); IF cond IN {0, 6} THEN Params[count, 1] := p - 1; INC(count) END - |3: ChangeCond(3, 1, 3, cond, c); IF cond = 6 THEN Params[count, 1] := p - 1; INC(count) END - |4: ChangeCond(5, 0, 5, cond, c); IF cond = 5 THEN Params[count, 0] := p END - |5: ChangeCond(5, 1, 5, cond, c); IF cond = 6 THEN Params[count, 1] := p - 1; INC(count) END - |6: - END; - INC(p) - END; - argc := count -END ParamParse; - - -PROCEDURE GetArg* (n: INTEGER; VAR s: ARRAY OF CHAR); -VAR - i, j, len: INTEGER; - c: CHAR; - -BEGIN - j := 0; - IF n < argc THEN - len := LEN(s) - 1; - i := Params[n, 0]; - WHILE (j < len) & (i <= Params[n, 1]) DO - c := GetChar(i); - IF c # 22X THEN - s[j] := c; - INC(j) - END; - INC(i) - END - END; - s[j] := 0X -END GetArg; - - -PROCEDURE FileRead* (F: INTEGER; VAR Buffer: ARRAY OF CHAR; bytes: INTEGER): INTEGER; -VAR - res: INTEGER; - -BEGIN - IF _ReadFile(F, SYSTEM.ADR(Buffer[0]), bytes, res, NIL) = 0 THEN - res := -1 - END - - RETURN res -END FileRead; - - -PROCEDURE FileWrite* (F: INTEGER; Buffer: ARRAY OF BYTE; bytes: INTEGER): INTEGER; -VAR - res: INTEGER; - -BEGIN - IF _WriteFile(F, SYSTEM.ADR(Buffer[0]), bytes, res, NIL) = 0 THEN - res := -1 - END - - RETURN res -END FileWrite; - - -PROCEDURE FileCreate* (FName: ARRAY OF CHAR): INTEGER; - RETURN _CreateFile(SYSTEM.ADR(FName[0]), 0C0000000H, 0, NIL, 2, 80H, 0) -END FileCreate; - - -PROCEDURE FileClose* (F: INTEGER); -BEGIN - _CloseHandle(F) -END FileClose; - - -PROCEDURE FileOpen* (FName: ARRAY OF CHAR): INTEGER; -VAR - ofstr: OFSTRUCT; - res: INTEGER; - -BEGIN - res := _OpenFile(SYSTEM.ADR(FName[0]), ofstr, 0); - IF res = 0FFFFFFFFH THEN - res := -1 - END - - RETURN res -END FileOpen; - - -PROCEDURE chmod* (FName: ARRAY OF CHAR); -END chmod; - - -PROCEDURE OutChar* (c: CHAR); -VAR - count: INTEGER; -BEGIN - _WriteFile(hConsoleOutput, SYSTEM.ADR(c), 1, count, NIL) -END OutChar; - - -PROCEDURE GetTickCount* (): INTEGER; - RETURN _GetTickCount() DIV 10 -END GetTickCount; - - -PROCEDURE letter (c: CHAR): BOOLEAN; - RETURN ("a" <= c) & (c <= "z") OR ("A" <= c) & (c <= "Z") -END letter; - - -PROCEDURE isRelative* (path: ARRAY OF CHAR): BOOLEAN; - RETURN ~(letter(path[0]) & (path[1] = ":")) -END isRelative; - - -PROCEDURE UnixTime* (): INTEGER; - RETURN _time(0) -END UnixTime; - - -PROCEDURE splitf* (x: REAL; VAR a, b: INTEGER): INTEGER; -BEGIN - SYSTEM.GET32(SYSTEM.ADR(x), a); - SYSTEM.GET32(SYSTEM.ADR(x) + 4, b) - RETURN a -END splitf; - - -PROCEDURE d2s* (x: REAL): INTEGER; -VAR - h, l, s, e: INTEGER; - -BEGIN - e := splitf(x, l, h); - - s := ASR(h, 31) MOD 2; - e := (h DIV 100000H) MOD 2048; - IF e <= 896 THEN - h := (h MOD 100000H) * 8 + (l DIV 20000000H) MOD 8 + 800000H; - REPEAT - h := h DIV 2; - INC(e) - UNTIL e = 897; - e := 896; - l := (h MOD 8) * 20000000H; - h := h DIV 8 - ELSIF (1151 <= e) & (e < 2047) THEN - e := 1151; - h := 0; - l := 0 - ELSIF e = 2047 THEN - e := 1151; - IF (h MOD 100000H # 0) OR (BITS(l) * {0..31} # {}) THEN - h := 80000H; - l := 0 - END - END; - DEC(e, 896) - - RETURN LSL(s, 31) + LSL(e, 23) + (h MOD 100000H) * 8 + (l DIV 20000000H) MOD 8 -END d2s; - - -BEGIN - maxreal := 1.9; - PACK(maxreal, 1023); - hConsoleOutput := _GetStdHandle(-11); - ParamParse -END HOST. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows32/In.ob07 b/programs/develop/oberon07/Lib/Windows32/In.ob07 deleted file mode 100644 index 3f5cc213ce..0000000000 --- a/programs/develop/oberon07/Lib/Windows32/In.ob07 +++ /dev/null @@ -1,80 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2020, Anton Krotov - All rights reserved. -*) - -MODULE In; - -IMPORT SYSTEM; - - -CONST - - MAX_LEN = 1024; - - -VAR - - Done*: BOOLEAN; - hConsoleInput: INTEGER; - s: ARRAY MAX_LEN + 4 OF CHAR; - - -PROCEDURE [ccall, "msvcrt.dll", ""] sscanf (buf: INTEGER; fmt: INTEGER; adr: INTEGER): INTEGER; -PROCEDURE [windows, "kernel32.dll", ""] GetStdHandle (nStdHandle: INTEGER): INTEGER; -PROCEDURE [windows, "kernel32.dll", ""] ReadConsoleA (hConsoleInput, lpBuffer, nNumberOfCharsToRead, lpNumberOfCharsRead, lpReserved: INTEGER); - - -PROCEDURE String* (VAR str: ARRAY OF CHAR); -VAR - count: INTEGER; - -BEGIN - ReadConsoleA(hConsoleInput, SYSTEM.ADR(s[0]), MAX_LEN, SYSTEM.ADR(count), 0); - IF (s[count - 1] = 0AX) & (s[count - 2] = 0DX) THEN - DEC(count, 2) - END; - s[count] := 0X; - COPY(s, str); - str[LEN(str) - 1] := 0X; - Done := TRUE -END String; - - -PROCEDURE Int* (VAR x: INTEGER); -BEGIN - String(s); - Done := sscanf(SYSTEM.ADR(s[0]), SYSTEM.SADR("%d"), SYSTEM.ADR(x)) = 1 -END Int; - - -PROCEDURE Real* (VAR x: REAL); -BEGIN - String(s); - Done := sscanf(SYSTEM.ADR(s[0]), SYSTEM.SADR("%lf"), SYSTEM.ADR(x)) = 1 -END Real; - - -PROCEDURE Char* (VAR x: CHAR); -BEGIN - String(s); - x := s[0] -END Char; - - -PROCEDURE Ln*; -BEGIN - String(s) -END Ln; - - -PROCEDURE Open*; -BEGIN - hConsoleInput := GetStdHandle(-10); - Done := TRUE -END Open; - - -END In. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows32/Math.ob07 b/programs/develop/oberon07/Lib/Windows32/Math.ob07 deleted file mode 100644 index d6056af747..0000000000 --- a/programs/develop/oberon07/Lib/Windows32/Math.ob07 +++ /dev/null @@ -1,450 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2013-2014, 2018-2020 Anton Krotov - All rights reserved. -*) - -MODULE Math; - -IMPORT SYSTEM; - - -CONST - - pi* = 3.141592653589793; - e* = 2.718281828459045; - - -PROCEDURE IsNan* (x: REAL): BOOLEAN; -VAR - h, l: SET; - -BEGIN - SYSTEM.GET(SYSTEM.ADR(x), l); - SYSTEM.GET(SYSTEM.ADR(x) + 4, h) - RETURN (h * {20..30} = {20..30}) & ((h * {0..19} # {}) OR (l * {0..31} # {})) -END IsNan; - - -PROCEDURE IsInf* (x: REAL): BOOLEAN; - RETURN ABS(x) = SYSTEM.INF() -END IsInf; - - -PROCEDURE Max (a, b: REAL): REAL; -VAR - res: REAL; - -BEGIN - IF a > b THEN - res := a - ELSE - res := b - END - RETURN res -END Max; - - -PROCEDURE Min (a, b: REAL): REAL; -VAR - res: REAL; - -BEGIN - IF a < b THEN - res := a - ELSE - res := b - END - RETURN res -END Min; - - -PROCEDURE SameValue (a, b: REAL): BOOLEAN; -VAR - eps: REAL; - res: BOOLEAN; - -BEGIN - eps := Max(Min(ABS(a), ABS(b)) * 1.0E-12, 1.0E-12); - IF a > b THEN - res := (a - b) <= eps - ELSE - res := (b - a) <= eps - END - RETURN res -END SameValue; - - -PROCEDURE IsZero (x: REAL): BOOLEAN; - RETURN ABS(x) <= 1.0E-12 -END IsZero; - - -PROCEDURE [stdcall] sqrt* (x: REAL): REAL; -BEGIN - SYSTEM.CODE( - 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) - 0D9H, 0FAH, (* fsqrt *) - 0C9H, (* leave *) - 0C2H, 008H, 000H (* ret 08h *) - ) - RETURN 0.0 -END sqrt; - - -PROCEDURE [stdcall] sin* (x: REAL): REAL; -BEGIN - SYSTEM.CODE( - 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) - 0D9H, 0FEH, (* fsin *) - 0C9H, (* leave *) - 0C2H, 008H, 000H (* ret 08h *) - ) - RETURN 0.0 -END sin; - - -PROCEDURE [stdcall] cos* (x: REAL): REAL; -BEGIN - SYSTEM.CODE( - 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) - 0D9H, 0FFH, (* fcos *) - 0C9H, (* leave *) - 0C2H, 008H, 000H (* ret 08h *) - ) - RETURN 0.0 -END cos; - - -PROCEDURE [stdcall] tan* (x: REAL): REAL; -BEGIN - SYSTEM.CODE( - 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) - 0D9H, 0FBH, (* fsincos *) - 0DEH, 0F9H, (* fdivp st1, st *) - 0C9H, (* leave *) - 0C2H, 008H, 000H (* ret 08h *) - ) - RETURN 0.0 -END tan; - - -PROCEDURE [stdcall] arctan2* (y, x: REAL): REAL; -BEGIN - SYSTEM.CODE( - 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) - 0DDH, 045H, 010H, (* fld qword [ebp + 10h] *) - 0D9H, 0F3H, (* fpatan *) - 0C9H, (* leave *) - 0C2H, 010H, 000H (* ret 10h *) - ) - RETURN 0.0 -END arctan2; - - -PROCEDURE [stdcall] ln* (x: REAL): REAL; -BEGIN - SYSTEM.CODE( - 0D9H, 0EDH, (* fldln2 *) - 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) - 0D9H, 0F1H, (* fyl2x *) - 0C9H, (* leave *) - 0C2H, 008H, 000H (* ret 08h *) - ) - RETURN 0.0 -END ln; - - -PROCEDURE [stdcall] log* (base, x: REAL): REAL; -BEGIN - SYSTEM.CODE( - 0D9H, 0E8H, (* fld1 *) - 0DDH, 045H, 010H, (* fld qword [ebp + 10h] *) - 0D9H, 0F1H, (* fyl2x *) - 0D9H, 0E8H, (* fld1 *) - 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) - 0D9H, 0F1H, (* fyl2x *) - 0DEH, 0F9H, (* fdivp st1, st *) - 0C9H, (* leave *) - 0C2H, 010H, 000H (* ret 10h *) - ) - RETURN 0.0 -END log; - - -PROCEDURE [stdcall] exp* (x: REAL): REAL; -BEGIN - SYSTEM.CODE( - 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) - 0D9H, 0EAH, (* fldl2e *) - 0DEH, 0C9H, 0D9H, 0C0H, - 0D9H, 0FCH, 0DCH, 0E9H, - 0D9H, 0C9H, 0D9H, 0F0H, - 0D9H, 0E8H, 0DEH, 0C1H, - 0D9H, 0FDH, 0DDH, 0D9H, - 0C9H, (* leave *) - 0C2H, 008H, 000H (* ret 08h *) - ) - RETURN 0.0 -END exp; - - -PROCEDURE [stdcall] round* (x: REAL): REAL; -BEGIN - SYSTEM.CODE( - 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) - 0D9H, 07DH, 0F4H, 0D9H, - 07DH, 0F6H, 066H, 081H, - 04DH, 0F6H, 000H, 003H, - 0D9H, 06DH, 0F6H, 0D9H, - 0FCH, 0D9H, 06DH, 0F4H, - 0C9H, (* leave *) - 0C2H, 008H, 000H (* ret 08h *) - ) - RETURN 0.0 -END round; - - -PROCEDURE [stdcall] frac* (x: REAL): REAL; -BEGIN - SYSTEM.CODE( - 050H, - 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *) - 0D9H, 0C0H, 0D9H, 03CH, - 024H, 0D9H, 07CH, 024H, - 002H, 066H, 081H, 04CH, - 024H, 002H, 000H, 00FH, - 0D9H, 06CH, 024H, 002H, - 0D9H, 0FCH, 0D9H, 02CH, - 024H, 0DEH, 0E9H, - 0C9H, (* leave *) - 0C2H, 008H, 000H (* ret 08h *) - ) - RETURN 0.0 -END frac; - - -PROCEDURE sqri* (x: INTEGER): INTEGER; - RETURN x * x -END sqri; - - -PROCEDURE sqrr* (x: REAL): REAL; - RETURN x * x -END sqrr; - - -PROCEDURE arcsin* (x: REAL): REAL; - RETURN arctan2(x, sqrt(1.0 - x * x)) -END arcsin; - - -PROCEDURE arccos* (x: REAL): REAL; - RETURN arctan2(sqrt(1.0 - x * x), x) -END arccos; - - -PROCEDURE arctan* (x: REAL): REAL; - RETURN arctan2(x, 1.0) -END arctan; - - -PROCEDURE sinh* (x: REAL): REAL; -BEGIN - x := exp(x) - RETURN (x - 1.0 / x) * 0.5 -END sinh; - - -PROCEDURE cosh* (x: REAL): REAL; -BEGIN - x := exp(x) - RETURN (x + 1.0 / x) * 0.5 -END cosh; - - -PROCEDURE tanh* (x: REAL): REAL; -BEGIN - IF x > 15.0 THEN - x := 1.0 - ELSIF x < -15.0 THEN - x := -1.0 - ELSE - x := exp(2.0 * x); - x := (x - 1.0) / (x + 1.0) - END - - RETURN x -END tanh; - - -PROCEDURE arsinh* (x: REAL): REAL; - RETURN ln(x + sqrt(x * x + 1.0)) -END arsinh; - - -PROCEDURE arcosh* (x: REAL): REAL; - RETURN ln(x + sqrt(x * x - 1.0)) -END arcosh; - - -PROCEDURE artanh* (x: REAL): REAL; -VAR - res: REAL; - -BEGIN - IF SameValue(x, 1.0) THEN - res := SYSTEM.INF() - ELSIF SameValue(x, -1.0) THEN - res := -SYSTEM.INF() - ELSE - res := 0.5 * ln((1.0 + x) / (1.0 - x)) - END - RETURN res -END artanh; - - -PROCEDURE floor* (x: REAL): REAL; -VAR - f: REAL; - -BEGIN - f := frac(x); - x := x - f; - IF f < 0.0 THEN - x := x - 1.0 - END - RETURN x -END floor; - - -PROCEDURE ceil* (x: REAL): REAL; -VAR - f: REAL; - -BEGIN - f := frac(x); - x := x - f; - IF f > 0.0 THEN - x := x + 1.0 - END - RETURN x -END ceil; - - -PROCEDURE power* (base, exponent: REAL): REAL; -VAR - res: REAL; - -BEGIN - IF exponent = 0.0 THEN - res := 1.0 - ELSIF (base = 0.0) & (exponent > 0.0) THEN - res := 0.0 - ELSE - res := exp(exponent * ln(base)) - END - RETURN res -END power; - - -PROCEDURE ipower* (base: REAL; exponent: INTEGER): REAL; -VAR - i: INTEGER; - a: REAL; - -BEGIN - a := 1.0; - - IF base # 0.0 THEN - IF exponent # 0 THEN - IF exponent < 0 THEN - base := 1.0 / base - END; - i := ABS(exponent); - WHILE i > 0 DO - WHILE ~ODD(i) DO - i := LSR(i, 1); - base := sqrr(base) - END; - DEC(i); - a := a * base - END - ELSE - a := 1.0 - END - ELSE - ASSERT(exponent > 0); - a := 0.0 - END - - RETURN a -END ipower; - - -PROCEDURE sgn* (x: REAL): INTEGER; -VAR - res: INTEGER; - -BEGIN - IF x > 0.0 THEN - res := 1 - ELSIF x < 0.0 THEN - res := -1 - ELSE - res := 0 - END - - RETURN res -END sgn; - - -PROCEDURE fact* (n: INTEGER): REAL; -VAR - res: REAL; - -BEGIN - res := 1.0; - WHILE n > 1 DO - res := res * FLT(n); - DEC(n) - END - - RETURN res -END fact; - - -PROCEDURE DegToRad* (x: REAL): REAL; - RETURN x * (pi / 180.0) -END DegToRad; - - -PROCEDURE RadToDeg* (x: REAL): REAL; - RETURN x * (180.0 / pi) -END RadToDeg; - - -(* Return hypotenuse of triangle *) -PROCEDURE hypot* (x, y: REAL): REAL; -VAR - a: REAL; - -BEGIN - x := ABS(x); - y := ABS(y); - IF x > y THEN - a := x * sqrt(1.0 + sqrr(y / x)) - ELSE - IF x > 0.0 THEN - a := y * sqrt(1.0 + sqrr(x / y)) - ELSE - a := y - END - END - - RETURN a -END hypot; - - -END Math. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows32/Out.ob07 b/programs/develop/oberon07/Lib/Windows32/Out.ob07 deleted file mode 100644 index 7795274927..0000000000 --- a/programs/develop/oberon07/Lib/Windows32/Out.ob07 +++ /dev/null @@ -1,77 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2020, Anton Krotov - All rights reserved. -*) - -MODULE Out; - -IMPORT SYSTEM; - - -VAR - - hConsoleOutput: INTEGER; - - -PROCEDURE [ccall, "msvcrt.dll", "printf"] printf1 (fmt: INTEGER; x: INTEGER); -PROCEDURE [ccall, "msvcrt.dll", "printf"] printf2 (fmt: INTEGER; width, x: INTEGER); -PROCEDURE [ccall, "msvcrt.dll", "printf"] printf3 (fmt: INTEGER; width, precision: INTEGER; x: REAL); - -PROCEDURE [windows, "kernel32.dll", ""] - WriteConsoleW (hConsoleOutput, lpBuffer, nNumberOfCharsToWrite, lpNumberOfCharsWritten, lpReserved: INTEGER); - -PROCEDURE [windows, "kernel32.dll", ""] - GetStdHandle (nStdHandle: INTEGER): INTEGER; - - -PROCEDURE Char* (x: CHAR); -BEGIN - printf1(SYSTEM.SADR("%c"), ORD(x)) -END Char; - - -PROCEDURE StringW* (s: ARRAY OF WCHAR); -BEGIN - WriteConsoleW(hConsoleOutput, SYSTEM.ADR(s[0]), LENGTH(s), 0, 0) -END StringW; - - -PROCEDURE String* (s: ARRAY OF CHAR); -BEGIN - printf2(SYSTEM.SADR("%.*s"), LENGTH(s), SYSTEM.ADR(s[0])) -END String; - - -PROCEDURE Ln*; -BEGIN - printf1(SYSTEM.SADR("%s"), SYSTEM.SADR(CHR(13) + CHR(10))) -END Ln; - - -PROCEDURE Int* (x, width: INTEGER); -BEGIN - printf2(SYSTEM.SADR("%*d"), width, x) -END Int; - - -PROCEDURE Real* (x: REAL; width: INTEGER); -BEGIN - printf3(SYSTEM.SADR("%*.*E"), width, MAX(MIN(width - 8, 15), 1), x) -END Real; - - -PROCEDURE FixReal* (x: REAL; width, precision: INTEGER); -BEGIN - printf3(SYSTEM.SADR("%*.*f"), width, precision, x) -END FixReal; - - -PROCEDURE Open*; -BEGIN - hConsoleOutput := GetStdHandle(-11) -END Open; - - -END Out. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows32/RTL.ob07 b/programs/develop/oberon07/Lib/Windows32/RTL.ob07 deleted file mode 100644 index 5f9e168085..0000000000 --- a/programs/develop/oberon07/Lib/Windows32/RTL.ob07 +++ /dev/null @@ -1,520 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018-2020, Anton Krotov - All rights reserved. -*) - -MODULE RTL; - -IMPORT SYSTEM, API; - - -CONST - - bit_depth* = 32; - maxint* = 7FFFFFFFH; - minint* = 80000000H; - - WORD = bit_depth DIV 8; - MAX_SET = bit_depth - 1; - - -VAR - - name: INTEGER; - types: INTEGER; - - -PROCEDURE [stdcall] _move* (bytes, dest, source: INTEGER); -BEGIN - SYSTEM.CODE( - 08BH, 045H, 008H, (* mov eax, dword [ebp + 8] *) - 085H, 0C0H, (* test eax, eax *) - 07EH, 019H, (* jle L *) - 0FCH, (* cld *) - 057H, (* push edi *) - 056H, (* push esi *) - 08BH, 075H, 010H, (* mov esi, dword [ebp + 16] *) - 08BH, 07DH, 00CH, (* mov edi, dword [ebp + 12] *) - 089H, 0C1H, (* mov ecx, eax *) - 0C1H, 0E9H, 002H, (* shr ecx, 2 *) - 0F3H, 0A5H, (* rep movsd *) - 089H, 0C1H, (* mov ecx, eax *) - 083H, 0E1H, 003H, (* and ecx, 3 *) - 0F3H, 0A4H, (* rep movsb *) - 05EH, (* pop esi *) - 05FH (* pop edi *) - (* L: *) - ) -END _move; - - -PROCEDURE [stdcall] _arrcpy* (base_size, len_dst, dst, len_src, src: INTEGER): BOOLEAN; -VAR - res: BOOLEAN; - -BEGIN - IF len_src > len_dst THEN - res := FALSE - ELSE - _move(len_src * base_size, dst, src); - res := TRUE - END - - RETURN res -END _arrcpy; - - -PROCEDURE [stdcall] _strcpy* (chr_size, len_src, src, len_dst, dst: INTEGER); -BEGIN - _move(MIN(len_dst, len_src) * chr_size, dst, src) -END _strcpy; - - -PROCEDURE [stdcall] _rot* (VAR A: ARRAY OF INTEGER); -VAR - i, n, k: INTEGER; - -BEGIN - k := LEN(A) - 1; - n := A[0]; - i := 0; - WHILE i < k DO - A[i] := A[i + 1]; - INC(i) - END; - A[k] := n -END _rot; - - -PROCEDURE [stdcall] _set* (b, a: INTEGER): INTEGER; -BEGIN - IF (a <= b) & (a <= MAX_SET) & (b >= 0) THEN - IF b > MAX_SET THEN - b := MAX_SET - END; - IF a < 0 THEN - a := 0 - END; - a := LSR(ASR(minint, b - a), MAX_SET - b) - ELSE - a := 0 - END - - RETURN a -END _set; - - -PROCEDURE [stdcall] _set1* (a: INTEGER); (* {a} -> eax *) -BEGIN - SYSTEM.CODE( - 031H, 0C0H, (* xor eax, eax *) - 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 8] *) (* ecx <- a *) - 083H, 0F9H, 01FH, (* cmp ecx, 31 *) - 077H, 003H, (* ja L *) - 00FH, 0ABH, 0C8H (* bts eax, ecx *) - (* L: *) - ) -END _set1; - - -PROCEDURE [stdcall] _divmod* (y, x: INTEGER); (* (x div y) -> eax; (x mod y) -> edx *) -BEGIN - SYSTEM.CODE( - 053H, (* push ebx *) - 08BH, 045H, 00CH, (* mov eax, dword [ebp + 12] *) (* eax <- x *) - 031H, 0D2H, (* xor edx, edx *) - 085H, 0C0H, (* test eax, eax *) - 074H, 018H, (* je L2 *) - 07FH, 002H, (* jg L1 *) - 0F7H, 0D2H, (* not edx *) - (* L1: *) - 089H, 0C3H, (* mov ebx, eax *) - 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 8] *) (* ecx <- y *) - 0F7H, 0F9H, (* idiv ecx *) - 085H, 0D2H, (* test edx, edx *) - 074H, 009H, (* je L2 *) - 031H, 0CBH, (* xor ebx, ecx *) - 085H, 0DBH, (* test ebx, ebx *) - 07DH, 003H, (* jge L2 *) - 048H, (* dec eax *) - 001H, 0CAH, (* add edx, ecx *) - (* L2: *) - 05BH (* pop ebx *) - ) -END _divmod; - - -PROCEDURE [stdcall] _new* (t, size: INTEGER; VAR ptr: INTEGER); -BEGIN - ptr := API._NEW(size); - IF ptr # 0 THEN - SYSTEM.PUT(ptr, t); - INC(ptr, WORD) - END -END _new; - - -PROCEDURE [stdcall] _dispose* (VAR ptr: INTEGER); -BEGIN - IF ptr # 0 THEN - ptr := API._DISPOSE(ptr - WORD) - END -END _dispose; - - -PROCEDURE [stdcall] _length* (len, str: INTEGER); -BEGIN - SYSTEM.CODE( - 08BH, 045H, 00CH, (* mov eax, dword [ebp + 0Ch] *) - 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 08h] *) - 048H, (* dec eax *) - (* L1: *) - 040H, (* inc eax *) - 080H, 038H, 000H, (* cmp byte [eax], 0 *) - 074H, 003H, (* jz L2 *) - 0E2H, 0F8H, (* loop L1 *) - 040H, (* inc eax *) - (* L2: *) - 02BH, 045H, 00CH (* sub eax, dword [ebp + 0Ch] *) - ) -END _length; - - -PROCEDURE [stdcall] _lengthw* (len, str: INTEGER); -BEGIN - SYSTEM.CODE( - 08BH, 045H, 00CH, (* mov eax, dword [ebp + 0Ch] *) - 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 08h] *) - 048H, (* dec eax *) - 048H, (* dec eax *) - (* L1: *) - 040H, (* inc eax *) - 040H, (* inc eax *) - 066H, 083H, 038H, 000H, (* cmp word [eax], 0 *) - 074H, 004H, (* jz L2 *) - 0E2H, 0F6H, (* loop L1 *) - 040H, (* inc eax *) - 040H, (* inc eax *) - (* L2: *) - 02BH, 045H, 00CH, (* sub eax, dword [ebp + 0Ch] *) - 0D1H, 0E8H (* shr eax, 1 *) - ) -END _lengthw; - - -PROCEDURE [stdcall] strncmp (a, b, n: INTEGER): INTEGER; -BEGIN - SYSTEM.CODE( - 056H, (* push esi *) - 057H, (* push edi *) - 053H, (* push ebx *) - 08BH, 075H, 008H, (* mov esi, dword[ebp + 8]; esi <- a *) - 08BH, 07DH, 00CH, (* mov edi, dword[ebp + 12]; edi <- b *) - 08BH, 05DH, 010H, (* mov ebx, dword[ebp + 16]; ebx <- n *) - 031H, 0C9H, (* xor ecx, ecx *) - 031H, 0D2H, (* xor edx, edx *) - 0B8H, - 000H, 000H, 000H, 080H, (* mov eax, minint *) - (* L1: *) - 085H, 0DBH, (* test ebx, ebx *) - 07EH, 017H, (* jle L3 *) - 08AH, 00EH, (* mov cl, byte[esi] *) - 08AH, 017H, (* mov dl, byte[edi] *) - 046H, (* inc esi *) - 047H, (* inc edi *) - 04BH, (* dec ebx *) - 039H, 0D1H, (* cmp ecx, edx *) - 074H, 006H, (* je L2 *) - 089H, 0C8H, (* mov eax, ecx *) - 029H, 0D0H, (* sub eax, edx *) - 0EBH, 006H, (* jmp L3 *) - (* L2: *) - 085H, 0C9H, (* test ecx, ecx *) - 075H, 0E7H, (* jne L1 *) - 031H, 0C0H, (* xor eax, eax *) - (* L3: *) - 05BH, (* pop ebx *) - 05FH, (* pop edi *) - 05EH, (* pop esi *) - 05DH, (* pop ebp *) - 0C2H, 00CH, 000H (* ret 12 *) - ) - RETURN 0 -END strncmp; - - -PROCEDURE [stdcall] strncmpw (a, b, n: INTEGER): INTEGER; -BEGIN - SYSTEM.CODE( - 056H, (* push esi *) - 057H, (* push edi *) - 053H, (* push ebx *) - 08BH, 075H, 008H, (* mov esi, dword[ebp + 8]; esi <- a *) - 08BH, 07DH, 00CH, (* mov edi, dword[ebp + 12]; edi <- b *) - 08BH, 05DH, 010H, (* mov ebx, dword[ebp + 16]; ebx <- n *) - 031H, 0C9H, (* xor ecx, ecx *) - 031H, 0D2H, (* xor edx, edx *) - 0B8H, - 000H, 000H, 000H, 080H, (* mov eax, minint *) - (* L1: *) - 085H, 0DBH, (* test ebx, ebx *) - 07EH, 01BH, (* jle L3 *) - 066H, 08BH, 00EH, (* mov cx, word[esi] *) - 066H, 08BH, 017H, (* mov dx, word[edi] *) - 046H, (* inc esi *) - 046H, (* inc esi *) - 047H, (* inc edi *) - 047H, (* inc edi *) - 04BH, (* dec ebx *) - 039H, 0D1H, (* cmp ecx, edx *) - 074H, 006H, (* je L2 *) - 089H, 0C8H, (* mov eax, ecx *) - 029H, 0D0H, (* sub eax, edx *) - 0EBH, 006H, (* jmp L3 *) - (* L2: *) - 085H, 0C9H, (* test ecx, ecx *) - 075H, 0E3H, (* jne L1 *) - 031H, 0C0H, (* xor eax, eax *) - (* L3: *) - 05BH, (* pop ebx *) - 05FH, (* pop edi *) - 05EH, (* pop esi *) - 05DH, (* pop ebp *) - 0C2H, 00CH, 000H (* ret 12 *) - ) - RETURN 0 -END strncmpw; - - -PROCEDURE [stdcall] _strcmp* (op, len2, str2, len1, str1: INTEGER): BOOLEAN; -VAR - res: INTEGER; - bRes: BOOLEAN; - c: CHAR; - -BEGIN - res := strncmp(str1, str2, MIN(len1, len2)); - IF res = minint THEN - IF len1 > len2 THEN - SYSTEM.GET(str1 + len2, c); - res := ORD(c) - ELSIF len1 < len2 THEN - SYSTEM.GET(str2 + len1, c); - res := -ORD(c) - ELSE - res := 0 - END - END; - - CASE op OF - |0: bRes := res = 0 - |1: bRes := res # 0 - |2: bRes := res < 0 - |3: bRes := res <= 0 - |4: bRes := res > 0 - |5: bRes := res >= 0 - END - - RETURN bRes -END _strcmp; - - -PROCEDURE [stdcall] _strcmpw* (op, len2, str2, len1, str1: INTEGER): BOOLEAN; -VAR - res: INTEGER; - bRes: BOOLEAN; - c: WCHAR; - -BEGIN - res := strncmpw(str1, str2, MIN(len1, len2)); - IF res = minint THEN - IF len1 > len2 THEN - SYSTEM.GET(str1 + len2 * 2, c); - res := ORD(c) - ELSIF len1 < len2 THEN - SYSTEM.GET(str2 + len1 * 2, c); - res := -ORD(c) - ELSE - res := 0 - END - END; - - CASE op OF - |0: bRes := res = 0 - |1: bRes := res # 0 - |2: bRes := res < 0 - |3: bRes := res <= 0 - |4: bRes := res > 0 - |5: bRes := res >= 0 - END - - RETURN bRes -END _strcmpw; - - -PROCEDURE PCharToStr (pchar: INTEGER; VAR s: ARRAY OF CHAR); -VAR - c: CHAR; - i: INTEGER; - -BEGIN - i := 0; - REPEAT - SYSTEM.GET(pchar, c); - s[i] := c; - INC(pchar); - INC(i) - UNTIL c = 0X -END PCharToStr; - - -PROCEDURE IntToStr (x: INTEGER; VAR str: ARRAY OF CHAR); -VAR - i, a: INTEGER; - -BEGIN - i := 0; - a := x; - REPEAT - INC(i); - a := a DIV 10 - UNTIL a = 0; - - str[i] := 0X; - - REPEAT - DEC(i); - str[i] := CHR(x MOD 10 + ORD("0")); - x := x DIV 10 - UNTIL x = 0 -END IntToStr; - - -PROCEDURE append (VAR s1: ARRAY OF CHAR; s2: ARRAY OF CHAR); -VAR - n1, n2: INTEGER; - -BEGIN - n1 := LENGTH(s1); - n2 := LENGTH(s2); - - ASSERT(n1 + n2 < LEN(s1)); - - SYSTEM.MOVE(SYSTEM.ADR(s2[0]), SYSTEM.ADR(s1[n1]), n2); - s1[n1 + n2] := 0X -END append; - - -PROCEDURE [stdcall] _error* (modnum, _module, err, line: INTEGER); -VAR - s, temp: ARRAY 1024 OF CHAR; - -BEGIN - CASE err OF - | 1: s := "assertion failure" - | 2: s := "NIL dereference" - | 3: s := "bad divisor" - | 4: s := "NIL procedure call" - | 5: s := "type guard error" - | 6: s := "index out of range" - | 7: s := "invalid CASE" - | 8: s := "array assignment error" - | 9: s := "CHR out of range" - |10: s := "WCHR out of range" - |11: s := "BYTE out of range" - END; - - append(s, API.eol + "module: "); PCharToStr(_module, temp); append(s, temp); - append(s, API.eol + "line: "); IntToStr(line, temp); append(s, temp); - - API.DebugMsg(SYSTEM.ADR(s[0]), name); - - API.exit_thread(0) -END _error; - - -PROCEDURE [stdcall] _isrec* (t0, t1, r: INTEGER): INTEGER; -BEGIN - SYSTEM.GET(t0 + t1 + types, t0) - RETURN t0 MOD 2 -END _isrec; - - -PROCEDURE [stdcall] _is* (t0, p: INTEGER): INTEGER; -BEGIN - IF p # 0 THEN - SYSTEM.GET(p - WORD, p); - SYSTEM.GET(t0 + p + types, p) - END - - RETURN p MOD 2 -END _is; - - -PROCEDURE [stdcall] _guardrec* (t0, t1: INTEGER): INTEGER; -BEGIN - SYSTEM.GET(t0 + t1 + types, t0) - RETURN t0 MOD 2 -END _guardrec; - - -PROCEDURE [stdcall] _guard* (t0, p: INTEGER): INTEGER; -BEGIN - SYSTEM.GET(p, p); - IF p # 0 THEN - SYSTEM.GET(p - WORD, p); - SYSTEM.GET(t0 + p + types, p) - ELSE - p := 1 - END - - RETURN p MOD 2 -END _guard; - - -PROCEDURE [stdcall] _dllentry* (hinstDLL, fdwReason, lpvReserved: INTEGER): INTEGER; - RETURN API.dllentry(hinstDLL, fdwReason, lpvReserved) -END _dllentry; - - -PROCEDURE [stdcall] _sofinit*; -BEGIN - API.sofinit -END _sofinit; - - -PROCEDURE [stdcall] _exit* (code: INTEGER); -BEGIN - API.exit(code) -END _exit; - - -PROCEDURE [stdcall] _init* (modname: INTEGER; tcount, _types: INTEGER; code, param: INTEGER); -VAR - t0, t1, i, j: INTEGER; - -BEGIN - SYSTEM.CODE(09BH, 0DBH, 0E3H); (* finit *) - API.init(param, code); - - types := API._NEW(tcount * tcount + SYSTEM.SIZE(INTEGER)); - ASSERT(types # 0); - FOR i := 0 TO tcount - 1 DO - FOR j := 0 TO tcount - 1 DO - t0 := i; t1 := j; - - WHILE (t1 # 0) & (t1 # t0) DO - SYSTEM.GET(_types + t1 * WORD, t1) - END; - - SYSTEM.PUT8(i * tcount + j + types, ORD(t0 = t1)) - END - END; - - name := modname -END _init; - - -END RTL. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows32/WINAPI.ob07 b/programs/develop/oberon07/Lib/Windows32/WINAPI.ob07 deleted file mode 100644 index 1fe4efabc9..0000000000 --- a/programs/develop/oberon07/Lib/Windows32/WINAPI.ob07 +++ /dev/null @@ -1,224 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2019-2020, Anton Krotov - All rights reserved. -*) - -MODULE WINAPI; - -IMPORT SYSTEM, API; - - -CONST - - OFS_MAXPATHNAME* = 128; - - KERNEL = "kernel32.dll"; - USER = "user32.dll"; - MSVCRT = "msvcrt.dll"; - - -TYPE - - DLL_ENTRY* = API.DLL_ENTRY; - - STRING = ARRAY 260 OF CHAR; - - TCoord* = RECORD - - X*, Y*: WCHAR - - END; - - TSmallRect* = RECORD - - Left*, Top*, Right*, Bottom*: WCHAR - - END; - - TConsoleScreenBufferInfo* = RECORD - - dwSize*: TCoord; - dwCursorPosition*: TCoord; - wAttributes*: WCHAR; - srWindow*: TSmallRect; - dwMaximumWindowSize*: TCoord - - END; - - TSystemTime* = RECORD - - Year*, - Month*, - DayOfWeek*, - Day*, - Hour*, - Min*, - Sec*, - MSec*: WCHAR - - END; - - tm* = RECORD - - sec*, - min*, - hour*, - mday*, - mon*, - year*, - wday*, - yday*, - isdst*: SYSTEM.CARD32 - - END; - - PSecurityAttributes* = POINTER TO TSecurityAttributes; - - TSecurityAttributes* = RECORD - - nLength*: SYSTEM.CARD32; - lpSecurityDescriptor*: INTEGER; - bInheritHandle*: SYSTEM.CARD32 (* BOOL *) - - END; - - TFileTime* = RECORD - - dwLowDateTime*, - dwHighDateTime*: SYSTEM.CARD32 - - END; - - TWin32FindData* = RECORD - - dwFileAttributes*: SYSTEM.CARD32; - ftCreationTime*: TFileTime; - ftLastAccessTime*: TFileTime; - ftLastWriteTime*: TFileTime; - nFileSizeHigh*: SYSTEM.CARD32; - nFileSizeLow*: SYSTEM.CARD32; - dwReserved0*: SYSTEM.CARD32; - dwReserved1*: SYSTEM.CARD32; - cFileName*: STRING; - cAlternateFileName*: ARRAY 14 OF CHAR; - dwFileType*: SYSTEM.CARD32; - dwCreatorType*: SYSTEM.CARD32; - wFinderFlags*: WCHAR - - END; - - OFSTRUCT* = RECORD - - cBytes*: BYTE; - fFixedDisk*: BYTE; - nErrCode*: WCHAR; - Reserved1*: WCHAR; - Reserved2*: WCHAR; - szPathName*: ARRAY OFS_MAXPATHNAME OF CHAR - - END; - - POverlapped* = POINTER TO OVERLAPPED; - - OVERLAPPED* = RECORD - - Internal*: INTEGER; - InternalHigh*: INTEGER; - Offset*: SYSTEM.CARD32; - OffsetHigh*: SYSTEM.CARD32; - hEvent*: INTEGER - - END; - - -PROCEDURE [windows-, KERNEL, ""] SetConsoleCursorPosition* (hConsoleOutput, dwCursorPosition: INTEGER): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] GetConsoleScreenBufferInfo* (hConsoleOutput: INTEGER; ConsoleScreenBufferInfo: TConsoleScreenBufferInfo): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] FillConsoleOutputCharacterA* (hConsoleOutput, cCaracter, nLength, dwWriteCoord, lpNumberOfCharsWritten: INTEGER): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] FillConsoleOutputAttribute* (hConsoleOutput, wAttribute, nLength, dwWriteCoord, lpNumberOfAttrsWritten: INTEGER): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] SetConsoleTextAttribute* (hConsoleOutput, wAttributes: INTEGER): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] GetStdHandle* (nStdHandle: INTEGER): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] GetLocalTime* (T: TSystemTime); - -PROCEDURE [windows-, KERNEL, ""] RemoveDirectoryA* (lpPathName: INTEGER): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] GetFileAttributesA* (lpPathName: INTEGER): SET; - -PROCEDURE [windows-, KERNEL, ""] CreateDirectoryA* (lpPathName: INTEGER; lpSecurityAttributes: PSecurityAttributes): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] FindFirstFileA* (lpFileName: INTEGER; lpFindFileData: TWin32FindData): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] DeleteFileA* (lpFileName: INTEGER): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] FindClose* (hFindFile: INTEGER): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] CloseHandle* (hObject: INTEGER): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] CreateFileA* ( - lpFileName, dwDesiredAccess, dwShareMode: INTEGER; - lpSecurityAttributes: PSecurityAttributes; - dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile: INTEGER): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] OpenFile* (lpFileName: INTEGER; lpReOpenBuff: OFSTRUCT; uStyle: INTEGER): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] SetFilePointer* (hFile, lDistanceToMove, lpDistanceToMoveHigh, dwMoveMethod: INTEGER): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] ReadFile* (hFile, Buffer, nNumberOfBytesToRead, lpNumberOfBytesRead: INTEGER; lpOverlapped: POverlapped): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] WriteFile* (hFile, Buffer, nNumberOfBytesToRead, lpNumberOfBytesRead: INTEGER; lpOverlapped: POverlapped): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] ReadConsoleA* (hConsoleInput, lpBuffer, nNumberOfCharsToRead, lpNumberOfCharsRead, lpReserved: INTEGER): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] GetCommandLineA* (): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] GlobalAlloc* (uFlags, dwBytes: INTEGER): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] GlobalFree* (hMem: INTEGER): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] WriteConsoleW* (hConsoleOutput, lpBuffer, nNumberOfCharsToWrite, lpNumberOfCharsWritten, lpReserved: INTEGER): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] ExitProcess* (code: INTEGER); - -PROCEDURE [windows-, KERNEL, ""] WriteConsoleA* (hConsoleOutput, lpBuffer, nNumberOfCharsToWrite, lpNumberOfCharsWritten, lpReserved: INTEGER): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] GetTickCount* (): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] Sleep* (dwMilliseconds: INTEGER); - -PROCEDURE [windows-, KERNEL, ""] FreeLibrary* (hLibModule: INTEGER): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] GetProcAddress* (hModule, name: INTEGER): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] LoadLibraryA* (name: INTEGER): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] AllocConsole* (): BOOLEAN; - -PROCEDURE [windows-, KERNEL, ""] FreeConsole* (): BOOLEAN; - -PROCEDURE [windows-, USER, ""] MessageBoxA* (hWnd, lpText, lpCaption, uType: INTEGER): INTEGER; - -PROCEDURE [windows-, USER, ""] MessageBoxW* (hWnd, lpText, lpCaption, uType: INTEGER): INTEGER; - -PROCEDURE [windows-, USER, ""] CreateWindowExA* ( - dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, - nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam: INTEGER): INTEGER; - -PROCEDURE [ccall-, MSVCRT, ""] time* (ptr: INTEGER): INTEGER; - -PROCEDURE [ccall-, MSVCRT, ""] mktime* (time: tm): INTEGER; - - -PROCEDURE SetDllEntry* (process_detach, thread_detach, thread_attach: DLL_ENTRY); -BEGIN - API.SetDll(process_detach, thread_detach, thread_attach) -END SetDllEntry; - - -END WINAPI. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows64/API.ob07 b/programs/develop/oberon07/Lib/Windows64/API.ob07 deleted file mode 100644 index 437d08b893..0000000000 --- a/programs/develop/oberon07/Lib/Windows64/API.ob07 +++ /dev/null @@ -1,132 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018-2020, Anton Krotov - All rights reserved. -*) - -MODULE API; - -IMPORT SYSTEM; - - -CONST - - eol* = 0DX + 0AX; - - SectionAlignment = 1000H; - - DLL_PROCESS_ATTACH = 1; - DLL_THREAD_ATTACH = 2; - DLL_THREAD_DETACH = 3; - DLL_PROCESS_DETACH = 0; - - KERNEL = "kernel32.dll"; - USER = "user32.dll"; - - -TYPE - - DLL_ENTRY* = PROCEDURE (hinstDLL, fdwReason, lpvReserved: INTEGER); - - -VAR - - base*: INTEGER; - heap: INTEGER; - - process_detach, - thread_detach, - thread_attach: DLL_ENTRY; - - -PROCEDURE [windows-, KERNEL, ""] ExitProcess (code: INTEGER); -PROCEDURE [windows-, KERNEL, ""] ExitThread (code: INTEGER); -PROCEDURE [windows-, KERNEL, ""] GetProcessHeap (): INTEGER; -PROCEDURE [windows-, KERNEL, ""] HeapAlloc (hHeap, dwFlags, dwBytes: INTEGER): INTEGER; -PROCEDURE [windows-, KERNEL, ""] HeapFree (hHeap, dwFlags, lpMem: INTEGER); -PROCEDURE [windows-, USER, ""] MessageBoxA (hWnd, lpText, lpCaption, uType: INTEGER): INTEGER; - - -PROCEDURE DebugMsg* (lpText, lpCaption: INTEGER); -BEGIN - MessageBoxA(0, lpText, lpCaption, 16) -END DebugMsg; - - -PROCEDURE _NEW* (size: INTEGER): INTEGER; - RETURN HeapAlloc(heap, 8, size) -END _NEW; - - -PROCEDURE _DISPOSE* (p: INTEGER): INTEGER; -BEGIN - HeapFree(heap, 0, p) - RETURN 0 -END _DISPOSE; - - -PROCEDURE init* (reserved, code: INTEGER); -BEGIN - process_detach := NIL; - thread_detach := NIL; - thread_attach := NIL; - base := code - SectionAlignment; - heap := GetProcessHeap() -END init; - - -PROCEDURE exit* (code: INTEGER); -BEGIN - ExitProcess(code) -END exit; - - -PROCEDURE exit_thread* (code: INTEGER); -BEGIN - ExitThread(code) -END exit_thread; - - -PROCEDURE dllentry* (hinstDLL, fdwReason, lpvReserved: INTEGER): INTEGER; -VAR - res: INTEGER; - -BEGIN - res := 0; - - CASE fdwReason OF - |DLL_PROCESS_ATTACH: - res := 1 - |DLL_THREAD_ATTACH: - IF thread_attach # NIL THEN - thread_attach(hinstDLL, fdwReason, lpvReserved) - END - |DLL_THREAD_DETACH: - IF thread_detach # NIL THEN - thread_detach(hinstDLL, fdwReason, lpvReserved) - END - |DLL_PROCESS_DETACH: - IF process_detach # NIL THEN - process_detach(hinstDLL, fdwReason, lpvReserved) - END - ELSE - END - - RETURN res -END dllentry; - - -PROCEDURE sofinit*; -END sofinit; - - -PROCEDURE SetDll* (_process_detach, _thread_detach, _thread_attach: DLL_ENTRY); -BEGIN - process_detach := _process_detach; - thread_detach := _thread_detach; - thread_attach := _thread_attach -END SetDll; - - -END API. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows64/Args.ob07 b/programs/develop/oberon07/Lib/Windows64/Args.ob07 deleted file mode 100644 index 3d4ae39cfe..0000000000 --- a/programs/develop/oberon07/Lib/Windows64/Args.ob07 +++ /dev/null @@ -1,101 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2019-2020, Anton Krotov - All rights reserved. -*) - -MODULE Args; - -IMPORT SYSTEM, WINAPI; - - -CONST - - MAX_PARAM = 1024; - - -VAR - - Params: ARRAY MAX_PARAM, 2 OF INTEGER; - argc*: INTEGER; - - -PROCEDURE GetChar (adr: INTEGER): CHAR; -VAR - res: CHAR; - -BEGIN - SYSTEM.GET(adr, res) - RETURN res -END GetChar; - - -PROCEDURE ParamParse; -VAR - p, count, cond: INTEGER; - c: CHAR; - - - PROCEDURE ChangeCond (A, B, C: INTEGER; VAR cond: INTEGER; c: CHAR): INTEGER; - BEGIN - IF (c <= 20X) & (c # 0X) THEN - cond := A - ELSIF c = 22X THEN - cond := B - ELSIF c = 0X THEN - cond := 6 - ELSE - cond := C - END - - RETURN cond - END ChangeCond; - - -BEGIN - p := WINAPI.GetCommandLineA(); - cond := 0; - count := 0; - WHILE (count < MAX_PARAM) & (cond # 6) DO - c := GetChar(p); - CASE cond OF - |0: IF ChangeCond(0, 4, 1, cond, c) = 1 THEN Params[count, 0] := p END - |1: IF ChangeCond(0, 3, 1, cond, c) IN {0, 6} THEN Params[count, 1] := p - 1; INC(count) END - |3: IF ChangeCond(3, 1, 3, cond, c) = 6 THEN Params[count, 1] := p - 1; INC(count) END - |4: IF ChangeCond(5, 0, 5, cond, c) = 5 THEN Params[count, 0] := p END - |5: IF ChangeCond(5, 1, 5, cond, c) = 6 THEN Params[count, 1] := p - 1; INC(count) END - |6: - END; - INC(p) - END; - argc := count -END ParamParse; - - -PROCEDURE GetArg* (n: INTEGER; VAR s: ARRAY OF CHAR); -VAR - i, j, len: INTEGER; - c: CHAR; - -BEGIN - j := 0; - IF n < argc THEN - i := Params[n, 0]; - len := LEN(s) - 1; - WHILE (j < len) & (i <= Params[n, 1]) DO - c := GetChar(i); - IF c # '"' THEN - s[j] := c; - INC(j) - END; - INC(i) - END - END; - s[j] := 0X -END GetArg; - - -BEGIN - ParamParse -END Args. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows64/Console.ob07 b/programs/develop/oberon07/Lib/Windows64/Console.ob07 deleted file mode 100644 index d11e06db42..0000000000 --- a/programs/develop/oberon07/Lib/Windows64/Console.ob07 +++ /dev/null @@ -1,100 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2019-2020, Anton Krotov - All rights reserved. -*) - -MODULE Console; - -IMPORT SYSTEM, WINAPI, In, Out; - - -CONST - - Black* = 0; Blue* = 1; Green* = 2; Cyan* = 3; - Red* = 4; Magenta* = 5; Brown* = 6; LightGray* = 7; - DarkGray* = 8; LightBlue* = 9; LightGreen* = 10; LightCyan* = 11; - LightRed* = 12; LightMagenta* = 13; Yellow* = 14; White* = 15; - - -VAR - - hConsoleOutput: INTEGER; - - -PROCEDURE SetCursor* (X, Y: INTEGER); -BEGIN - WINAPI.SetConsoleCursorPosition(hConsoleOutput, X + Y * 65536) -END SetCursor; - - -PROCEDURE GetCursor* (VAR X, Y: INTEGER); -VAR - ScrBufInfo: WINAPI.TConsoleScreenBufferInfo; - -BEGIN - WINAPI.GetConsoleScreenBufferInfo(hConsoleOutput, ScrBufInfo); - X := ORD(ScrBufInfo.dwCursorPosition.X); - Y := ORD(ScrBufInfo.dwCursorPosition.Y) -END GetCursor; - - -PROCEDURE Cls*; -VAR - fill: INTEGER; - ScrBufInfo: WINAPI.TConsoleScreenBufferInfo; - -BEGIN - WINAPI.GetConsoleScreenBufferInfo(hConsoleOutput, ScrBufInfo); - fill := ORD(ScrBufInfo.dwSize.X) * ORD(ScrBufInfo.dwSize.Y); - WINAPI.FillConsoleOutputCharacterA(hConsoleOutput, 20H, fill, 0, SYSTEM.ADR(fill)); - WINAPI.FillConsoleOutputAttribute(hConsoleOutput, ORD(ScrBufInfo.wAttributes), fill, 0, SYSTEM.ADR(fill)); - SetCursor(0, 0) -END Cls; - - -PROCEDURE SetColor* (FColor, BColor: INTEGER); -BEGIN - IF (FColor IN {0..15}) & (BColor IN {0..15}) THEN - WINAPI.SetConsoleTextAttribute(hConsoleOutput, LSL(BColor, 4) + FColor) - END -END SetColor; - - -PROCEDURE GetCursorX* (): INTEGER; -VAR - ScrBufInfo: WINAPI.TConsoleScreenBufferInfo; - -BEGIN - WINAPI.GetConsoleScreenBufferInfo(hConsoleOutput, ScrBufInfo) - RETURN ORD(ScrBufInfo.dwCursorPosition.X) -END GetCursorX; - - -PROCEDURE GetCursorY* (): INTEGER; -VAR - ScrBufInfo: WINAPI.TConsoleScreenBufferInfo; - -BEGIN - WINAPI.GetConsoleScreenBufferInfo(hConsoleOutput, ScrBufInfo) - RETURN ORD(ScrBufInfo.dwCursorPosition.Y) -END GetCursorY; - - -PROCEDURE open*; -BEGIN - WINAPI.AllocConsole; - hConsoleOutput := WINAPI.GetStdHandle(-11); - In.Open; - Out.Open -END open; - - -PROCEDURE exit* (b: BOOLEAN); -BEGIN - WINAPI.FreeConsole -END exit; - - -END Console. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows64/DateTime.ob07 b/programs/develop/oberon07/Lib/Windows64/DateTime.ob07 deleted file mode 100644 index f527c18f27..0000000000 --- a/programs/develop/oberon07/Lib/Windows64/DateTime.ob07 +++ /dev/null @@ -1,197 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2019-2020, Anton Krotov - All rights reserved. -*) - -MODULE DateTime; - -IMPORT WINAPI, SYSTEM; - - -CONST - - ERR* = -7.0E5; - - -VAR - - DateTable: ARRAY 120000, 3 OF INTEGER; - MonthsTable: ARRAY 13, 4 OF INTEGER; - - -PROCEDURE Encode* (Year, Month, Day, Hour, Min, Sec, MSec: INTEGER): REAL; -VAR - d, bis: INTEGER; - res: REAL; - -BEGIN - res := ERR; - IF (Year >= 1) & (Year <= 9999) & (Month >= 1) & (Month <= 12) & - (Day >= 1) & (Day <= 31) & (Hour >= 0) & (Hour <= 23) & - (Min >= 0) & (Min <= 59) & (Sec >= 0) & (Sec <= 59) & - (MSec >= 0) & (MSec <= 999) THEN - - bis := ORD((Year MOD 4 = 0) & (Year MOD 100 # 0) OR (Year MOD 400 = 0)); - - IF Day <= MonthsTable[Month][2 + bis] THEN - DEC(Year); - d := Year * 365 + (Year DIV 4) - (Year DIV 100) + (Year DIV 400) + - MonthsTable[Month][bis] + Day - 693594; - res := FLT(d) + FLT(Hour * 3600000 + Min * 60000 + Sec * 1000 + MSec) / 86400000.0 - END - END - RETURN res -END Encode; - - -PROCEDURE Decode* (Date: REAL; VAR Year, Month, Day, Hour, Min, Sec, MSec: INTEGER): BOOLEAN; -VAR - res: BOOLEAN; - d, t: INTEGER; - L, R, M: INTEGER; - -BEGIN - res := (Date >= -693593.0) & (Date < 2958466.0); - IF res THEN - d := FLOOR(Date); - t := FLOOR((Date - FLT(d)) * 86400000.0); - INC(d, 693593); - - L := 0; - R := LEN(DateTable) - 1; - M := (L + R) DIV 2; - - WHILE R - L > 1 DO - IF d > DateTable[M][0] THEN - L := M; - M := (L + R) DIV 2 - ELSIF d < DateTable[M][0] THEN - R := M; - M := (L + R) DIV 2 - ELSE - L := M; - R := M - END - END; - - Year := DateTable[L][1]; - Month := DateTable[L][2]; - Day := d - DateTable[L][0] + 1; - - Hour := t DIV 3600000; t := t MOD 3600000; - Min := t DIV 60000; t := t MOD 60000; - Sec := t DIV 1000; - MSec := t MOD 1000 - END - - RETURN res -END Decode; - - -PROCEDURE Now* (VAR Year, Month, Day, Hour, Min, Sec, MSec: INTEGER); -VAR - T: WINAPI.TSystemTime; - -BEGIN - WINAPI.GetLocalTime(T); - Year := ORD(T.Year); - Month := ORD(T.Month); - Day := ORD(T.Day); - Hour := ORD(T.Hour); - Min := ORD(T.Min); - Sec := ORD(T.Sec); - MSec := ORD(T.MSec) -END Now; - - -PROCEDURE NowEncode* (): REAL; -VAR - Year, Month, Day, Hour, Min, Sec, MSec: INTEGER; - -BEGIN - Now(Year, Month, Day, Hour, Min, Sec, MSec) - RETURN Encode(Year, Month, Day, Hour, Min, Sec, MSec) -END NowEncode; - - -PROCEDURE NowUnixTime* (): INTEGER; - RETURN WINAPI.time(0) -END NowUnixTime; - - -PROCEDURE UnixTime* (Year, Month, Day, Hour, Min, Sec: INTEGER): INTEGER; -VAR - t: WINAPI.tm; - -BEGIN - DEC(Year, 1900); - DEC(Month); - SYSTEM.GET(SYSTEM.ADR(Sec), t.sec); - SYSTEM.GET(SYSTEM.ADR(Min), t.min); - SYSTEM.GET(SYSTEM.ADR(Hour), t.hour); - SYSTEM.GET(SYSTEM.ADR(Day), t.mday); - SYSTEM.GET(SYSTEM.ADR(Month), t.mon); - SYSTEM.GET(SYSTEM.ADR(Year), t.year); - - RETURN WINAPI.mktime(t) -END UnixTime; - - -PROCEDURE init; -VAR - day, year, month, i: INTEGER; - Months: ARRAY 13 OF INTEGER; - -BEGIN - Months[1] := 31; Months[2] := 28; Months[3] := 31; Months[4] := 30; - Months[5] := 31; Months[6] := 30; Months[7] := 31; Months[8] := 31; - Months[9] := 30; Months[10] := 31; Months[11] := 30; Months[12] := 31; - - day := 0; - year := 1; - month := 1; - i := 0; - - WHILE year <= 10000 DO - DateTable[i][0] := day; - DateTable[i][1] := year; - DateTable[i][2] := month; - INC(day, Months[month]); - IF (month = 2) & ((year MOD 4 = 0) & (year MOD 100 # 0) OR (year MOD 400 = 0)) THEN - INC(day) - END; - INC(month); - IF month > 12 THEN - month := 1; - INC(year) - END; - INC(i) - END; - - MonthsTable[1][0] := 0; - FOR i := 2 TO 12 DO - MonthsTable[i][0] := MonthsTable[i - 1][0] + Months[i - 1] - END; - - FOR i := 1 TO 12 DO - MonthsTable[i][2] := Months[i] - END; - - Months[2] := 29; - MonthsTable[1][1] := 0; - FOR i := 2 TO 12 DO - MonthsTable[i][1] := MonthsTable[i - 1][1] + Months[i - 1] - END; - - FOR i := 1 TO 12 DO - MonthsTable[i][3] := Months[i] - END - -END init; - - -BEGIN - init -END DateTime. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows64/File.ob07 b/programs/develop/oberon07/Lib/Windows64/File.ob07 deleted file mode 100644 index 4e003eee35..0000000000 --- a/programs/develop/oberon07/Lib/Windows64/File.ob07 +++ /dev/null @@ -1,139 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2019-2020, Anton Krotov - All rights reserved. -*) - -MODULE File; - -IMPORT SYSTEM, WINAPI, API; - - -CONST - - OPEN_R* = 0; OPEN_W* = 1; OPEN_RW* = 2; - SEEK_BEG* = 0; SEEK_CUR* = 1; SEEK_END* = 2; - - -PROCEDURE Exists* (FName: ARRAY OF CHAR): BOOLEAN; -VAR - FindData: WINAPI.TWin32FindData; - Handle: INTEGER; - attr: SET; - -BEGIN - Handle := WINAPI.FindFirstFileA(SYSTEM.ADR(FName[0]), FindData); - IF Handle # -1 THEN - WINAPI.FindClose(Handle); - SYSTEM.GET32(SYSTEM.ADR(FindData.dwFileAttributes), attr); - IF 4 IN attr THEN - Handle := -1 - END - END - - RETURN Handle # -1 -END Exists; - - -PROCEDURE Delete* (FName: ARRAY OF CHAR): BOOLEAN; - RETURN WINAPI.DeleteFileA(SYSTEM.ADR(FName[0])) # 0 -END Delete; - - -PROCEDURE Create* (FName: ARRAY OF CHAR): INTEGER; - RETURN WINAPI.CreateFileA(SYSTEM.ADR(FName[0]), 0C0000000H, 0, NIL, 2, 80H, 0) -END Create; - - -PROCEDURE Close* (F: INTEGER); -BEGIN - WINAPI.CloseHandle(F) -END Close; - - -PROCEDURE Open* (FName: ARRAY OF CHAR; Mode: INTEGER): INTEGER; -VAR - ofstr: WINAPI.OFSTRUCT; -BEGIN - RETURN WINAPI.OpenFile(SYSTEM.ADR(FName[0]), ofstr, Mode) -END Open; - - -PROCEDURE Seek* (F, Offset, Origin: INTEGER): INTEGER; - RETURN WINAPI.SetFilePointer(F, Offset MOD 100000000H, SYSTEM.ADR(Offset) + 4, Origin) -END Seek; - - -PROCEDURE Read* (F, Buffer, Count: INTEGER): INTEGER; -VAR - res: INTEGER; - -BEGIN - IF WINAPI.ReadFile(F, Buffer, Count, SYSTEM.ADR(res), NIL) = 0 THEN - res := -1 - END - - RETURN res -END Read; - - -PROCEDURE Write* (F, Buffer, Count: INTEGER): INTEGER; -VAR - res: INTEGER; - -BEGIN - IF WINAPI.WriteFile(F, Buffer, Count, SYSTEM.ADR(res), NIL) = 0 THEN - res := -1 - END - - RETURN res -END Write; - - -PROCEDURE Load* (FName: ARRAY OF CHAR; VAR Size: INTEGER): INTEGER; -VAR - res, n, F: INTEGER; - -BEGIN - res := 0; - F := Open(FName, OPEN_R); - - IF F # -1 THEN - Size := Seek(F, 0, SEEK_END); - n := Seek(F, 0, SEEK_BEG); - res := API._NEW(Size); - IF (res = 0) OR (Read(F, res, Size) # Size) THEN - IF res # 0 THEN - res := API._DISPOSE(res); - Size := 0 - END - END; - Close(F) - END - - RETURN res -END Load; - - -PROCEDURE RemoveDir* (DirName: ARRAY OF CHAR): BOOLEAN; - RETURN WINAPI.RemoveDirectoryA(SYSTEM.ADR(DirName[0])) # 0 -END RemoveDir; - - -PROCEDURE ExistsDir* (DirName: ARRAY OF CHAR): BOOLEAN; -VAR - Code: SET; - -BEGIN - Code := WINAPI.GetFileAttributesA(SYSTEM.ADR(DirName[0])) - RETURN (Code # {0..31}) & (4 IN Code) -END ExistsDir; - - -PROCEDURE CreateDir* (DirName: ARRAY OF CHAR): BOOLEAN; - RETURN WINAPI.CreateDirectoryA(SYSTEM.ADR(DirName[0]), NIL) # 0 -END CreateDir; - - -END File. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows64/HOST.ob07 b/programs/develop/oberon07/Lib/Windows64/HOST.ob07 deleted file mode 100644 index 20301868c9..0000000000 --- a/programs/develop/oberon07/Lib/Windows64/HOST.ob07 +++ /dev/null @@ -1,339 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018-2020, Anton Krotov - All rights reserved. -*) - -MODULE HOST; - -IMPORT SYSTEM, RTL; - - -CONST - - slash* = "\"; - eol* = 0DX + 0AX; - - bit_depth* = RTL.bit_depth; - maxint* = RTL.maxint; - minint* = RTL.minint; - - MAX_PARAM = 1024; - - OFS_MAXPATHNAME = 128; - - -TYPE - - POverlapped = POINTER TO OVERLAPPED; - - OVERLAPPED = RECORD - - Internal: INTEGER; - InternalHigh: INTEGER; - Offset: INTEGER; - OffsetHigh: INTEGER; - hEvent: INTEGER - - END; - - OFSTRUCT = RECORD - - cBytes: CHAR; - fFixedDisk: CHAR; - nErrCode: WCHAR; - Reserved1: WCHAR; - Reserved2: WCHAR; - szPathName: ARRAY OFS_MAXPATHNAME OF CHAR - - END; - - PSecurityAttributes = POINTER TO TSecurityAttributes; - - TSecurityAttributes = RECORD - - nLength: INTEGER; - lpSecurityDescriptor: INTEGER; - bInheritHandle: INTEGER - - END; - - -VAR - - hConsoleOutput: INTEGER; - - Params: ARRAY MAX_PARAM, 2 OF INTEGER; - argc: INTEGER; - - maxreal*: REAL; - - -PROCEDURE [windows-, "kernel32.dll", "GetTickCount"] - _GetTickCount (): INTEGER; - -PROCEDURE [windows-, "kernel32.dll", "GetStdHandle"] - _GetStdHandle (nStdHandle: INTEGER): INTEGER; - -PROCEDURE [windows-, "kernel32.dll", "GetCommandLineA"] - _GetCommandLine (): INTEGER; - -PROCEDURE [windows-, "kernel32.dll", "ReadFile"] - _ReadFile (hFile, Buffer, nNumberOfBytesToRW: INTEGER; VAR NumberOfBytesRW: INTEGER; lpOverlapped: POverlapped): INTEGER; - -PROCEDURE [windows-, "kernel32.dll", "WriteFile"] - _WriteFile (hFile, Buffer, nNumberOfBytesToRW: INTEGER; VAR NumberOfBytesRW: INTEGER; lpOverlapped: POverlapped): INTEGER; - -PROCEDURE [windows-, "kernel32.dll", "CloseHandle"] - _CloseHandle (hObject: INTEGER): INTEGER; - -PROCEDURE [windows-, "kernel32.dll", "CreateFileA"] - _CreateFile ( - lpFileName, dwDesiredAccess, dwShareMode: INTEGER; - lpSecurityAttributes: PSecurityAttributes; - dwCreationDisposition, dwFlagsAndAttributes, - hTemplateFile: INTEGER): INTEGER; - -PROCEDURE [windows-, "kernel32.dll", "OpenFile"] - _OpenFile (lpFileName: INTEGER; lpReOpenBuff: OFSTRUCT; uStyle: INTEGER): INTEGER; - -PROCEDURE [windows-, "kernel32.dll", "GetCurrentDirectoryA"] - _GetCurrentDirectory (nBufferLength, lpBuffer: INTEGER): INTEGER; - -PROCEDURE [windows, "kernel32.dll", "ExitProcess"] - _ExitProcess (code: INTEGER); - -PROCEDURE [windows, "msvcrt.dll", "time"] - _time (ptr: INTEGER): INTEGER; - - -PROCEDURE ExitProcess* (code: INTEGER); -BEGIN - _ExitProcess(code) -END ExitProcess; - - -PROCEDURE GetCurrentDirectory* (VAR path: ARRAY OF CHAR); -VAR - n: INTEGER; - -BEGIN - n := _GetCurrentDirectory(LEN(path), SYSTEM.ADR(path[0])); - path[n] := slash; - path[n + 1] := 0X -END GetCurrentDirectory; - - -PROCEDURE GetChar (adr: INTEGER): CHAR; -VAR - res: CHAR; - -BEGIN - SYSTEM.GET(adr, res) - RETURN res -END GetChar; - - -PROCEDURE ParamParse; -VAR - p, count, cond: INTEGER; - c: CHAR; - - - PROCEDURE ChangeCond (A, B, C: INTEGER; VAR cond: INTEGER; c: CHAR); - BEGIN - IF (c <= 20X) & (c # 0X) THEN - cond := A - ELSIF c = 22X THEN - cond := B - ELSIF c = 0X THEN - cond := 6 - ELSE - cond := C - END - END ChangeCond; - - -BEGIN - p := _GetCommandLine(); - cond := 0; - count := 0; - WHILE (count < MAX_PARAM) & (cond # 6) DO - c := GetChar(p); - CASE cond OF - |0: ChangeCond(0, 4, 1, cond, c); IF cond = 1 THEN Params[count, 0] := p END - |1: ChangeCond(0, 3, 1, cond, c); IF cond IN {0, 6} THEN Params[count, 1] := p - 1; INC(count) END - |3: ChangeCond(3, 1, 3, cond, c); IF cond = 6 THEN Params[count, 1] := p - 1; INC(count) END - |4: ChangeCond(5, 0, 5, cond, c); IF cond = 5 THEN Params[count, 0] := p END - |5: ChangeCond(5, 1, 5, cond, c); IF cond = 6 THEN Params[count, 1] := p - 1; INC(count) END - |6: - END; - INC(p) - END; - argc := count -END ParamParse; - - -PROCEDURE GetArg* (n: INTEGER; VAR s: ARRAY OF CHAR); -VAR - i, j, len: INTEGER; - c: CHAR; - -BEGIN - j := 0; - IF n < argc THEN - len := LEN(s) - 1; - i := Params[n, 0]; - WHILE (j < len) & (i <= Params[n, 1]) DO - c := GetChar(i); - IF c # 22X THEN - s[j] := c; - INC(j) - END; - INC(i) - END - END; - s[j] := 0X -END GetArg; - - -PROCEDURE FileRead* (F: INTEGER; VAR Buffer: ARRAY OF CHAR; bytes: INTEGER): INTEGER; -VAR - res: INTEGER; - -BEGIN - IF _ReadFile(F, SYSTEM.ADR(Buffer[0]), bytes, res, NIL) = 0 THEN - res := -1 - END - - RETURN res -END FileRead; - - -PROCEDURE FileWrite* (F: INTEGER; Buffer: ARRAY OF BYTE; bytes: INTEGER): INTEGER; -VAR - res: INTEGER; - -BEGIN - IF _WriteFile(F, SYSTEM.ADR(Buffer[0]), bytes, res, NIL) = 0 THEN - res := -1 - END - - RETURN res -END FileWrite; - - -PROCEDURE FileCreate* (FName: ARRAY OF CHAR): INTEGER; - RETURN _CreateFile(SYSTEM.ADR(FName[0]), 0C0000000H, 0, NIL, 2, 80H, 0) -END FileCreate; - - -PROCEDURE FileClose* (F: INTEGER); -BEGIN - _CloseHandle(F) -END FileClose; - - -PROCEDURE FileOpen* (FName: ARRAY OF CHAR): INTEGER; -VAR - ofstr: OFSTRUCT; - res: INTEGER; - -BEGIN - res := _OpenFile(SYSTEM.ADR(FName[0]), ofstr, 0); - IF res = 0FFFFFFFFH THEN - res := -1 - END - - RETURN res -END FileOpen; - - -PROCEDURE chmod* (FName: ARRAY OF CHAR); -END chmod; - - -PROCEDURE OutChar* (c: CHAR); -VAR - count: INTEGER; -BEGIN - _WriteFile(hConsoleOutput, SYSTEM.ADR(c), 1, count, NIL) -END OutChar; - - -PROCEDURE GetTickCount* (): INTEGER; - RETURN _GetTickCount() DIV 10 -END GetTickCount; - - -PROCEDURE letter (c: CHAR): BOOLEAN; - RETURN ("a" <= c) & (c <= "z") OR ("A" <= c) & (c <= "Z") -END letter; - - -PROCEDURE isRelative* (path: ARRAY OF CHAR): BOOLEAN; - RETURN ~(letter(path[0]) & (path[1] = ":")) -END isRelative; - - -PROCEDURE UnixTime* (): INTEGER; - RETURN _time(0) -END UnixTime; - - -PROCEDURE splitf* (x: REAL; VAR a, b: INTEGER): INTEGER; -VAR - res: INTEGER; - -BEGIN - a := 0; - b := 0; - SYSTEM.GET32(SYSTEM.ADR(x), a); - SYSTEM.GET32(SYSTEM.ADR(x) + 4, b); - SYSTEM.GET(SYSTEM.ADR(x), res) - RETURN res -END splitf; - - -PROCEDURE d2s* (x: REAL): INTEGER; -VAR - h, l, s, e: INTEGER; - -BEGIN - e := splitf(x, l, h); - - s := ASR(h, 31) MOD 2; - e := (h DIV 100000H) MOD 2048; - IF e <= 896 THEN - h := (h MOD 100000H) * 8 + (l DIV 20000000H) MOD 8 + 800000H; - REPEAT - h := h DIV 2; - INC(e) - UNTIL e = 897; - e := 896; - l := (h MOD 8) * 20000000H; - h := h DIV 8 - ELSIF (1151 <= e) & (e < 2047) THEN - e := 1151; - h := 0; - l := 0 - ELSIF e = 2047 THEN - e := 1151; - IF (h MOD 100000H # 0) OR (BITS(l) * {0..31} # {}) THEN - h := 80000H; - l := 0 - END - END; - DEC(e, 896) - - RETURN LSL(s, 31) + LSL(e, 23) + (h MOD 100000H) * 8 + (l DIV 20000000H) MOD 8 -END d2s; - - -BEGIN - maxreal := 1.9; - PACK(maxreal, 1023); - hConsoleOutput := _GetStdHandle(-11); - ParamParse -END HOST. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows64/In.ob07 b/programs/develop/oberon07/Lib/Windows64/In.ob07 deleted file mode 100644 index 1e2b21f573..0000000000 --- a/programs/develop/oberon07/Lib/Windows64/In.ob07 +++ /dev/null @@ -1,80 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2020, Anton Krotov - All rights reserved. -*) - -MODULE In; - -IMPORT SYSTEM; - - -CONST - - MAX_LEN = 1024; - - -VAR - - Done*: BOOLEAN; - hConsoleInput: INTEGER; - s: ARRAY MAX_LEN + 4 OF CHAR; - - -PROCEDURE [windows, "msvcrt.dll", ""] sscanf (buf: INTEGER; fmt: INTEGER; adr: INTEGER): INTEGER; -PROCEDURE [windows, "kernel32.dll", ""] GetStdHandle (nStdHandle: INTEGER): INTEGER; -PROCEDURE [windows, "kernel32.dll", ""] ReadConsoleA (hConsoleInput, lpBuffer, nNumberOfCharsToRead, lpNumberOfCharsRead, lpReserved: INTEGER); - - -PROCEDURE String* (VAR str: ARRAY OF CHAR); -VAR - count: INTEGER; - -BEGIN - ReadConsoleA(hConsoleInput, SYSTEM.ADR(s[0]), MAX_LEN, SYSTEM.ADR(count), 0); - IF (s[count - 1] = 0AX) & (s[count - 2] = 0DX) THEN - DEC(count, 2) - END; - s[count] := 0X; - COPY(s, str); - str[LEN(str) - 1] := 0X; - Done := TRUE -END String; - - -PROCEDURE Int* (VAR x: INTEGER); -BEGIN - String(s); - Done := sscanf(SYSTEM.ADR(s[0]), SYSTEM.SADR("%lld"), SYSTEM.ADR(x)) = 1 -END Int; - - -PROCEDURE Real* (VAR x: REAL); -BEGIN - String(s); - Done := sscanf(SYSTEM.ADR(s[0]), SYSTEM.SADR("%lf"), SYSTEM.ADR(x)) = 1 -END Real; - - -PROCEDURE Char* (VAR x: CHAR); -BEGIN - String(s); - x := s[0] -END Char; - - -PROCEDURE Ln*; -BEGIN - String(s) -END Ln; - - -PROCEDURE Open*; -BEGIN - hConsoleInput := GetStdHandle(-10); - Done := TRUE -END Open; - - -END In. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows64/Math.ob07 b/programs/develop/oberon07/Lib/Windows64/Math.ob07 deleted file mode 100644 index 42a5de5e7e..0000000000 --- a/programs/develop/oberon07/Lib/Windows64/Math.ob07 +++ /dev/null @@ -1,480 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2019-2020, Anton Krotov - All rights reserved. -*) - -MODULE Math; - -IMPORT SYSTEM; - - -CONST - - pi* = 3.1415926535897932384626433832795028841972E0; - e* = 2.7182818284590452353602874713526624977572E0; - - ZERO = 0.0E0; - ONE = 1.0E0; - HALF = 0.5E0; - TWO = 2.0E0; - sqrtHalf = 0.70710678118654752440E0; - eps = 5.5511151E-17; - ln2Inv = 1.44269504088896340735992468100189213E0; - piInv = ONE / pi; - Limit = 1.0536712E-8; - piByTwo = pi / TWO; - - expoMax = 1023; - expoMin = 1 - expoMax; - - -VAR - - LnInfinity, LnSmall, large, miny: REAL; - - -PROCEDURE [stdcall64] sqrt* (x: REAL): REAL; -BEGIN - ASSERT(x >= ZERO); - SYSTEM.CODE( - 0F2H, 0FH, 51H, 45H, 10H, (* sqrtsd xmm0, qword[rbp + 10h] *) - 05DH, (* pop rbp *) - 0C2H, 08H, 00H (* ret 8 *) - ) - - RETURN 0.0 -END sqrt; - - -PROCEDURE sqri* (x: INTEGER): INTEGER; - RETURN x * x -END sqri; - - -PROCEDURE sqrr* (x: REAL): REAL; - RETURN x * x -END sqrr; - - -PROCEDURE exp* (x: REAL): REAL; -CONST - c1 = 0.693359375E0; - c2 = -2.1219444005469058277E-4; - P0 = 0.249999999999999993E+0; - P1 = 0.694360001511792852E-2; - P2 = 0.165203300268279130E-4; - Q1 = 0.555538666969001188E-1; - Q2 = 0.495862884905441294E-3; - -VAR - xn, g, p, q, z: REAL; - n: INTEGER; - -BEGIN - IF x > LnInfinity THEN - x := SYSTEM.INF() - ELSIF x < LnSmall THEN - x := ZERO - ELSIF ABS(x) < eps THEN - x := ONE - ELSE - IF x >= ZERO THEN - n := FLOOR(ln2Inv * x + HALF) - ELSE - n := FLOOR(ln2Inv * x - HALF) - END; - - xn := FLT(n); - g := (x - xn * c1) - xn * c2; - z := g * g; - p := ((P2 * z + P1) * z + P0) * g; - q := (Q2 * z + Q1) * z + HALF; - x := HALF + p / (q - p); - PACK(x, n + 1) - END - - RETURN x -END exp; - - -PROCEDURE ln* (x: REAL): REAL; -CONST - c1 = 355.0E0 / 512.0E0; - c2 = -2.121944400546905827679E-4; - P0 = -0.64124943423745581147E+2; - P1 = 0.16383943563021534222E+2; - P2 = -0.78956112887491257267E+0; - Q0 = -0.76949932108494879777E+3; - Q1 = 0.31203222091924532844E+3; - Q2 = -0.35667977739034646171E+2; - -VAR - zn, zd, r, z, w, p, q, xn: REAL; - n: INTEGER; - -BEGIN - ASSERT(x > ZERO); - - UNPK(x, n); - x := x * HALF; - - IF x > sqrtHalf THEN - zn := x - ONE; - zd := x * HALF + HALF; - INC(n) - ELSE - zn := x - HALF; - zd := zn * HALF + HALF - END; - - z := zn / zd; - w := z * z; - q := ((w + Q2) * w + Q1) * w + Q0; - p := w * ((P2 * w + P1) * w + P0); - r := z + z * (p / q); - xn := FLT(n) - - RETURN (xn * c2 + r) + xn * c1 -END ln; - - -PROCEDURE power* (base, exponent: REAL): REAL; -BEGIN - ASSERT(base > ZERO) - RETURN exp(exponent * ln(base)) -END power; - - -PROCEDURE ipower* (base: REAL; exponent: INTEGER): REAL; -VAR - i: INTEGER; - a: REAL; - -BEGIN - a := 1.0; - - IF base # 0.0 THEN - IF exponent # 0 THEN - IF exponent < 0 THEN - base := 1.0 / base - END; - i := ABS(exponent); - WHILE i > 0 DO - WHILE ~ODD(i) DO - i := LSR(i, 1); - base := sqrr(base) - END; - DEC(i); - a := a * base - END - ELSE - a := 1.0 - END - ELSE - ASSERT(exponent > 0); - a := 0.0 - END - - RETURN a -END ipower; - - -PROCEDURE log* (base, x: REAL): REAL; -BEGIN - ASSERT(base > ZERO); - ASSERT(x > ZERO) - RETURN ln(x) / ln(base) -END log; - - -PROCEDURE SinCos (x, y, sign: REAL): REAL; -CONST - ymax = 210828714; - c1 = 3.1416015625E0; - c2 = -8.908910206761537356617E-6; - r1 = -0.16666666666666665052E+0; - r2 = 0.83333333333331650314E-2; - r3 = -0.19841269841201840457E-3; - r4 = 0.27557319210152756119E-5; - r5 = -0.25052106798274584544E-7; - r6 = 0.16058936490371589114E-9; - r7 = -0.76429178068910467734E-12; - r8 = 0.27204790957888846175E-14; - -VAR - n: INTEGER; - xn, f, x1, g: REAL; - -BEGIN - ASSERT(y < FLT(ymax)); - - n := FLOOR(y * piInv + HALF); - xn := FLT(n); - IF ODD(n) THEN - sign := -sign - END; - x := ABS(x); - IF x # y THEN - xn := xn - HALF - END; - - x1 := FLT(FLOOR(x)); - f := ((x1 - xn * c1) + (x - x1)) - xn * c2; - - IF ABS(f) < Limit THEN - x := sign * f - ELSE - g := f * f; - g := (((((((r8 * g + r7) * g + r6) * g + r5) * g + r4) * g + r3) * g + r2) * g + r1) * g; - g := f + f * g; - x := sign * g - END - - RETURN x -END SinCos; - - -PROCEDURE sin* (x: REAL): REAL; -BEGIN - IF x < ZERO THEN - x := SinCos(x, -x, -ONE) - ELSE - x := SinCos(x, x, ONE) - END - - RETURN x -END sin; - - -PROCEDURE cos* (x: REAL): REAL; - RETURN SinCos(x, ABS(x) + piByTwo, ONE) -END cos; - - -PROCEDURE tan* (x: REAL): REAL; -VAR - s, c: REAL; - -BEGIN - s := sin(x); - c := sqrt(ONE - s * s); - x := ABS(x) / (TWO * pi); - x := x - FLT(FLOOR(x)); - IF (0.25 < x) & (x < 0.75) THEN - c := -c - END - - RETURN s / c -END tan; - - -PROCEDURE arctan2* (y, x: REAL): REAL; -CONST - P0 = 0.216062307897242551884E+3; P1 = 0.3226620700132512059245E+3; - P2 = 0.13270239816397674701E+3; P3 = 0.1288838303415727934E+2; - Q0 = 0.2160623078972426128957E+3; Q1 = 0.3946828393122829592162E+3; - Q2 = 0.221050883028417680623E+3; Q3 = 0.3850148650835119501E+2; - Sqrt3 = 1.7320508075688772935E0; - -VAR - atan, z, z2, p, q: REAL; - yExp, xExp, Quadrant: INTEGER; - -BEGIN - IF ABS(x) < miny THEN - ASSERT(ABS(y) >= miny); - atan := piByTwo - ELSE - z := y; - UNPK(z, yExp); - z := x; - UNPK(z, xExp); - - IF yExp - xExp >= expoMax - 3 THEN - atan := piByTwo - ELSIF yExp - xExp < expoMin + 3 THEN - atan := ZERO - ELSE - IF ABS(y) > ABS(x) THEN - z := ABS(x / y); - Quadrant := 2 - ELSE - z := ABS(y / x); - Quadrant := 0 - END; - - IF z > TWO - Sqrt3 THEN - z := (z * Sqrt3 - ONE) / (Sqrt3 + z); - INC(Quadrant) - END; - - IF ABS(z) < Limit THEN - atan := z - ELSE - z2 := z * z; - p := (((P3 * z2 + P2) * z2 + P1) * z2 + P0) * z; - q := (((z2 + Q3) * z2 + Q2) * z2 + Q1) * z2 + Q0; - atan := p / q - END; - - CASE Quadrant OF - |0: - |1: atan := atan + pi / 6.0 - |2: atan := piByTwo - atan - |3: atan := pi / 3.0 - atan - END - END; - - IF x < ZERO THEN - atan := pi - atan - END - END; - - IF y < ZERO THEN - atan := -atan - END - - RETURN atan -END arctan2; - - -PROCEDURE arcsin* (x: REAL): REAL; -BEGIN - ASSERT(ABS(x) <= ONE) - RETURN arctan2(x, sqrt(ONE - x * x)) -END arcsin; - - -PROCEDURE arccos* (x: REAL): REAL; -BEGIN - ASSERT(ABS(x) <= ONE) - RETURN arctan2(sqrt(ONE - x * x), x) -END arccos; - - -PROCEDURE arctan* (x: REAL): REAL; - RETURN arctan2(x, ONE) -END arctan; - - -PROCEDURE sinh* (x: REAL): REAL; -BEGIN - x := exp(x) - RETURN (x - ONE / x) * HALF -END sinh; - - -PROCEDURE cosh* (x: REAL): REAL; -BEGIN - x := exp(x) - RETURN (x + ONE / x) * HALF -END cosh; - - -PROCEDURE tanh* (x: REAL): REAL; -BEGIN - IF x > 15.0 THEN - x := ONE - ELSIF x < -15.0 THEN - x := -ONE - ELSE - x := exp(TWO * x); - x := (x - ONE) / (x + ONE) - END - - RETURN x -END tanh; - - -PROCEDURE arsinh* (x: REAL): REAL; - RETURN ln(x + sqrt(x * x + ONE)) -END arsinh; - - -PROCEDURE arcosh* (x: REAL): REAL; -BEGIN - ASSERT(x >= ONE) - RETURN ln(x + sqrt(x * x - ONE)) -END arcosh; - - -PROCEDURE artanh* (x: REAL): REAL; -BEGIN - ASSERT(ABS(x) < ONE) - RETURN HALF * ln((ONE + x) / (ONE - x)) -END artanh; - - -PROCEDURE sgn* (x: REAL): INTEGER; -VAR - res: INTEGER; - -BEGIN - IF x > ZERO THEN - res := 1 - ELSIF x < ZERO THEN - res := -1 - ELSE - res := 0 - END - - RETURN res -END sgn; - - -PROCEDURE fact* (n: INTEGER): REAL; -VAR - res: REAL; - -BEGIN - res := ONE; - WHILE n > 1 DO - res := res * FLT(n); - DEC(n) - END - - RETURN res -END fact; - - -PROCEDURE DegToRad* (x: REAL): REAL; - RETURN x * (pi / 180.0) -END DegToRad; - - -PROCEDURE RadToDeg* (x: REAL): REAL; - RETURN x * (180.0 / pi) -END RadToDeg; - - -(* Return hypotenuse of triangle *) -PROCEDURE hypot* (x, y: REAL): REAL; -VAR - a: REAL; - -BEGIN - x := ABS(x); - y := ABS(y); - IF x > y THEN - a := x * sqrt(1.0 + sqrr(y / x)) - ELSE - IF x > 0.0 THEN - a := y * sqrt(1.0 + sqrr(x / y)) - ELSE - a := y - END - END - - RETURN a -END hypot; - - -BEGIN - large := 1.9; - PACK(large, expoMax); - miny := ONE / large; - LnInfinity := ln(large); - LnSmall := ln(miny); -END Math. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows64/Out.ob07 b/programs/develop/oberon07/Lib/Windows64/Out.ob07 deleted file mode 100644 index 3903c11174..0000000000 --- a/programs/develop/oberon07/Lib/Windows64/Out.ob07 +++ /dev/null @@ -1,86 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2020, Anton Krotov - All rights reserved. -*) - -MODULE Out; - -IMPORT SYSTEM; - - -VAR - - hConsoleOutput: INTEGER; - -PROCEDURE [windows, "msvcrt.dll", "printf"] printf1 (fmt: INTEGER; x: INTEGER); -PROCEDURE [windows, "msvcrt.dll", "printf"] printf2 (fmt: INTEGER; width, x: INTEGER); -PROCEDURE [windows, "msvcrt.dll", "printf"] printf3 (fmt: INTEGER; width, precision, x: INTEGER); - -PROCEDURE [windows, "kernel32.dll", ""] - WriteConsoleW (hConsoleOutput, lpBuffer, nNumberOfCharsToWrite, lpNumberOfCharsWritten, lpReserved: INTEGER); - -PROCEDURE [windows, "kernel32.dll", ""] - GetStdHandle (nStdHandle: INTEGER): INTEGER; - - -PROCEDURE Char* (x: CHAR); -BEGIN - printf1(SYSTEM.SADR("%c"), ORD(x)) -END Char; - - -PROCEDURE StringW* (s: ARRAY OF WCHAR); -BEGIN - WriteConsoleW(hConsoleOutput, SYSTEM.ADR(s[0]), LENGTH(s), 0, 0) -END StringW; - - -PROCEDURE String* (s: ARRAY OF CHAR); -BEGIN - printf2(SYSTEM.SADR("%.*s"), LENGTH(s), SYSTEM.ADR(s[0])) -END String; - - -PROCEDURE Ln*; -BEGIN - printf1(SYSTEM.SADR("%s"), SYSTEM.SADR(CHR(13) + CHR(10))) -END Ln; - - -PROCEDURE Int* (x, width: INTEGER); -BEGIN - printf2(SYSTEM.SADR("%*lld"), width, x) -END Int; - - -PROCEDURE intval (x: REAL): INTEGER; -VAR - i: INTEGER; - -BEGIN - SYSTEM.GET(SYSTEM.ADR(x), i) - RETURN i -END intval; - - -PROCEDURE Real* (x: REAL; width: INTEGER); -BEGIN - printf3(SYSTEM.SADR("%*.*E"), width, MAX(MIN(width - 8, 15), 1), intval(x)) -END Real; - - -PROCEDURE FixReal* (x: REAL; width, precision: INTEGER); -BEGIN - printf3(SYSTEM.SADR("%*.*f"), width, precision, intval(x)) -END FixReal; - - -PROCEDURE Open*; -BEGIN - hConsoleOutput := GetStdHandle(-11) -END Open; - - -END Out. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows64/RTL.ob07 b/programs/develop/oberon07/Lib/Windows64/RTL.ob07 deleted file mode 100644 index 7b6bbfb6a7..0000000000 --- a/programs/develop/oberon07/Lib/Windows64/RTL.ob07 +++ /dev/null @@ -1,503 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2018-2020, Anton Krotov - All rights reserved. -*) - -MODULE RTL; - -IMPORT SYSTEM, API; - - -CONST - - bit_depth* = 64; - maxint* = 7FFFFFFFFFFFFFFFH; - minint* = 8000000000000000H; - - WORD = bit_depth DIV 8; - MAX_SET = bit_depth - 1; - - -VAR - - name: INTEGER; - types: INTEGER; - sets: ARRAY (MAX_SET + 1) * (MAX_SET + 1) OF INTEGER; - - -PROCEDURE [stdcall64] _move* (bytes, dest, source: INTEGER); -BEGIN - SYSTEM.CODE( - 048H, 08BH, 045H, 010H, (* mov rax, qword [rbp + 16] *) - 048H, 085H, 0C0H, (* test rax, rax *) - 07EH, 020H, (* jle L *) - 0FCH, (* cld *) - 057H, (* push rdi *) - 056H, (* push rsi *) - 048H, 08BH, 075H, 020H, (* mov rsi, qword [rbp + 32] *) - 048H, 08BH, 07DH, 018H, (* mov rdi, qword [rbp + 24] *) - 048H, 089H, 0C1H, (* mov rcx, rax *) - 048H, 0C1H, 0E9H, 003H, (* shr rcx, 3 *) - 0F3H, 048H, 0A5H, (* rep movsd *) - 048H, 089H, 0C1H, (* mov rcx, rax *) - 048H, 083H, 0E1H, 007H, (* and rcx, 7 *) - 0F3H, 0A4H, (* rep movsb *) - 05EH, (* pop rsi *) - 05FH (* pop rdi *) - (* L: *) - ) -END _move; - - -PROCEDURE [stdcall64] _arrcpy* (base_size, len_dst, dst, len_src, src: INTEGER): BOOLEAN; -VAR - res: BOOLEAN; - -BEGIN - IF len_src > len_dst THEN - res := FALSE - ELSE - _move(len_src * base_size, dst, src); - res := TRUE - END - - RETURN res -END _arrcpy; - - -PROCEDURE [stdcall64] _strcpy* (chr_size, len_src, src, len_dst, dst: INTEGER); -BEGIN - _move(MIN(len_dst, len_src) * chr_size, dst, src) -END _strcpy; - - -PROCEDURE [stdcall64] _rot* (VAR A: ARRAY OF INTEGER); -VAR - i, n, k: INTEGER; - -BEGIN - k := LEN(A) - 1; - n := A[0]; - i := 0; - WHILE i < k DO - A[i] := A[i + 1]; - INC(i) - END; - A[k] := n -END _rot; - - -PROCEDURE [stdcall64] _set* (b, a: INTEGER): INTEGER; -BEGIN - IF (a <= b) & (a <= MAX_SET) & (b >= 0) THEN - SYSTEM.GET((MIN(b, MAX_SET) * (MAX_SET + 1) + MAX(a, 0)) * WORD + SYSTEM.ADR(sets[0]), a) - ELSE - a := 0 - END - - RETURN a -END _set; - - -PROCEDURE [stdcall64] _set1* (a: INTEGER); (* {a} -> rax *) -BEGIN - SYSTEM.CODE( - 048H, 031H, 0C0H, (* xor rax, rax *) - 048H, 08BH, 04DH, 010H, (* mov rcx, qword [rbp + 16] *) (* rcx <- a *) - 048H, 083H, 0F9H, 03FH, (* cmp rcx, 63 *) - 077H, 004H, (* ja L *) - 048H, 00FH, 0ABH, 0C8H (* bts rax, rcx *) - (* L: *) - ) -END _set1; - - -PROCEDURE [stdcall64] _divmod* (y, x: INTEGER); (* (x div y) -> rax; (x mod y) -> rdx *) -BEGIN - SYSTEM.CODE( - 048H, 08BH, 045H, 018H, (* mov rax, qword [rbp + 24] *) (* rax <- x *) - 048H, 031H, 0D2H, (* xor rdx, rdx *) - 048H, 085H, 0C0H, (* test rax, rax *) - 074H, 022H, (* je L2 *) - 07FH, 003H, (* jg L1 *) - 048H, 0F7H, 0D2H, (* not rdx *) - (* L1: *) - 049H, 089H, 0C0H, (* mov r8, rax *) - 048H, 08BH, 04DH, 010H, (* mov rcx, qword [rbp + 16] *) (* rcx <- y *) - 048H, 0F7H, 0F9H, (* idiv rcx *) - 048H, 085H, 0D2H, (* test rdx, rdx *) - 074H, 00EH, (* je L2 *) - 049H, 031H, 0C8H, (* xor r8, rcx *) - 04DH, 085H, 0C0H, (* test r8, r8 *) - 07DH, 006H, (* jge L2 *) - 048H, 0FFH, 0C8H, (* dec rax *) - 048H, 001H, 0CAH (* add rdx, rcx *) - (* L2: *) - ) -END _divmod; - - -PROCEDURE [stdcall64] _new* (t, size: INTEGER; VAR ptr: INTEGER); -BEGIN - ptr := API._NEW(size); - IF ptr # 0 THEN - SYSTEM.PUT(ptr, t); - INC(ptr, WORD) - END -END _new; - - -PROCEDURE [stdcall64] _dispose* (VAR ptr: INTEGER); -BEGIN - IF ptr # 0 THEN - ptr := API._DISPOSE(ptr - WORD) - END -END _dispose; - - -PROCEDURE [stdcall64] _length* (len, str: INTEGER); -BEGIN - SYSTEM.CODE( - 048H, 08BH, 045H, 018H, (* mov rax, qword [rbp + 24] *) - 048H, 08BH, 04DH, 010H, (* mov rcx, qword [rbp + 16] *) - 048H, 0FFH, 0C8H, (* dec rax *) - (* L1: *) - 048H, 0FFH, 0C0H, (* inc rax *) - 080H, 038H, 000H, (* cmp byte [rax], 0 *) - 074H, 005H, (* jz L2 *) - 0E2H, 0F6H, (* loop L1 *) - 048H, 0FFH, 0C0H, (* inc rax *) - (* L2: *) - 048H, 02BH, 045H, 018H (* sub rax, qword [rbp + 24] *) - ) -END _length; - - -PROCEDURE [stdcall64] _lengthw* (len, str: INTEGER); -BEGIN - SYSTEM.CODE( - 048H, 08BH, 045H, 018H, (* mov rax, qword [rbp + 24] *) - 048H, 08BH, 04DH, 010H, (* mov rcx, qword [rbp + 16] *) - 048H, 083H, 0E8H, 002H, (* sub rax, 2 *) - (* L1: *) - 048H, 083H, 0C0H, 002H, (* add rax, 2 *) - 066H, 083H, 038H, 000H, (* cmp word [rax], 0 *) - 074H, 006H, (* jz L2 *) - 0E2H, 0F4H, (* loop L1 *) - 048H, 083H, 0C0H, 002H, (* add rax, 2 *) - (* L2: *) - 048H, 02BH, 045H, 018H, (* sub rax, qword [rbp + 24] *) - 048H, 0D1H, 0E8H (* shr rax, 1 *) - ) -END _lengthw; - - -PROCEDURE [stdcall64] strncmp (a, b, n: INTEGER): INTEGER; -BEGIN - SYSTEM.CODE( - 048H, 08BH, 04DH, 010H, (* mov rcx, qword[rbp + 16]; rcx <- a *) - 048H, 08BH, 055H, 018H, (* mov rdx, qword[rbp + 24]; rdx <- b *) - 04CH, 08BH, 045H, 020H, (* mov r8, qword[rbp + 32]; r8 <- n *) - 04DH, 031H, 0C9H, (* xor r9, r9 *) - 04DH, 031H, 0D2H, (* xor r10, r10 *) - 048H, 0B8H, 000H, 000H, - 000H, 000H, 000H, 000H, - 000H, 080H, (* movabs rax, minint *) - (* L1: *) - 04DH, 085H, 0C0H, (* test r8, r8 *) - 07EH, 024H, (* jle L3 *) - 044H, 08AH, 009H, (* mov r9b, byte[rcx] *) - 044H, 08AH, 012H, (* mov r10b, byte[rdx] *) - 048H, 0FFH, 0C1H, (* inc rcx *) - 048H, 0FFH, 0C2H, (* inc rdx *) - 049H, 0FFH, 0C8H, (* dec r8 *) - 04DH, 039H, 0D1H, (* cmp r9, r10 *) - 074H, 008H, (* je L2 *) - 04CH, 089H, 0C8H, (* mov rax, r9 *) - 04CH, 029H, 0D0H, (* sub rax, r10 *) - 0EBH, 008H, (* jmp L3 *) - (* L2: *) - 04DH, 085H, 0C9H, (* test r9, r9 *) - 075H, 0DAH, (* jne L1 *) - 048H, 031H, 0C0H, (* xor rax, rax *) - (* L3: *) - 05DH, (* pop rbp *) - 0C2H, 018H, 000H (* ret 24 *) - ) - RETURN 0 -END strncmp; - - -PROCEDURE [stdcall64] strncmpw (a, b, n: INTEGER): INTEGER; -BEGIN - SYSTEM.CODE( - 048H, 08BH, 04DH, 010H, (* mov rcx, qword[rbp + 16]; rcx <- a *) - 048H, 08BH, 055H, 018H, (* mov rdx, qword[rbp + 24]; rdx <- b *) - 04CH, 08BH, 045H, 020H, (* mov r8, qword[rbp + 32]; r8 <- n *) - 04DH, 031H, 0C9H, (* xor r9, r9 *) - 04DH, 031H, 0D2H, (* xor r10, r10 *) - 048H, 0B8H, 000H, 000H, - 000H, 000H, 000H, 000H, - 000H, 080H, (* movabs rax, minint *) - (* L1: *) - 04DH, 085H, 0C0H, (* test r8, r8 *) - 07EH, 028H, (* jle L3 *) - 066H, 044H, 08BH, 009H, (* mov r9w, word[rcx] *) - 066H, 044H, 08BH, 012H, (* mov r10w, word[rdx] *) - 048H, 083H, 0C1H, 002H, (* add rcx, 2 *) - 048H, 083H, 0C2H, 002H, (* add rdx, 2 *) - 049H, 0FFH, 0C8H, (* dec r8 *) - 04DH, 039H, 0D1H, (* cmp r9, r10 *) - 074H, 008H, (* je L2 *) - 04CH, 089H, 0C8H, (* mov rax, r9 *) - 04CH, 029H, 0D0H, (* sub rax, r10 *) - 0EBH, 008H, (* jmp L3 *) - (* L2: *) - 04DH, 085H, 0C9H, (* test r9, r9 *) - 075H, 0D6H, (* jne L1 *) - 048H, 031H, 0C0H, (* xor rax, rax *) - (* L3: *) - 05DH, (* pop rbp *) - 0C2H, 018H, 000H (* ret 24 *) - ) - RETURN 0 -END strncmpw; - - -PROCEDURE [stdcall64] _strcmp* (op, len2, str2, len1, str1: INTEGER): BOOLEAN; -VAR - res: INTEGER; - bRes: BOOLEAN; - c: CHAR; - -BEGIN - res := strncmp(str1, str2, MIN(len1, len2)); - IF res = minint THEN - IF len1 > len2 THEN - SYSTEM.GET(str1 + len2, c); - res := ORD(c) - ELSIF len1 < len2 THEN - SYSTEM.GET(str2 + len1, c); - res := -ORD(c) - ELSE - res := 0 - END - END; - - CASE op OF - |0: bRes := res = 0 - |1: bRes := res # 0 - |2: bRes := res < 0 - |3: bRes := res <= 0 - |4: bRes := res > 0 - |5: bRes := res >= 0 - END - - RETURN bRes -END _strcmp; - - -PROCEDURE [stdcall64] _strcmpw* (op, len2, str2, len1, str1: INTEGER): BOOLEAN; -VAR - res: INTEGER; - bRes: BOOLEAN; - c: WCHAR; - -BEGIN - res := strncmpw(str1, str2, MIN(len1, len2)); - IF res = minint THEN - IF len1 > len2 THEN - SYSTEM.GET(str1 + len2 * 2, c); - res := ORD(c) - ELSIF len1 < len2 THEN - SYSTEM.GET(str2 + len1 * 2, c); - res := -ORD(c) - ELSE - res := 0 - END - END; - - CASE op OF - |0: bRes := res = 0 - |1: bRes := res # 0 - |2: bRes := res < 0 - |3: bRes := res <= 0 - |4: bRes := res > 0 - |5: bRes := res >= 0 - END - - RETURN bRes -END _strcmpw; - - -PROCEDURE PCharToStr (pchar: INTEGER; VAR s: ARRAY OF CHAR); -VAR - c: CHAR; - i: INTEGER; - -BEGIN - i := 0; - REPEAT - SYSTEM.GET(pchar, c); - s[i] := c; - INC(pchar); - INC(i) - UNTIL c = 0X -END PCharToStr; - - -PROCEDURE IntToStr (x: INTEGER; VAR str: ARRAY OF CHAR); -VAR - i, a: INTEGER; - -BEGIN - i := 0; - a := x; - REPEAT - INC(i); - a := a DIV 10 - UNTIL a = 0; - - str[i] := 0X; - - REPEAT - DEC(i); - str[i] := CHR(x MOD 10 + ORD("0")); - x := x DIV 10 - UNTIL x = 0 -END IntToStr; - - -PROCEDURE append (VAR s1: ARRAY OF CHAR; s2: ARRAY OF CHAR); -VAR - n1, n2: INTEGER; - -BEGIN - n1 := LENGTH(s1); - n2 := LENGTH(s2); - - ASSERT(n1 + n2 < LEN(s1)); - - SYSTEM.MOVE(SYSTEM.ADR(s2[0]), SYSTEM.ADR(s1[n1]), n2); - s1[n1 + n2] := 0X -END append; - - -PROCEDURE [stdcall64] _error* (modnum, _module, err, line: INTEGER); -VAR - s, temp: ARRAY 1024 OF CHAR; - -BEGIN - CASE err OF - | 1: s := "assertion failure" - | 2: s := "NIL dereference" - | 3: s := "bad divisor" - | 4: s := "NIL procedure call" - | 5: s := "type guard error" - | 6: s := "index out of range" - | 7: s := "invalid CASE" - | 8: s := "array assignment error" - | 9: s := "CHR out of range" - |10: s := "WCHR out of range" - |11: s := "BYTE out of range" - END; - - append(s, API.eol + "module: "); PCharToStr(_module, temp); append(s, temp); - append(s, API.eol + "line: "); IntToStr(line, temp); append(s, temp); - - API.DebugMsg(SYSTEM.ADR(s[0]), name); - - API.exit_thread(0) -END _error; - - -PROCEDURE [stdcall64] _isrec* (t0, t1, r: INTEGER): INTEGER; -BEGIN - SYSTEM.GET(t0 + t1 + types, t0) - RETURN t0 MOD 2 -END _isrec; - - -PROCEDURE [stdcall64] _is* (t0, p: INTEGER): INTEGER; -BEGIN - IF p # 0 THEN - SYSTEM.GET(p - WORD, p); - SYSTEM.GET(t0 + p + types, p) - END - - RETURN p MOD 2 -END _is; - - -PROCEDURE [stdcall64] _guardrec* (t0, t1: INTEGER): INTEGER; -BEGIN - SYSTEM.GET(t0 + t1 + types, t0) - RETURN t0 MOD 2 -END _guardrec; - - -PROCEDURE [stdcall64] _guard* (t0, p: INTEGER): INTEGER; -BEGIN - SYSTEM.GET(p, p); - IF p # 0 THEN - SYSTEM.GET(p - WORD, p); - SYSTEM.GET(t0 + p + types, p) - ELSE - p := 1 - END - - RETURN p MOD 2 -END _guard; - - -PROCEDURE [stdcall64] _dllentry* (hinstDLL, fdwReason, lpvReserved: INTEGER): INTEGER; - RETURN API.dllentry(hinstDLL, fdwReason, lpvReserved) -END _dllentry; - - -PROCEDURE [stdcall64] _sofinit*; -BEGIN - API.sofinit -END _sofinit; - - -PROCEDURE [stdcall64] _exit* (code: INTEGER); -BEGIN - API.exit(code) -END _exit; - - -PROCEDURE [stdcall64] _init* (modname: INTEGER; tcount, _types: INTEGER; code, param: INTEGER); -VAR - t0, t1, i, j: INTEGER; - -BEGIN - API.init(param, code); - - types := API._NEW(tcount * tcount + SYSTEM.SIZE(INTEGER)); - ASSERT(types # 0); - FOR i := 0 TO tcount - 1 DO - FOR j := 0 TO tcount - 1 DO - t0 := i; t1 := j; - - WHILE (t1 # 0) & (t1 # t0) DO - SYSTEM.GET(_types + t1 * WORD, t1) - END; - - SYSTEM.PUT8(i * tcount + j + types, ORD(t0 = t1)) - END - END; - - FOR i := 0 TO MAX_SET DO - FOR j := 0 TO i DO - sets[i * (MAX_SET + 1) + j] := LSR(ASR(minint, i - j), MAX_SET - i) - END - END; - - name := modname -END _init; - - -END RTL. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/Windows64/WINAPI.ob07 b/programs/develop/oberon07/Lib/Windows64/WINAPI.ob07 deleted file mode 100644 index a6337b5798..0000000000 --- a/programs/develop/oberon07/Lib/Windows64/WINAPI.ob07 +++ /dev/null @@ -1,224 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2019-2020, Anton Krotov - All rights reserved. -*) - -MODULE WINAPI; - -IMPORT SYSTEM, API; - - -CONST - - OFS_MAXPATHNAME* = 128; - - KERNEL = "kernel32.dll"; - USER = "user32.dll"; - MSVCRT = "msvcrt.dll"; - - -TYPE - - DLL_ENTRY* = API.DLL_ENTRY; - - STRING = ARRAY 260 OF CHAR; - - TCoord* = RECORD - - X*, Y*: WCHAR - - END; - - TSmallRect* = RECORD - - Left*, Top*, Right*, Bottom*: WCHAR - - END; - - TConsoleScreenBufferInfo* = RECORD - - dwSize*: TCoord; - dwCursorPosition*: TCoord; - wAttributes*: WCHAR; - srWindow*: TSmallRect; - dwMaximumWindowSize*: TCoord - - END; - - TSystemTime* = RECORD - - Year*, - Month*, - DayOfWeek*, - Day*, - Hour*, - Min*, - Sec*, - MSec*: WCHAR - - END; - - tm* = RECORD - - sec*, - min*, - hour*, - mday*, - mon*, - year*, - wday*, - yday*, - isdst*: SYSTEM.CARD32 - - END; - - PSecurityAttributes* = POINTER TO TSecurityAttributes; - - TSecurityAttributes* = RECORD - - nLength*: SYSTEM.CARD32; - lpSecurityDescriptor*: INTEGER; - bInheritHandle*: SYSTEM.CARD32 (* BOOL *) - - END; - - TFileTime* = RECORD - - dwLowDateTime*, - dwHighDateTime*: SYSTEM.CARD32 - - END; - - TWin32FindData* = RECORD - - dwFileAttributes*: SYSTEM.CARD32; - ftCreationTime*: TFileTime; - ftLastAccessTime*: TFileTime; - ftLastWriteTime*: TFileTime; - nFileSizeHigh*: SYSTEM.CARD32; - nFileSizeLow*: SYSTEM.CARD32; - dwReserved0*: SYSTEM.CARD32; - dwReserved1*: SYSTEM.CARD32; - cFileName*: STRING; - cAlternateFileName*: ARRAY 14 OF CHAR; - dwFileType*: SYSTEM.CARD32; - dwCreatorType*: SYSTEM.CARD32; - wFinderFlags*: WCHAR - - END; - - OFSTRUCT* = RECORD - - cBytes*: BYTE; - fFixedDisk*: BYTE; - nErrCode*: WCHAR; - Reserved1*: WCHAR; - Reserved2*: WCHAR; - szPathName*: ARRAY OFS_MAXPATHNAME OF CHAR - - END; - - POverlapped* = POINTER TO OVERLAPPED; - - OVERLAPPED* = RECORD - - Internal*: INTEGER; - InternalHigh*: INTEGER; - Offset*: SYSTEM.CARD32; - OffsetHigh*: SYSTEM.CARD32; - hEvent*: INTEGER - - END; - - -PROCEDURE [windows-, KERNEL, ""] SetConsoleCursorPosition* (hConsoleOutput, dwCursorPosition: INTEGER): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] GetConsoleScreenBufferInfo* (hConsoleOutput: INTEGER; ConsoleScreenBufferInfo: TConsoleScreenBufferInfo): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] FillConsoleOutputCharacterA* (hConsoleOutput, cCaracter, nLength, dwWriteCoord, lpNumberOfCharsWritten: INTEGER): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] FillConsoleOutputAttribute* (hConsoleOutput, wAttribute, nLength, dwWriteCoord, lpNumberOfAttrsWritten: INTEGER): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] SetConsoleTextAttribute* (hConsoleOutput, wAttributes: INTEGER): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] GetStdHandle* (nStdHandle: INTEGER): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] CloseHandle* (hObject: INTEGER): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] WriteFile* (hFile, Buffer, nNumberOfBytesToRead, lpNumberOfBytesRead: INTEGER; lpOverlapped: POverlapped): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] ReadFile* (hFile, Buffer, nNumberOfBytesToRead, lpNumberOfBytesRead: INTEGER; lpOverlapped: POverlapped): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] GetCommandLineA* (): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] GlobalAlloc* (uFlags, dwBytes: INTEGER): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] GlobalFree* (hMem: INTEGER): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] ExitProcess* (code: INTEGER); - -PROCEDURE [windows-, KERNEL, ""] GetTickCount* (): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] Sleep* (dwMilliseconds: INTEGER); - -PROCEDURE [windows-, KERNEL, ""] FreeLibrary* (hLibModule: INTEGER): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] GetProcAddress* (hModule, name: INTEGER): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] LoadLibraryA* (name: INTEGER): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] AllocConsole* (): BOOLEAN; - -PROCEDURE [windows-, KERNEL, ""] FreeConsole* (): BOOLEAN; - -PROCEDURE [windows-, KERNEL, ""] GetLocalTime* (T: TSystemTime); - -PROCEDURE [windows-, KERNEL, ""] RemoveDirectoryA* (lpPathName: INTEGER): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] GetFileAttributesA* (lpPathName: INTEGER): SET; - -PROCEDURE [windows-, KERNEL, ""] CreateDirectoryA* (lpPathName: INTEGER; lpSecurityAttributes: PSecurityAttributes): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] FindFirstFileA* (lpFileName: INTEGER; lpFindFileData: TWin32FindData): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] DeleteFileA* (lpFileName: INTEGER): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] FindClose* (hFindFile: INTEGER): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] CreateFileA* ( - lpFileName, dwDesiredAccess, dwShareMode: INTEGER; - lpSecurityAttributes: PSecurityAttributes; - dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile: INTEGER): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] OpenFile* (lpFileName: INTEGER; lpReOpenBuff: OFSTRUCT; uStyle: INTEGER): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] SetFilePointer* (hFile, lDistanceToMove, lpDistanceToMoveHigh, dwMoveMethod: INTEGER): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] ReadConsoleA* (hConsoleInput, lpBuffer, nNumberOfCharsToRead, lpNumberOfCharsRead, lpReserved: INTEGER): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] WriteConsoleW* (hConsoleOutput, lpBuffer, nNumberOfCharsToWrite, lpNumberOfCharsWritten, lpReserved: INTEGER): INTEGER; - -PROCEDURE [windows-, KERNEL, ""] WriteConsoleA* (hConsoleOutput, lpBuffer, nNumberOfCharsToWrite, lpNumberOfCharsWritten, lpReserved: INTEGER): INTEGER; - -PROCEDURE [windows-, USER, ""] MessageBoxA* (hWnd, lpText, lpCaption, uType: INTEGER): INTEGER; - -PROCEDURE [windows-, USER, ""] MessageBoxW* (hWnd, lpText, lpCaption, uType: INTEGER): INTEGER; - -PROCEDURE [windows-, USER, ""] CreateWindowExA* ( - dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, - nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam: INTEGER): INTEGER; - -PROCEDURE [windows-, MSVCRT, ""] time* (ptr: INTEGER): INTEGER; - -PROCEDURE [windows-, MSVCRT, ""] mktime* (time: tm): INTEGER; - - -PROCEDURE SetDllEntry* (process_detach, thread_detach, thread_attach: DLL_ENTRY); -BEGIN - API.SetDll(process_detach, thread_detach, thread_attach) -END SetDllEntry; - - -END WINAPI. \ No newline at end of file diff --git a/programs/develop/oberon07/README.md b/programs/develop/oberon07/README.md new file mode 100644 index 0000000000..e2d394b376 --- /dev/null +++ b/programs/develop/oberon07/README.md @@ -0,0 +1,6 @@ +Oberon-07 compiler for x64 (Windows, Linux), x86 (Windows, Linux, KolibriOS), MSP430x{1,2}xx, STM32 Cortex-M3 +============================================ +**Links:** + +https://github.com/prospero78/obGraph (Тест графических возможностей компилятора Оберона-07) +https://github.com/VadimAnIsaev/Oberon-07-additional-modules (Additional modules / Дополнительные модули) diff --git a/programs/develop/oberon07/Samples/Linux/HW.ob07 b/programs/develop/oberon07/Samples/Linux/HW.ob07 deleted file mode 100644 index 382ab9ca2d..0000000000 --- a/programs/develop/oberon07/Samples/Linux/HW.ob07 +++ /dev/null @@ -1,52 +0,0 @@ -MODULE HW; - -IMPORT SYSTEM, Libdl, Args; - - -VAR - - libc: INTEGER; - puts: PROCEDURE [linux] (pStr: INTEGER); - - -PROCEDURE OutStringLn (s: ARRAY OF CHAR); -BEGIN - puts(SYSTEM.ADR(s[0])) -END OutStringLn; - - -PROCEDURE main; -VAR - i: INTEGER; - s: ARRAY 80 OF CHAR; - -BEGIN - OutStringLn("Hello"); - - OutStringLn(""); - i := 0; - WHILE i < Args.argc DO - Args.GetArg(i, s); - INC(i); - OutStringLn(s) - END; - - OutStringLn(""); - i := 0; - WHILE i < Args.envc DO - Args.GetEnv(i, s); - INC(i); - OutStringLn(s) - END; - OutStringLn(""); - - OutStringLn("Bye") -END main; - - -BEGIN - libc := Libdl.open("libc.so.6", Libdl.LAZY); - SYSTEM.PUT(SYSTEM.ADR(puts), Libdl.sym(libc, "puts")); - ASSERT(puts # NIL); - main -END HW. diff --git a/programs/develop/oberon07/Samples/Linux/X11/animation/_unix.ob07 b/programs/develop/oberon07/Samples/Linux/X11/animation/_unix.ob07 deleted file mode 100644 index 0cd77749e2..0000000000 --- a/programs/develop/oberon07/Samples/Linux/X11/animation/_unix.ob07 +++ /dev/null @@ -1,74 +0,0 @@ -MODULE _unix; (* connect to unix host *) -IMPORT SYSTEM, API; - -(* how to find C declarations: -- gcc -E preprocess only (to stdout) (preprocessor expand) -- grep -r name /usr/include/* -- ldd progfile -- objdump -T progfile (-t) (-x) -*) - -CONST RTLD_LAZY = 1; - BIT_DEPTH* = API.BIT_DEPTH; - -VAR sym, libc, libdl :INTEGER; - - _dlopen* :PROCEDURE [linux] (name, flags :INTEGER) :INTEGER; - _dlsym* :PROCEDURE [linux] (p, name :INTEGER) :INTEGER; - _dlclose* :PROCEDURE [linux] (p :INTEGER) :INTEGER; - _open* :PROCEDURE [linux] (name, flags, mode :INTEGER) :INTEGER; - _close* :PROCEDURE [linux] (fd :INTEGER) :INTEGER; - _read* :PROCEDURE [linux] (fd, buf, sz :INTEGER): INTEGER; - _write* :PROCEDURE [linux] (fd, buf, sz :INTEGER) :INTEGER; - _exit* :PROCEDURE [linux] (n :INTEGER); - _malloc* :PROCEDURE [linux] (sz :INTEGER) :INTEGER; - _select* :PROCEDURE [linux] (cnt, readfds, writefds, exceptfds, timeout :INTEGER) :INTEGER; - - (* error message to stderr *) -PROCEDURE writeChar (c :CHAR); -VAR ri :INTEGER; -BEGIN ri := _write (2, SYSTEM.ADR(c), 1); ASSERT (ri = 1) END writeChar; - -PROCEDURE writeString (s :ARRAY OF CHAR); -VAR i :INTEGER; -BEGIN i := 0; WHILE s[i] # 0X DO writeChar (s[i]); INC(i) END; END writeString; - -PROCEDURE nl; -BEGIN writeChar (0AX) END nl; - - -PROCEDURE getSymAdr (lib :INTEGER; name :ARRAY OF CHAR; adr :INTEGER); -BEGIN - sym := _dlsym (lib, SYSTEM.ADR(name[0])); - IF sym = 0 THEN writeString ("error: dlsym: "); writeString (name); nl END; - ASSERT (sym # 0); - SYSTEM.PUT (adr, sym) -END getSymAdr; - - -PROCEDURE finish*; -VAR ri :INTEGER; -BEGIN - IF libc # 0 THEN ri := _dlclose (libc); libc := 0 END; - IF libdl # 0 THEN ri := _dlclose (libdl); libdl := 0 END; -END finish; - - -BEGIN - _dlopen := API.dlopen; - _dlsym := API.dlsym; - libc := _dlopen (SYSTEM.SADR("libc.so.6"), RTLD_LAZY); ASSERT (libc # 0); - (* getSymAdr is not used for write() to get writeString() error message going *); - sym := _dlsym (libc, SYSTEM.SADR("write")); ASSERT (sym # 0); SYSTEM.PUT (SYSTEM.ADR(_write), sym); - - libdl := _dlopen (SYSTEM.SADR("libdl.so.2"), RTLD_LAZY); ASSERT (libdl # 0); - getSymAdr (libdl, "dlclose", SYSTEM.ADR(_dlclose)); - - getSymAdr (libc, "open", SYSTEM.ADR(_open)); - getSymAdr (libc, "close", SYSTEM.ADR(_close)); - getSymAdr (libc, "read", SYSTEM.ADR(_read)); - getSymAdr (libc, "exit", SYSTEM.ADR(_exit)); - getSymAdr (libc, "malloc", SYSTEM.ADR(_malloc)); - getSymAdr (libc, "select", SYSTEM.ADR(_select)); -END _unix. - diff --git a/programs/develop/oberon07/Samples/Linux/X11/animation/animation.ob07 b/programs/develop/oberon07/Samples/Linux/X11/animation/animation.ob07 deleted file mode 100644 index eaf840334f..0000000000 --- a/programs/develop/oberon07/Samples/Linux/X11/animation/animation.ob07 +++ /dev/null @@ -1,89 +0,0 @@ -MODULE animation; (* moving turtle example *) -(* demonstrates use of timeout and select() to display a moving turtle in an X11 window *) -IMPORT SYSTEM, gr; - -CONST - Side = 8; (* nr of pixels of a square side *) - -VAR base, stride, screenBufSize :INTEGER; - currentX :INTEGER; - - -PROCEDURE drawSquare (x, y, color :INTEGER); -VAR p, i, j :INTEGER; -BEGIN - p := (y*stride + x*4)*Side; - ASSERT (p + (Side-1)*stride + (Side-1)*4 <= screenBufSize); - p := base + p; - FOR j := 0 TO Side-1 DO - FOR i := 0 TO Side-1 DO SYSTEM.PUT32 (p, color); INC(p, 4) END; - p := p + stride - Side*4; - END; -END drawSquare; - - -PROCEDURE putLine (x : INTEGER; y: INTEGER;str : ARRAY OF CHAR); -VAR z, x1: INTEGER; -BEGIN - FOR z := 0 TO LEN(str) - 1 DO - x1 := (x + z) MOD 100; - IF str[z] = "b" THEN drawSquare(x1, y, 0600000H); END; (* brown *) - IF str[z] = "g" THEN drawSquare(x1, y, 000C000H); END; (* green *) - END; -END putLine; - - -PROCEDURE turtlePicture (x , y : INTEGER); -BEGIN - putLine(x, y + 0 , "....bb........"); - putLine(x, y + 1 , "....bbb......."); - putLine(x, y + 2 , "....bbbb......"); - putLine(x, y + 3 , ".bb..bbb......"); - putLine(x, y + 4 , ".bgggbbbgbbgb."); - putLine(x, y + 5 , ".ggggggggbbbb."); - putLine(x, y + 6 , "bggggggggbbbb."); - putLine(x, y + 7 , ".ggggggg......"); - putLine(x, y + 8 , ".bb..bbb......"); - putLine(x, y + 9 , "....bbbb......"); - putLine(x, y + 10, ".....bbb......"); - putLine(x, y + 11, ".....bb.......") -END turtlePicture; - - -PROCEDURE drawAll; -BEGIN - gr.screenBegin; - gr.clear (0C0F0FFH); (* light blue *) - turtlePicture (currentX, 15); - gr.screenEnd; -END drawAll; - - -PROCEDURE run*; -VAR stop :BOOLEAN; - ev :gr.EventPars; - ch :CHAR; -BEGIN - base := gr.base; stride := gr.stride; - gr.createWindow (800, 480); - screenBufSize := gr.winHeight * stride; - stop := FALSE; currentX := 15; - drawAll; - REPEAT - gr.nextEvent (400, ev); - IF ev[0] = gr.EventTimeOut THEN - drawAll; - INC (currentX, 4); - ELSIF ev[0] = gr.EventKeyPressed THEN - ch := CHR(ev[4]); - IF (ch = "q") OR (ch = 0AX) OR (ch = " ") THEN stop := TRUE END; - IF ev[2] = 9 (* ESC *) THEN stop := TRUE END; - END; - UNTIL stop; - gr.finish; -END run; - -BEGIN - run; -END animation. - diff --git a/programs/develop/oberon07/Samples/Linux/X11/animation/gr.ob07 b/programs/develop/oberon07/Samples/Linux/X11/animation/gr.ob07 deleted file mode 100644 index c22e75e82f..0000000000 --- a/programs/develop/oberon07/Samples/Linux/X11/animation/gr.ob07 +++ /dev/null @@ -1,292 +0,0 @@ -MODULE gr; (* connect to libX11 *) -IMPORT SYSTEM, unix, out; - -(* -X11 documentation in: -- http://tronche.com/gui/x/xlib/ an X11 reference -- http://www.sbin.org/doc/Xlib an X11 tutorial (this domain has disappeared) -*) - -CONST - InputOutput = 1; - StructureNotifyMask = 20000H; (* input event mask *) - ExposureMask = 8000H; KeyPressMask = 1; KeyReleaseMask = 2; - ButtonPressMask = 4; ButtonReleaseMask = 8; (* PointerNotionMask *) - ZPixmap = 2; - Expose = 12; (* X event type *) ConfigureNotify = 22; KeyPress = 2; ButtonPress = 4; - - EventTimeOut* = 80; (* 0, 0, 0, 0 *) - EventResize* = 81; (* 0, w, h, 0 *) - EventKeyPressed* = 82; (* isPrintable, keyCode (X11 scan code), state, keySym (ASCII) *) - EventKeyReleased* = 83; (* 0, keyCode, state, 0 *) - EventButtonPressed* = 84; (* button, x, y, state *) - EventButtonReleased* = 85; (* button, x, y, state *) - (* mouse button 1-5 = Left, Middle, Right, Scroll wheel up, Scroll wheel down *) - - bit64 = ORD(unix.BIT_DEPTH = 64); - -TYPE EventPars* = ARRAY 5 OF INTEGER; - XEvent = RECORD - val :ARRAY 192 OF BYTE (* union { ..., long pad[24]; } *) - (* val :ARRAY 48 OF CARD32; *) - END; - -VAR ScreenWidth*, ScreenHeight* :INTEGER; - winWidth*, winHeight* :INTEGER; (* draw by writing to pixel buffer: *) - base*, stride* :INTEGER; (* width, height, base ptr, stride in bytes, 32-bit RGB *) - painting :BOOLEAN; - - libX11 :INTEGER; (* handle to dynamic library *) - XOpenDisplay :PROCEDURE [linux] (name :INTEGER) :INTEGER; - XCloseDisplay :PROCEDURE [linux] (display :INTEGER); - XSynchronize :PROCEDURE [linux] (display, onoff :INTEGER) :INTEGER; (* return prev onoff *) - XConnectionNumber :PROCEDURE [linux] (display :INTEGER) :INTEGER; - XCreateWindow :PROCEDURE [linux] (display, parent_window, x, y, w, h, border_width, depth, - class, visual, valuemask, attributes :INTEGER) :INTEGER; (* Window *) - XDefaultScreen :PROCEDURE [linux] (display :INTEGER) :INTEGER; - XDefaultGC :PROCEDURE [linux] (display, screenNr :INTEGER) :INTEGER; (* GC *) - XDisplayWidth :PROCEDURE [linux] (display, screenNr :INTEGER) :INTEGER; - XDisplayHeight :PROCEDURE [linux] (display, screenNr :INTEGER) :INTEGER; - XDefaultVisual :PROCEDURE [linux] (display, screenNr :INTEGER) :INTEGER; (* visual *) - XDefaultRootWindow :PROCEDURE [linux] (display :INTEGER) :INTEGER; (* Window *) - XDefaultDepth :PROCEDURE [linux] (display, screenNr :INTEGER) :INTEGER; - XSelectInput :PROCEDURE [linux] (display, window, event_mask :INTEGER); - XMapWindow :PROCEDURE [linux] (display, window :INTEGER); - XNextEvent :PROCEDURE [linux] (display, XEvent_p :INTEGER); - XPending :PROCEDURE [linux] (display :INTEGER) :INTEGER; - XLookupString :PROCEDURE [linux] (key_event, buffer_return, buflen, keysym_return, status_in_out :INTEGER) :INTEGER; - XCreateImage :PROCEDURE [linux] (display, visual, depth, format, offset, data, - width, height, bitmap_pad, bytes_per_line :INTEGER) :INTEGER; (* ptr to XImage *) - XPutImage :PROCEDURE [linux] (display, window, gc, image, sx, sy, dx, dy, w, h :INTEGER); - - display, screen, window, gc, img :INTEGER; - connectionNr :INTEGER; (* fd of X11 socket *) - readX11 :unix.fd_set; (* used by select() timeout on X11 socket *) - - -PROCEDURE getSymAdr (lib :INTEGER; name :ARRAY OF CHAR; adr :INTEGER); -VAR sym :INTEGER; -BEGIN - sym := unix.dlsym (lib, SYSTEM.ADR(name[0])); - IF sym = 0 THEN out.formatStr ("error: dlsym: %", name); out.nl END; - ASSERT (sym # 0); - SYSTEM.PUT (adr, sym) -END getSymAdr; - - -PROCEDURE init; -BEGIN - display := XOpenDisplay (0); - IF display = 0 THEN out.str ("error: can not open X11 display."); out.nl; out.exit(1) END; - (* ri := XSynchronize (display, 1); *) - connectionNr := XConnectionNumber (display); ASSERT (connectionNr < unix.FD_SETSIZE); - NEW (readX11); unix.FD_ZERO(readX11); unix.FD_SET (connectionNr, readX11); - screen := XDefaultScreen (display); gc := XDefaultGC (display, screen); - ScreenWidth := XDisplayWidth (display, screen); ScreenHeight := XDisplayHeight (display, screen); - base := unix.malloc (ScreenWidth * ScreenHeight * 4); - IF base = 0 THEN - out.formatInt2 ("error: can not allocate screen buffer % x %", ScreenWidth, ScreenHeight); out.nl; out.exit(1); - END; - stride := ScreenWidth * 4; - img := XCreateImage (display, XDefaultVisual (display, screen), XDefaultDepth (display, screen), - ZPixmap, 0, base, ScreenWidth, ScreenHeight, 32, 0); -END init; - - -PROCEDURE finish*; -VAR ri :INTEGER; -BEGIN - IF display # 0 THEN XCloseDisplay(display); display := 0 END; - IF libX11 # 0 THEN ri := unix.dlclose (libX11); libX11 := 0 END; -END finish; - - -PROCEDURE createWindow* (w, h :INTEGER); -VAR eventMask :INTEGER; -BEGIN - IF (w > ScreenWidth) OR (h > ScreenHeight) THEN - out.str ("error: X11.createWindow: window too large"); out.exit(1); - END; - ASSERT ((w >= 0) & (h >= 0)); - window := XCreateWindow (display, XDefaultRootWindow (display), 0, 0, w, h, 0, - XDefaultDepth (display, screen), InputOutput, XDefaultVisual (display, screen), 0, 0); - winWidth := w; winHeight := h; - eventMask := StructureNotifyMask + ExposureMask + KeyPressMask + ButtonPressMask; - XSelectInput (display, window, eventMask); - XMapWindow (display, window); -END createWindow; - - -PROCEDURE screenBegin*; - (* intended to enable future cooperation with iOS / MacOS *) -BEGIN - ASSERT (~painting); painting := TRUE -END screenBegin; - - -PROCEDURE screenEnd*; -BEGIN - ASSERT (painting); - XPutImage (display, window, gc, img, 0, 0, 0, 0, winWidth, winHeight); - painting := FALSE; -END screenEnd; - - -PROCEDURE readInt (e :XEvent; i :INTEGER) :INTEGER; - (* treat XEvent byte array as int array *) -VAR n :INTEGER; -BEGIN - ASSERT (i >= 0); - ASSERT (i < 48); - i := i * 4; - n := e.val[i+3]*1000000H + e.val[i+2]*10000H + e.val[i+1]*100H + e.val[i]; -RETURN n -END readInt; - - -PROCEDURE nextEvent* (msTimeOut :INTEGER; VAR ev :EventPars); -VAR _type, n, ri :INTEGER; - event :XEvent; - x, y, w, h :INTEGER; - timeout :unix.timespec; -BEGIN -(* struct XEvent (64-bit): -any: 4 type 8 serial 4 send_event 8 display 8 window 8 window -expose: 40 any 4 x, y, w, h, count -xconfigure: 48 any 4 x, y, w, h -xkey / xbutton / xmotion: 48 any 8 sub_window 8 time_ms 4 x, y, x_root, y_root 4 state 4 keycode/button -*) -(* struct XEvent (32-bit): -any: 4 type 4 serial 4 send_event 4 display 4 window -expose: 20 any 4 x, y, w, h, count -xconfigure: 24 any 4 x, y, w, h -xkey / xbutton / xmotion: 24 any 4 sub_window 4 time_ms 4 x, y, x_root, y_root 4 state 4 keycode/button -*) - _type := 0; - WHILE _type = 0 DO - IF (msTimeOut > 0) & (XPending(display) = 0) THEN - timeout.tv_sec := msTimeOut DIV 1000; timeout.tv_usec := (msTimeOut MOD 1000) * 1000; - ri := unix.select (connectionNr + 1, readX11, NIL, NIL, timeout); ASSERT (ri # -1); - IF ri = 0 THEN _type := EventTimeOut; ev[1] := 0; ev[2] := 0; ev[3] := 0; ev[4] := 0 END; - END; - IF _type = 0 THEN - XNextEvent (display, SYSTEM.ADR(event)); - CASE readInt (event, 0) OF - Expose : - x := readInt (event, 5 + 5 * bit64); y := readInt (event, 6 + 5 * bit64); - w := readInt (event, 7 + 5 * bit64); h := readInt (event, 8 + 5 * bit64); - XPutImage (display, window, gc, img, x, y, x, y, w, h); - | ConfigureNotify : - w := readInt (event, 8 + 6 * bit64); h := readInt (event, 9 + 6 * bit64); - IF (w # winWidth) & (h # winHeight) THEN - ASSERT ((w >= 0) & (h >= 0)); - IF w > ScreenWidth THEN w := ScreenWidth END; - IF h > ScreenHeight THEN h := ScreenHeight END; - winWidth := w; winHeight := h; - ev[0] := EventResize; ev[1] := 0; ev[2] := w; ev[3] := h; ev[4] := 0; - END; - | KeyPress : - _type := EventKeyPressed; - x := XLookupString (SYSTEM.ADR(event), 0, 0, SYSTEM.ADR(n), 0); (* KeySym *) - IF (n = 8) OR (n = 10) OR (n >= 32) & (n <= 126) THEN ev[1] := 1 ELSE ev[1] := 0; n := 0 END; (* isprint *) - ev[2] := readInt (event, 13 + 8 * bit64); (* keycode *) - ev[3] := readInt (event, 12 + 8 * bit64); (* state *) - ev[4] := n; (* KeySym *) - | ButtonPress : - _type := EventButtonPressed; - ev[1] := readInt (event, 13 + 8 * bit64); (* button *) - ev[2] := readInt (event, 8 + 8 * bit64); (* x *) - ev[3] := readInt (event, 9 + 8 * bit64); (* y *) - ev[4] := readInt (event, 12 + 8 * bit64); (* state *) - ELSE - END - END - END; - ev[0] := _type -END nextEvent; - - -PROCEDURE clear* (color :INTEGER); (* fill window area with color *) -VAR p, i, j :INTEGER; -BEGIN - FOR j := 0 TO winHeight-1 DO - p := base + j*stride; - FOR i := 0 TO winWidth-1 DO SYSTEM.PUT32 (p, color); INC (p, 4) END - END -END clear; - - -(* -PROCEDURE blitError (stride, x, y, w, h :INTEGER); -BEGIN - o.formatInt ("error: screen.blit (src, %)", stride); - o.formatInt2 (", %, %", x, y); - o.formatInt2 (", %, %) out of bounds", w, h); o.nl; - ASSERT (FALSE) -END blitError; - -PROCEDURE blit* (src, srcStride, x, y, w, h :INTEGER); -VAR dstStride, p :INTEGER; -BEGIN - IF (x < 0) OR (y < 0) THEN blitError (srcStride, x, y, w, h) END; - IF (w <= 0) OR (h <= 0) THEN blitError (srcStride, x, y, w, h) END; - IF (x + w > ScreenWidth) OR (y + h > ScreenHeight) THEN blitError (srcStride, x, y, w, h) END; - - dstStride := ScreenWidth - w; - p := ScreenBase + y * ScreenWidth + x * 4; - REPEAT - SYSTEM.COPY (src, p, w); - INC (src, srcStride); INC (p, dstStride); DEC (h) - UNTIL h = 0 -END blit; -*) - -(* -PROCEDURE setPixel* (x, y, color :INTEGER); -VAR p :INTEGER; -BEGIN - ASSERT ((x >= 0) & (x < ScreenWidth) & (y >= 0) & (y < ScreenHeight)); - screenBegin; p := base + (y*ScreenWidth + x)*4; SYSTEM.PUT32 (p, color); p := p + 4 screenEnd -END setPixel; -*) - -(* -PROCEDURE loop; (* example main loop *) -VAR e :EventPars; - stop :BOOLEAN; -BEGIN - createWindow (200, 200); - stop := FALSE; - REPEAT - nextEvent (0, e); - IF e[0] = EventKeyPressed THEN stop := TRUE END; - UNTIL stop; - XCloseDisplay (display); -END loop; -*) - - -BEGIN - libX11 := unix.dlopen (SYSTEM.SADR("libX11.so.6"), unix.RTLD_LAZY); ASSERT (libX11 # 0); - getSymAdr (libX11, "XOpenDisplay", SYSTEM.ADR(XOpenDisplay)); - getSymAdr (libX11, "XCloseDisplay", SYSTEM.ADR(XCloseDisplay)); - getSymAdr (libX11, "XSynchronize", SYSTEM.ADR(XSynchronize)); - getSymAdr (libX11, "XConnectionNumber", SYSTEM.ADR(XConnectionNumber)); - getSymAdr (libX11, "XCreateWindow", SYSTEM.ADR(XCreateWindow)); - getSymAdr (libX11, "XDefaultScreen", SYSTEM.ADR(XDefaultScreen)); - getSymAdr (libX11, "XDefaultGC", SYSTEM.ADR(XDefaultGC)); - getSymAdr (libX11, "XDisplayWidth", SYSTEM.ADR(XDisplayWidth)); - getSymAdr (libX11, "XDisplayHeight", SYSTEM.ADR(XDisplayHeight)); - getSymAdr (libX11, "XDefaultVisual", SYSTEM.ADR(XDefaultVisual)); - getSymAdr (libX11, "XDefaultRootWindow", SYSTEM.ADR(XDefaultRootWindow)); - getSymAdr (libX11, "XDefaultDepth", SYSTEM.ADR(XDefaultDepth)); - getSymAdr (libX11, "XSelectInput", SYSTEM.ADR(XSelectInput)); - getSymAdr (libX11, "XMapWindow", SYSTEM.ADR(XMapWindow)); - getSymAdr (libX11, "XNextEvent", SYSTEM.ADR(XNextEvent)); - getSymAdr (libX11, "XPending", SYSTEM.ADR(XPending)); - getSymAdr (libX11, "XLookupString", SYSTEM.ADR(XLookupString)); - getSymAdr (libX11, "XCreateImage", SYSTEM.ADR(XCreateImage)); - getSymAdr (libX11, "XPutImage", SYSTEM.ADR(XPutImage)); - init; -END gr. - diff --git a/programs/develop/oberon07/Samples/Linux/X11/animation/out.ob07 b/programs/develop/oberon07/Samples/Linux/X11/animation/out.ob07 deleted file mode 100644 index ad8478ce98..0000000000 --- a/programs/develop/oberon07/Samples/Linux/X11/animation/out.ob07 +++ /dev/null @@ -1,142 +0,0 @@ -MODULE out; (* formatted output to stdout *) -(* Wim Niemann, Jan Tuitman 06-OCT-2016 *) - -IMPORT SYSTEM, _unix; - -(* example: IMPORT o:=out; - o.str("Hello, World!");o.nl; - o.formatInt("n = %", 3);o.nl; -*) - -(* -The output functions buffer the characters in buf. This buffer is flushed when out.nl is -called and also when the buffer is full. - -Calling flush once per line is far more efficient then one system call per -character, but this is noticable only at very long outputs. -*) - -CONST MAX = 63; (* last position in buf *) - -VAR len :INTEGER; (* string length in buf *) - buf :ARRAY MAX+1 OF BYTE; - -PROCEDURE exit* (n :INTEGER); - (* prevent IMPORT unix for many programs *) -BEGIN _unix._exit(n) END exit; - -PROCEDURE writeChars; - (* write buf to the output function and set to empty string *) -VAR ri :INTEGER; -BEGIN - IF len > 0 THEN - (* buf[len] := 0X; *) - ri := _unix._write (1, SYSTEM.ADR(buf), len); ASSERT (ri = len); (* stdout *) - len := 0 - END -END writeChars; - -PROCEDURE nl*; (* append a newline to buf and flush *) -BEGIN - IF len = MAX THEN writeChars END; - buf[len] := 0AH; INC(len); - (* unix: 0AX; Oberon: 0DX; - Windows: IF len >= MAX-1 THEN 0DX 0AX; *) - writeChars; -END nl; - -PROCEDURE char* (c :CHAR); - (* append char to the end of buf *) -BEGIN - IF len = MAX THEN writeChars END; - buf[len] := ORD(c); INC(len) -END char; - -PROCEDURE str* (t :ARRAY OF CHAR); - (* append t to buf *) -VAR j :INTEGER; -BEGIN - j := 0; WHILE t[j] # 0X DO char(t[j]); INC(j) END -END str; - -PROCEDURE int* (n :INTEGER); - (* append integer; append n to d, return TRUE on overflow of d *) -VAR j :INTEGER; - sign :BOOLEAN; - dig :ARRAY 11 OF CHAR; (* assume 32 bit INTEGER *) -BEGIN - sign := FALSE; IF n < 0 THEN sign := TRUE; n := -n END; - IF n < 0 THEN - str ("-2147483648"); - ELSE - j := 0; - REPEAT dig[j] := CHR (n MOD 10 + 30H); n := n DIV 10; INC(j) UNTIL n = 0; - IF sign THEN char ("-") END; - REPEAT DEC(j); char(dig[j]) UNTIL j = 0; - END -END int; - -PROCEDURE formatInt* (t :ARRAY OF CHAR; n :INTEGER); - (* append formatted string t. Replace the first % by n *) -VAR j :INTEGER; -BEGIN - j := 0; WHILE (t[j] # 0X) & (t[j] # "%") DO char(t[j]); INC(j) END; - IF t[j] = "%" THEN - int(n); INC(j); - WHILE t[j] # 0X DO char(t[j]); INC(j) END - END -END formatInt; - -PROCEDURE formatInt2* (t:ARRAY OF CHAR; n1, n2 :INTEGER); - (* append formatted string t. Replace the first two % by n1 and n2 *) -VAR j :INTEGER; -BEGIN - j := 0; WHILE (t[j] # 0X) & (t[j] # "%") DO char(t[j]); INC(j) END; - IF t[j] = "%" THEN - int(n1); INC(j); - WHILE (t[j] # 0X) & (t[j] # "%") DO char(t[j]); INC(j) END; - IF t[j] = "%" THEN - int(n2); INC(j); - WHILE t[j] # 0X DO char(t[j]); INC(j) END - END - END -END formatInt2; - -PROCEDURE formatStr* (t, u :ARRAY OF CHAR); - (* append formatted string. Replace the first % in t by u *) -VAR j, k :INTEGER; -BEGIN - j := 0; WHILE (t[j] # 0X) & (t[j] # "%") DO char(t[j]); INC(j) END; - IF t[j] = "%" THEN - k := 0; WHILE u[k] # 0X DO char(u[k]); INC(k) END; - INC(j); WHILE t[j] # 0X DO char(t[j]); INC(j) END - END -END formatStr; - -PROCEDURE hex* (n, width :INTEGER); - (* print width positions of n as hex string. If necessary, prefix with leading zeroes *) - (* note: if n needs more positions than width, the first hex digits are not printed *) -VAR j :INTEGER; - dig :ARRAY 9 OF CHAR; -BEGIN - ASSERT(width > 0); - ASSERT (width <= 8); - dig[width] := 0X; - REPEAT - j := n MOD 16; n := n DIV 16; - IF j < 10 THEN j := ORD("0") + j ELSE j := ORD("A") + j - 10 END; - DEC(width); dig[width] := CHR(j) - UNTIL width = 0; - str (dig); -END hex; - -PROCEDURE flush*; -(* this routine comes at the end. It won't hardly ever be called - because nl also flushes. It is present only in case you - want to write a flushed string which does not end with nl. *) -BEGIN writeChars END flush; - -(* note: global variable 'len' must be 0 on init. Within the core, bodies of imported modules - are not executed, so rely on zero initialisation by Modules.Load *) -END out. - diff --git a/programs/develop/oberon07/Samples/Linux/X11/animation/unix.ob07 b/programs/develop/oberon07/Samples/Linux/X11/animation/unix.ob07 deleted file mode 100644 index d74ed88c16..0000000000 --- a/programs/develop/oberon07/Samples/Linux/X11/animation/unix.ob07 +++ /dev/null @@ -1,74 +0,0 @@ -MODULE unix; (* connect to unix host *) -IMPORT SYSTEM, _unix; -(* provide some Oberon friendly POSIX without need for SYSTEM *) - -CONST RTLD_LAZY* = 1; - O_RDONLY* = 0; - O_NEWFILE* = 0C2H; (* O_RDWR | O_CREAT | O_EXCL *) - (* O_RDONLY=0, O_WRONLY=1, O_RDWR=2, O_CREAT=0x40, O_EXCL=0x80, O_TRUNC=0x200 *) - FD_SETSIZE* = 1024; (* fd for select() must be smaller than FD_SETSIZE *) - BIT_DEPTH* = _unix.BIT_DEPTH; - LEN_FD_SET = FD_SETSIZE DIV BIT_DEPTH; - -TYPE - timespec* = RECORD - tv_sec*, tv_usec* :INTEGER - END; - fd_set* = POINTER TO RECORD (* for select() *) - bits* :ARRAY LEN_FD_SET OF SET (* 1024 bits *) - END; - -VAR - dlopen* :PROCEDURE [linux] (name, flags :INTEGER) :INTEGER; - dlsym* :PROCEDURE [linux] (p, name :INTEGER) :INTEGER; - dlclose* :PROCEDURE [linux] (p :INTEGER) :INTEGER; - close* :PROCEDURE [linux] (fd :INTEGER) :INTEGER; - exit* :PROCEDURE [linux] (n :INTEGER); - malloc* :PROCEDURE [linux] (sz :INTEGER) :INTEGER; - -PROCEDURE open* (path :ARRAY OF CHAR; flag, perm :INTEGER) :INTEGER; -BEGIN RETURN _unix._open (SYSTEM.ADR(path[0]), flag, perm) END open; - -PROCEDURE read* (fd :INTEGER; VAR buf :ARRAY OF BYTE; len :INTEGER) :INTEGER; -BEGIN RETURN _unix._read (fd, SYSTEM.ADR(buf[0]), len) END read; - -PROCEDURE readByte* (fd :INTEGER; VAR n :BYTE) :INTEGER; -BEGIN RETURN _unix._read (fd, SYSTEM.ADR(n), 1) END readByte; - -PROCEDURE write* (fd :INTEGER; buf :ARRAY OF BYTE; len :INTEGER) :INTEGER; -BEGIN RETURN _unix._write (fd, SYSTEM.ADR(buf[0]), len) END write; - -PROCEDURE writeByte* (fd :INTEGER; n :BYTE) :INTEGER; -BEGIN RETURN _unix._write (fd, SYSTEM.ADR(n), 1) END writeByte; - - -PROCEDURE FD_ZERO* (VAR selectSet :fd_set); -VAR i :INTEGER; -BEGIN FOR i := 0 TO LEN_FD_SET-1 DO selectSet.bits[i] := {} END END FD_ZERO; - -PROCEDURE FD_SET* (fd :INTEGER; VAR selectSet :fd_set); (* set fd bit in a select() fd_set *) -BEGIN INCL(selectSet.bits[fd DIV BIT_DEPTH], fd MOD BIT_DEPTH) -END FD_SET; - -PROCEDURE select* (cnt :INTEGER; readfds, writefds, exceptfds :fd_set; timeout :timespec) :INTEGER; -VAR n1, n2, n3 :INTEGER; -BEGIN - n1 := 0; IF readfds # NIL THEN n1 := SYSTEM.ADR (readfds.bits[0]) END; - n2 := 0; IF writefds # NIL THEN n2 := SYSTEM.ADR (writefds.bits[0]) END; - n3 := 0; IF exceptfds # NIL THEN n3 := SYSTEM.ADR (exceptfds.bits[0]) END; -RETURN _unix._select (cnt, n1, n2, n3, SYSTEM.ADR(timeout)) -END select; - - -PROCEDURE finish*; -BEGIN _unix.finish; END finish; - -BEGIN - dlopen := _unix._dlopen; - dlsym := _unix._dlsym; - dlclose := _unix._dlclose; - close := _unix._close; - exit := _unix._exit; - malloc := _unix._malloc; -END unix. - diff --git a/programs/develop/oberon07/Samples/Linux/X11/filler/_unix.ob07 b/programs/develop/oberon07/Samples/Linux/X11/filler/_unix.ob07 deleted file mode 100644 index 0cd77749e2..0000000000 --- a/programs/develop/oberon07/Samples/Linux/X11/filler/_unix.ob07 +++ /dev/null @@ -1,74 +0,0 @@ -MODULE _unix; (* connect to unix host *) -IMPORT SYSTEM, API; - -(* how to find C declarations: -- gcc -E preprocess only (to stdout) (preprocessor expand) -- grep -r name /usr/include/* -- ldd progfile -- objdump -T progfile (-t) (-x) -*) - -CONST RTLD_LAZY = 1; - BIT_DEPTH* = API.BIT_DEPTH; - -VAR sym, libc, libdl :INTEGER; - - _dlopen* :PROCEDURE [linux] (name, flags :INTEGER) :INTEGER; - _dlsym* :PROCEDURE [linux] (p, name :INTEGER) :INTEGER; - _dlclose* :PROCEDURE [linux] (p :INTEGER) :INTEGER; - _open* :PROCEDURE [linux] (name, flags, mode :INTEGER) :INTEGER; - _close* :PROCEDURE [linux] (fd :INTEGER) :INTEGER; - _read* :PROCEDURE [linux] (fd, buf, sz :INTEGER): INTEGER; - _write* :PROCEDURE [linux] (fd, buf, sz :INTEGER) :INTEGER; - _exit* :PROCEDURE [linux] (n :INTEGER); - _malloc* :PROCEDURE [linux] (sz :INTEGER) :INTEGER; - _select* :PROCEDURE [linux] (cnt, readfds, writefds, exceptfds, timeout :INTEGER) :INTEGER; - - (* error message to stderr *) -PROCEDURE writeChar (c :CHAR); -VAR ri :INTEGER; -BEGIN ri := _write (2, SYSTEM.ADR(c), 1); ASSERT (ri = 1) END writeChar; - -PROCEDURE writeString (s :ARRAY OF CHAR); -VAR i :INTEGER; -BEGIN i := 0; WHILE s[i] # 0X DO writeChar (s[i]); INC(i) END; END writeString; - -PROCEDURE nl; -BEGIN writeChar (0AX) END nl; - - -PROCEDURE getSymAdr (lib :INTEGER; name :ARRAY OF CHAR; adr :INTEGER); -BEGIN - sym := _dlsym (lib, SYSTEM.ADR(name[0])); - IF sym = 0 THEN writeString ("error: dlsym: "); writeString (name); nl END; - ASSERT (sym # 0); - SYSTEM.PUT (adr, sym) -END getSymAdr; - - -PROCEDURE finish*; -VAR ri :INTEGER; -BEGIN - IF libc # 0 THEN ri := _dlclose (libc); libc := 0 END; - IF libdl # 0 THEN ri := _dlclose (libdl); libdl := 0 END; -END finish; - - -BEGIN - _dlopen := API.dlopen; - _dlsym := API.dlsym; - libc := _dlopen (SYSTEM.SADR("libc.so.6"), RTLD_LAZY); ASSERT (libc # 0); - (* getSymAdr is not used for write() to get writeString() error message going *); - sym := _dlsym (libc, SYSTEM.SADR("write")); ASSERT (sym # 0); SYSTEM.PUT (SYSTEM.ADR(_write), sym); - - libdl := _dlopen (SYSTEM.SADR("libdl.so.2"), RTLD_LAZY); ASSERT (libdl # 0); - getSymAdr (libdl, "dlclose", SYSTEM.ADR(_dlclose)); - - getSymAdr (libc, "open", SYSTEM.ADR(_open)); - getSymAdr (libc, "close", SYSTEM.ADR(_close)); - getSymAdr (libc, "read", SYSTEM.ADR(_read)); - getSymAdr (libc, "exit", SYSTEM.ADR(_exit)); - getSymAdr (libc, "malloc", SYSTEM.ADR(_malloc)); - getSymAdr (libc, "select", SYSTEM.ADR(_select)); -END _unix. - diff --git a/programs/develop/oberon07/Samples/Linux/X11/filler/filler.ob07 b/programs/develop/oberon07/Samples/Linux/X11/filler/filler.ob07 deleted file mode 100644 index 969cab918e..0000000000 --- a/programs/develop/oberon07/Samples/Linux/X11/filler/filler.ob07 +++ /dev/null @@ -1,221 +0,0 @@ -MODULE filler; (* filler game, color more fields than the opponent *) -IMPORT SYSTEM, out, unix, gr; - -CONST - Side = 14; (* nr of pixels of a field side *) - width = 62; height = 48; (* board size *) - nrFields = width * height; - BackGroundColor = 0B0B050H; - -VAR fdRandom :INTEGER; (* /dev/urandom *) - base, stride, screenBufSize :INTEGER; - palette :ARRAY 6 OF INTEGER; - field :ARRAY nrFields OF INTEGER; (* color 0..5 *) - visit :ARRAY nrFields OF INTEGER; (* 0 unvisited, 1 neighbour to do, 2 done *) - Acount, Acolor, Bcount, Bcolor :INTEGER; (* player conquered fields and current color *) - rndSeed, rndIndex :INTEGER; - -PROCEDURE check (b :BOOLEAN; n :INTEGER); -BEGIN - IF ~b THEN - out.formatInt ("internal check failed: filler.mod: %", n); out.nl; - out.exit(1) - END -END check; - -PROCEDURE random6 () :INTEGER; (* return random 0..5 *) -VAR n :INTEGER; - b :BYTE; -BEGIN - IF rndIndex = 3 THEN - (* 6 ^ 3 = 216 so 3 random6 nrs fit in one random byte, don't waste entropy *) - n := unix.readByte (fdRandom, b); ASSERT (n = 1); - rndSeed := b; rndIndex := 0; - END; - n := rndSeed MOD 6; rndSeed := rndSeed DIV 6; INC (rndIndex) -RETURN n -END random6; - -PROCEDURE drawRect (x, y, color :INTEGER); -VAR p, i, j :INTEGER; -BEGIN - p := (y*stride + x*4)*Side; - check (p + (Side-1)*stride + (Side-1)*4 <= screenBufSize, 20); - p := base + p; - FOR j := 0 TO Side-1 DO - FOR i := 0 TO Side-1 DO SYSTEM.PUT32 (p, color); INC(p, 4) END; - p := p + stride - Side*4; - END; -END drawRect; - -PROCEDURE clearVisit; -VAR i :INTEGER; -BEGIN FOR i := 0 TO nrFields-1 DO visit[i] := 0 END; END clearVisit; - -PROCEDURE doNeighbour (i, old, new, v :INTEGER; VAR changed :BOOLEAN); - (* helper routine for connect() *) -BEGIN - IF visit[i] = 0 THEN - IF (v = 1) & (field[i] = old) THEN visit[i] := 1; changed := TRUE END; - IF field[i] = new THEN visit[i] := 2; changed := TRUE END - END -END doNeighbour; -(* - all visit := 0; count := 0; visit[corner] := 1 - repeat - changed := false; - foreach: - if (visit = 1) or (visit = 2) then - curVisit = visit - color := new; visit := 3; count++ - foreach neighbour: - if visit = 0 then - if curVisit = 1 then - if color = old then visit := 1; changed := true - if color = new then visit := 2; changed := true - if curVisit = 2 then - if color = new then visit := 2; changed := true - until no changes -*) -PROCEDURE connect (old, new :INTEGER) :INTEGER; -VAR count, i, x, y, v :INTEGER; - changed :BOOLEAN; -BEGIN -out.formatInt2 ("connect: old new % % ", old+1, new+1); - count := 0; - REPEAT - changed := FALSE; - FOR i := 0 TO nrFields-1 DO - v := visit[i]; - IF (v=1) OR (v=2) THEN - field[i] := new; visit[i] := 3; INC(count); - x := i MOD width; y := i DIV width; - IF x > 0 THEN doNeighbour (i-1, old, new, v, changed) END; - IF x < width-1 THEN doNeighbour (i+1, old, new, v, changed) END; - IF y > 0 THEN doNeighbour (i-width, old, new, v, changed) END; - IF y < height-1 THEN doNeighbour (i+width, old, new, v, changed) END; - END - END - UNTIL ~changed -RETURN count -END connect; - -PROCEDURE doMaxGainNeighbour (i, old, new, v :INTEGER; VAR changed :BOOLEAN); - (* helper routine for maxGain() *) -BEGIN - IF visit[i] = 0 THEN - IF v = 1 THEN - IF field[i] = old THEN visit[i] := 1 ELSE visit[i] := 2 END; - changed := TRUE - ELSE - IF field[i] = new THEN visit[i] := 2; changed := TRUE END - END - END -END doMaxGainNeighbour; -(* v=1 & field=old -> visit := 1 - v=1 & field # old -> visit := 2 - v=2 & field = new -> visit := 2 -*) - -PROCEDURE maxGain (old :INTEGER) :INTEGER; - (* return the color which will conquer the most fields *) -VAR - i, x, y, new, v :INTEGER; - max :ARRAY 6 OF INTEGER; - changed :BOOLEAN; -BEGIN - FOR i := 0 TO 5 DO max[i] := 0 END; - REPEAT - changed := FALSE; - FOR i := 0 TO nrFields-1 DO - v := visit[i]; - IF (v=1) OR (v=2) THEN - visit[i] := 3; new := field[i]; INC (max[new]); - x := i MOD width; y := i DIV width; - IF x > 0 THEN doMaxGainNeighbour (i-1, old, new, v, changed) END; - IF x < width-1 THEN doMaxGainNeighbour (i+1, old, new, v, changed) END; - IF y > 0 THEN doMaxGainNeighbour (i-width, old, new, v, changed) END; - IF y < height-1 THEN doMaxGainNeighbour (i+width, old, new, v, changed) END; - END - END - UNTIL ~changed; - x := -1; y := -1; max[Acolor] := -1; max[Bcolor] := -1; -out.str ("maxGain"); out.nl; -FOR i := 0 TO 5 DO out.formatInt2 (" % %", i+1, max[i]); out.nl END; - FOR i := 0 TO 5 DO IF (max[i] > y) & (i # old) THEN x := i; y := max[i] END END -RETURN x -END maxGain; - -PROCEDURE drawAll; -VAR x, y :INTEGER; -BEGIN - gr.screenBegin; - gr.clear (BackGroundColor); - FOR y := 0 TO 5 DO drawRect (0, 6 + y DIV 3 + 2*y, palette[y]) END; - FOR y := 0 TO 47 DO - FOR x := 0 TO 61 DO drawRect (x+2, y, palette[ field[y*width + x] ]) END - END; - gr.screenEnd; -END drawAll; - -PROCEDURE run*; -VAR stop :BOOLEAN; - ev :gr.EventPars; - x, y, i, old :INTEGER; - ch :CHAR; -BEGIN - FOR i := 0 TO nrFields-1 DO field[i] := random6() END; - Acolor := field[47*width]; field[47*width+1] := Acolor; field[46*width] := Acolor; field[46*width+1] := Acolor; - Bcolor := field[width-1]; field[width-2] := Bcolor; field[2*width-2] := Bcolor; field[2*width-1] := Bcolor; - base := gr.base; stride := gr.stride; - gr.createWindow (1000, 700); - screenBufSize := gr.winHeight * stride; - stop := FALSE; - drawAll; - REPEAT - gr.nextEvent (0, ev); - IF ev[0] = gr.EventKeyPressed THEN - (* o.formatInt("key pressed %",ev[2]);o.nl; *) - (* ev[2]: q=24, ESC=9, CR=36 *) - ch := CHR (ev[4]); - IF ev[2] = 9 THEN stop := TRUE END; (* ESC *) - (* IF ch = "q" THEN stop := TRUE END; *) - IF (ch >= "1") & (ch <= "6") THEN - i := ev[4] - ORD("1"); - IF (i # Acolor) & (i # Bcolor) THEN - (* player A *) - old := Acolor; Acolor := i; -out.formatInt ("play color %", Acolor+1); out.nl; - clearVisit; visit[47*width] := 1; - Acount := connect (old, Acolor) -;out.formatInt ("count A = %", Acount); out.nl; out.nl; - (* player B *) - clearVisit; visit[width-1] := 1; old := field[width-1]; - Bcolor := maxGain (old); - clearVisit; visit[width-1] := 1; - Bcount := connect (old, Bcolor); -out.formatInt ("count B = %", Bcount); out.nl; out.nl; - drawAll; - END - END; - ELSIF ev[0] = gr.EventButtonPressed THEN - x := ev[2] DIV Side; y := ev[3] DIV Side; - END; - UNTIL stop; - gr.finish; - unix.finish; -END run; - -BEGIN - fdRandom := unix.open ("/dev/urandom", unix.O_RDONLY, 0); ASSERT (fdRandom # -1); - rndIndex := 3; - (* a partial copy of the lexaloffle pico-8 16-color palette *) - palette[0] := 0FF004DH; (* red *) - palette[1] := 0FFA300H; (* orange *) - palette[2] := 07E2553H; (* dark purple *) - palette[3] := 0008751H; (* dark green *) - palette[4] := 029ADFFH; (* blue *) - palette[5] := 0FF77A8H; (* pink *) - run; -END filler. - diff --git a/programs/develop/oberon07/Samples/Linux/X11/filler/filler.txt b/programs/develop/oberon07/Samples/Linux/X11/filler/filler.txt deleted file mode 100644 index 143a343e48..0000000000 --- a/programs/develop/oberon07/Samples/Linux/X11/filler/filler.txt +++ /dev/null @@ -1,15 +0,0 @@ - -Filler game - -Player and computer each try to conquer the most fields. -Player starts at left bottom and computer at right top. - -At each turn, a new color is chosen and area extended. - -Press 1 .. 6 to choose color. At the left side of the board the top -color has nr 1 and the bottom color nr 6. The current colors of player -and opponent can not be chosen. The current area receives the new color -and is extended with all bordering areas of the chosen color. - -Have fun! - diff --git a/programs/develop/oberon07/Samples/Linux/X11/filler/gr.ob07 b/programs/develop/oberon07/Samples/Linux/X11/filler/gr.ob07 deleted file mode 100644 index c22e75e82f..0000000000 --- a/programs/develop/oberon07/Samples/Linux/X11/filler/gr.ob07 +++ /dev/null @@ -1,292 +0,0 @@ -MODULE gr; (* connect to libX11 *) -IMPORT SYSTEM, unix, out; - -(* -X11 documentation in: -- http://tronche.com/gui/x/xlib/ an X11 reference -- http://www.sbin.org/doc/Xlib an X11 tutorial (this domain has disappeared) -*) - -CONST - InputOutput = 1; - StructureNotifyMask = 20000H; (* input event mask *) - ExposureMask = 8000H; KeyPressMask = 1; KeyReleaseMask = 2; - ButtonPressMask = 4; ButtonReleaseMask = 8; (* PointerNotionMask *) - ZPixmap = 2; - Expose = 12; (* X event type *) ConfigureNotify = 22; KeyPress = 2; ButtonPress = 4; - - EventTimeOut* = 80; (* 0, 0, 0, 0 *) - EventResize* = 81; (* 0, w, h, 0 *) - EventKeyPressed* = 82; (* isPrintable, keyCode (X11 scan code), state, keySym (ASCII) *) - EventKeyReleased* = 83; (* 0, keyCode, state, 0 *) - EventButtonPressed* = 84; (* button, x, y, state *) - EventButtonReleased* = 85; (* button, x, y, state *) - (* mouse button 1-5 = Left, Middle, Right, Scroll wheel up, Scroll wheel down *) - - bit64 = ORD(unix.BIT_DEPTH = 64); - -TYPE EventPars* = ARRAY 5 OF INTEGER; - XEvent = RECORD - val :ARRAY 192 OF BYTE (* union { ..., long pad[24]; } *) - (* val :ARRAY 48 OF CARD32; *) - END; - -VAR ScreenWidth*, ScreenHeight* :INTEGER; - winWidth*, winHeight* :INTEGER; (* draw by writing to pixel buffer: *) - base*, stride* :INTEGER; (* width, height, base ptr, stride in bytes, 32-bit RGB *) - painting :BOOLEAN; - - libX11 :INTEGER; (* handle to dynamic library *) - XOpenDisplay :PROCEDURE [linux] (name :INTEGER) :INTEGER; - XCloseDisplay :PROCEDURE [linux] (display :INTEGER); - XSynchronize :PROCEDURE [linux] (display, onoff :INTEGER) :INTEGER; (* return prev onoff *) - XConnectionNumber :PROCEDURE [linux] (display :INTEGER) :INTEGER; - XCreateWindow :PROCEDURE [linux] (display, parent_window, x, y, w, h, border_width, depth, - class, visual, valuemask, attributes :INTEGER) :INTEGER; (* Window *) - XDefaultScreen :PROCEDURE [linux] (display :INTEGER) :INTEGER; - XDefaultGC :PROCEDURE [linux] (display, screenNr :INTEGER) :INTEGER; (* GC *) - XDisplayWidth :PROCEDURE [linux] (display, screenNr :INTEGER) :INTEGER; - XDisplayHeight :PROCEDURE [linux] (display, screenNr :INTEGER) :INTEGER; - XDefaultVisual :PROCEDURE [linux] (display, screenNr :INTEGER) :INTEGER; (* visual *) - XDefaultRootWindow :PROCEDURE [linux] (display :INTEGER) :INTEGER; (* Window *) - XDefaultDepth :PROCEDURE [linux] (display, screenNr :INTEGER) :INTEGER; - XSelectInput :PROCEDURE [linux] (display, window, event_mask :INTEGER); - XMapWindow :PROCEDURE [linux] (display, window :INTEGER); - XNextEvent :PROCEDURE [linux] (display, XEvent_p :INTEGER); - XPending :PROCEDURE [linux] (display :INTEGER) :INTEGER; - XLookupString :PROCEDURE [linux] (key_event, buffer_return, buflen, keysym_return, status_in_out :INTEGER) :INTEGER; - XCreateImage :PROCEDURE [linux] (display, visual, depth, format, offset, data, - width, height, bitmap_pad, bytes_per_line :INTEGER) :INTEGER; (* ptr to XImage *) - XPutImage :PROCEDURE [linux] (display, window, gc, image, sx, sy, dx, dy, w, h :INTEGER); - - display, screen, window, gc, img :INTEGER; - connectionNr :INTEGER; (* fd of X11 socket *) - readX11 :unix.fd_set; (* used by select() timeout on X11 socket *) - - -PROCEDURE getSymAdr (lib :INTEGER; name :ARRAY OF CHAR; adr :INTEGER); -VAR sym :INTEGER; -BEGIN - sym := unix.dlsym (lib, SYSTEM.ADR(name[0])); - IF sym = 0 THEN out.formatStr ("error: dlsym: %", name); out.nl END; - ASSERT (sym # 0); - SYSTEM.PUT (adr, sym) -END getSymAdr; - - -PROCEDURE init; -BEGIN - display := XOpenDisplay (0); - IF display = 0 THEN out.str ("error: can not open X11 display."); out.nl; out.exit(1) END; - (* ri := XSynchronize (display, 1); *) - connectionNr := XConnectionNumber (display); ASSERT (connectionNr < unix.FD_SETSIZE); - NEW (readX11); unix.FD_ZERO(readX11); unix.FD_SET (connectionNr, readX11); - screen := XDefaultScreen (display); gc := XDefaultGC (display, screen); - ScreenWidth := XDisplayWidth (display, screen); ScreenHeight := XDisplayHeight (display, screen); - base := unix.malloc (ScreenWidth * ScreenHeight * 4); - IF base = 0 THEN - out.formatInt2 ("error: can not allocate screen buffer % x %", ScreenWidth, ScreenHeight); out.nl; out.exit(1); - END; - stride := ScreenWidth * 4; - img := XCreateImage (display, XDefaultVisual (display, screen), XDefaultDepth (display, screen), - ZPixmap, 0, base, ScreenWidth, ScreenHeight, 32, 0); -END init; - - -PROCEDURE finish*; -VAR ri :INTEGER; -BEGIN - IF display # 0 THEN XCloseDisplay(display); display := 0 END; - IF libX11 # 0 THEN ri := unix.dlclose (libX11); libX11 := 0 END; -END finish; - - -PROCEDURE createWindow* (w, h :INTEGER); -VAR eventMask :INTEGER; -BEGIN - IF (w > ScreenWidth) OR (h > ScreenHeight) THEN - out.str ("error: X11.createWindow: window too large"); out.exit(1); - END; - ASSERT ((w >= 0) & (h >= 0)); - window := XCreateWindow (display, XDefaultRootWindow (display), 0, 0, w, h, 0, - XDefaultDepth (display, screen), InputOutput, XDefaultVisual (display, screen), 0, 0); - winWidth := w; winHeight := h; - eventMask := StructureNotifyMask + ExposureMask + KeyPressMask + ButtonPressMask; - XSelectInput (display, window, eventMask); - XMapWindow (display, window); -END createWindow; - - -PROCEDURE screenBegin*; - (* intended to enable future cooperation with iOS / MacOS *) -BEGIN - ASSERT (~painting); painting := TRUE -END screenBegin; - - -PROCEDURE screenEnd*; -BEGIN - ASSERT (painting); - XPutImage (display, window, gc, img, 0, 0, 0, 0, winWidth, winHeight); - painting := FALSE; -END screenEnd; - - -PROCEDURE readInt (e :XEvent; i :INTEGER) :INTEGER; - (* treat XEvent byte array as int array *) -VAR n :INTEGER; -BEGIN - ASSERT (i >= 0); - ASSERT (i < 48); - i := i * 4; - n := e.val[i+3]*1000000H + e.val[i+2]*10000H + e.val[i+1]*100H + e.val[i]; -RETURN n -END readInt; - - -PROCEDURE nextEvent* (msTimeOut :INTEGER; VAR ev :EventPars); -VAR _type, n, ri :INTEGER; - event :XEvent; - x, y, w, h :INTEGER; - timeout :unix.timespec; -BEGIN -(* struct XEvent (64-bit): -any: 4 type 8 serial 4 send_event 8 display 8 window 8 window -expose: 40 any 4 x, y, w, h, count -xconfigure: 48 any 4 x, y, w, h -xkey / xbutton / xmotion: 48 any 8 sub_window 8 time_ms 4 x, y, x_root, y_root 4 state 4 keycode/button -*) -(* struct XEvent (32-bit): -any: 4 type 4 serial 4 send_event 4 display 4 window -expose: 20 any 4 x, y, w, h, count -xconfigure: 24 any 4 x, y, w, h -xkey / xbutton / xmotion: 24 any 4 sub_window 4 time_ms 4 x, y, x_root, y_root 4 state 4 keycode/button -*) - _type := 0; - WHILE _type = 0 DO - IF (msTimeOut > 0) & (XPending(display) = 0) THEN - timeout.tv_sec := msTimeOut DIV 1000; timeout.tv_usec := (msTimeOut MOD 1000) * 1000; - ri := unix.select (connectionNr + 1, readX11, NIL, NIL, timeout); ASSERT (ri # -1); - IF ri = 0 THEN _type := EventTimeOut; ev[1] := 0; ev[2] := 0; ev[3] := 0; ev[4] := 0 END; - END; - IF _type = 0 THEN - XNextEvent (display, SYSTEM.ADR(event)); - CASE readInt (event, 0) OF - Expose : - x := readInt (event, 5 + 5 * bit64); y := readInt (event, 6 + 5 * bit64); - w := readInt (event, 7 + 5 * bit64); h := readInt (event, 8 + 5 * bit64); - XPutImage (display, window, gc, img, x, y, x, y, w, h); - | ConfigureNotify : - w := readInt (event, 8 + 6 * bit64); h := readInt (event, 9 + 6 * bit64); - IF (w # winWidth) & (h # winHeight) THEN - ASSERT ((w >= 0) & (h >= 0)); - IF w > ScreenWidth THEN w := ScreenWidth END; - IF h > ScreenHeight THEN h := ScreenHeight END; - winWidth := w; winHeight := h; - ev[0] := EventResize; ev[1] := 0; ev[2] := w; ev[3] := h; ev[4] := 0; - END; - | KeyPress : - _type := EventKeyPressed; - x := XLookupString (SYSTEM.ADR(event), 0, 0, SYSTEM.ADR(n), 0); (* KeySym *) - IF (n = 8) OR (n = 10) OR (n >= 32) & (n <= 126) THEN ev[1] := 1 ELSE ev[1] := 0; n := 0 END; (* isprint *) - ev[2] := readInt (event, 13 + 8 * bit64); (* keycode *) - ev[3] := readInt (event, 12 + 8 * bit64); (* state *) - ev[4] := n; (* KeySym *) - | ButtonPress : - _type := EventButtonPressed; - ev[1] := readInt (event, 13 + 8 * bit64); (* button *) - ev[2] := readInt (event, 8 + 8 * bit64); (* x *) - ev[3] := readInt (event, 9 + 8 * bit64); (* y *) - ev[4] := readInt (event, 12 + 8 * bit64); (* state *) - ELSE - END - END - END; - ev[0] := _type -END nextEvent; - - -PROCEDURE clear* (color :INTEGER); (* fill window area with color *) -VAR p, i, j :INTEGER; -BEGIN - FOR j := 0 TO winHeight-1 DO - p := base + j*stride; - FOR i := 0 TO winWidth-1 DO SYSTEM.PUT32 (p, color); INC (p, 4) END - END -END clear; - - -(* -PROCEDURE blitError (stride, x, y, w, h :INTEGER); -BEGIN - o.formatInt ("error: screen.blit (src, %)", stride); - o.formatInt2 (", %, %", x, y); - o.formatInt2 (", %, %) out of bounds", w, h); o.nl; - ASSERT (FALSE) -END blitError; - -PROCEDURE blit* (src, srcStride, x, y, w, h :INTEGER); -VAR dstStride, p :INTEGER; -BEGIN - IF (x < 0) OR (y < 0) THEN blitError (srcStride, x, y, w, h) END; - IF (w <= 0) OR (h <= 0) THEN blitError (srcStride, x, y, w, h) END; - IF (x + w > ScreenWidth) OR (y + h > ScreenHeight) THEN blitError (srcStride, x, y, w, h) END; - - dstStride := ScreenWidth - w; - p := ScreenBase + y * ScreenWidth + x * 4; - REPEAT - SYSTEM.COPY (src, p, w); - INC (src, srcStride); INC (p, dstStride); DEC (h) - UNTIL h = 0 -END blit; -*) - -(* -PROCEDURE setPixel* (x, y, color :INTEGER); -VAR p :INTEGER; -BEGIN - ASSERT ((x >= 0) & (x < ScreenWidth) & (y >= 0) & (y < ScreenHeight)); - screenBegin; p := base + (y*ScreenWidth + x)*4; SYSTEM.PUT32 (p, color); p := p + 4 screenEnd -END setPixel; -*) - -(* -PROCEDURE loop; (* example main loop *) -VAR e :EventPars; - stop :BOOLEAN; -BEGIN - createWindow (200, 200); - stop := FALSE; - REPEAT - nextEvent (0, e); - IF e[0] = EventKeyPressed THEN stop := TRUE END; - UNTIL stop; - XCloseDisplay (display); -END loop; -*) - - -BEGIN - libX11 := unix.dlopen (SYSTEM.SADR("libX11.so.6"), unix.RTLD_LAZY); ASSERT (libX11 # 0); - getSymAdr (libX11, "XOpenDisplay", SYSTEM.ADR(XOpenDisplay)); - getSymAdr (libX11, "XCloseDisplay", SYSTEM.ADR(XCloseDisplay)); - getSymAdr (libX11, "XSynchronize", SYSTEM.ADR(XSynchronize)); - getSymAdr (libX11, "XConnectionNumber", SYSTEM.ADR(XConnectionNumber)); - getSymAdr (libX11, "XCreateWindow", SYSTEM.ADR(XCreateWindow)); - getSymAdr (libX11, "XDefaultScreen", SYSTEM.ADR(XDefaultScreen)); - getSymAdr (libX11, "XDefaultGC", SYSTEM.ADR(XDefaultGC)); - getSymAdr (libX11, "XDisplayWidth", SYSTEM.ADR(XDisplayWidth)); - getSymAdr (libX11, "XDisplayHeight", SYSTEM.ADR(XDisplayHeight)); - getSymAdr (libX11, "XDefaultVisual", SYSTEM.ADR(XDefaultVisual)); - getSymAdr (libX11, "XDefaultRootWindow", SYSTEM.ADR(XDefaultRootWindow)); - getSymAdr (libX11, "XDefaultDepth", SYSTEM.ADR(XDefaultDepth)); - getSymAdr (libX11, "XSelectInput", SYSTEM.ADR(XSelectInput)); - getSymAdr (libX11, "XMapWindow", SYSTEM.ADR(XMapWindow)); - getSymAdr (libX11, "XNextEvent", SYSTEM.ADR(XNextEvent)); - getSymAdr (libX11, "XPending", SYSTEM.ADR(XPending)); - getSymAdr (libX11, "XLookupString", SYSTEM.ADR(XLookupString)); - getSymAdr (libX11, "XCreateImage", SYSTEM.ADR(XCreateImage)); - getSymAdr (libX11, "XPutImage", SYSTEM.ADR(XPutImage)); - init; -END gr. - diff --git a/programs/develop/oberon07/Samples/Linux/X11/filler/out.ob07 b/programs/develop/oberon07/Samples/Linux/X11/filler/out.ob07 deleted file mode 100644 index ad8478ce98..0000000000 --- a/programs/develop/oberon07/Samples/Linux/X11/filler/out.ob07 +++ /dev/null @@ -1,142 +0,0 @@ -MODULE out; (* formatted output to stdout *) -(* Wim Niemann, Jan Tuitman 06-OCT-2016 *) - -IMPORT SYSTEM, _unix; - -(* example: IMPORT o:=out; - o.str("Hello, World!");o.nl; - o.formatInt("n = %", 3);o.nl; -*) - -(* -The output functions buffer the characters in buf. This buffer is flushed when out.nl is -called and also when the buffer is full. - -Calling flush once per line is far more efficient then one system call per -character, but this is noticable only at very long outputs. -*) - -CONST MAX = 63; (* last position in buf *) - -VAR len :INTEGER; (* string length in buf *) - buf :ARRAY MAX+1 OF BYTE; - -PROCEDURE exit* (n :INTEGER); - (* prevent IMPORT unix for many programs *) -BEGIN _unix._exit(n) END exit; - -PROCEDURE writeChars; - (* write buf to the output function and set to empty string *) -VAR ri :INTEGER; -BEGIN - IF len > 0 THEN - (* buf[len] := 0X; *) - ri := _unix._write (1, SYSTEM.ADR(buf), len); ASSERT (ri = len); (* stdout *) - len := 0 - END -END writeChars; - -PROCEDURE nl*; (* append a newline to buf and flush *) -BEGIN - IF len = MAX THEN writeChars END; - buf[len] := 0AH; INC(len); - (* unix: 0AX; Oberon: 0DX; - Windows: IF len >= MAX-1 THEN 0DX 0AX; *) - writeChars; -END nl; - -PROCEDURE char* (c :CHAR); - (* append char to the end of buf *) -BEGIN - IF len = MAX THEN writeChars END; - buf[len] := ORD(c); INC(len) -END char; - -PROCEDURE str* (t :ARRAY OF CHAR); - (* append t to buf *) -VAR j :INTEGER; -BEGIN - j := 0; WHILE t[j] # 0X DO char(t[j]); INC(j) END -END str; - -PROCEDURE int* (n :INTEGER); - (* append integer; append n to d, return TRUE on overflow of d *) -VAR j :INTEGER; - sign :BOOLEAN; - dig :ARRAY 11 OF CHAR; (* assume 32 bit INTEGER *) -BEGIN - sign := FALSE; IF n < 0 THEN sign := TRUE; n := -n END; - IF n < 0 THEN - str ("-2147483648"); - ELSE - j := 0; - REPEAT dig[j] := CHR (n MOD 10 + 30H); n := n DIV 10; INC(j) UNTIL n = 0; - IF sign THEN char ("-") END; - REPEAT DEC(j); char(dig[j]) UNTIL j = 0; - END -END int; - -PROCEDURE formatInt* (t :ARRAY OF CHAR; n :INTEGER); - (* append formatted string t. Replace the first % by n *) -VAR j :INTEGER; -BEGIN - j := 0; WHILE (t[j] # 0X) & (t[j] # "%") DO char(t[j]); INC(j) END; - IF t[j] = "%" THEN - int(n); INC(j); - WHILE t[j] # 0X DO char(t[j]); INC(j) END - END -END formatInt; - -PROCEDURE formatInt2* (t:ARRAY OF CHAR; n1, n2 :INTEGER); - (* append formatted string t. Replace the first two % by n1 and n2 *) -VAR j :INTEGER; -BEGIN - j := 0; WHILE (t[j] # 0X) & (t[j] # "%") DO char(t[j]); INC(j) END; - IF t[j] = "%" THEN - int(n1); INC(j); - WHILE (t[j] # 0X) & (t[j] # "%") DO char(t[j]); INC(j) END; - IF t[j] = "%" THEN - int(n2); INC(j); - WHILE t[j] # 0X DO char(t[j]); INC(j) END - END - END -END formatInt2; - -PROCEDURE formatStr* (t, u :ARRAY OF CHAR); - (* append formatted string. Replace the first % in t by u *) -VAR j, k :INTEGER; -BEGIN - j := 0; WHILE (t[j] # 0X) & (t[j] # "%") DO char(t[j]); INC(j) END; - IF t[j] = "%" THEN - k := 0; WHILE u[k] # 0X DO char(u[k]); INC(k) END; - INC(j); WHILE t[j] # 0X DO char(t[j]); INC(j) END - END -END formatStr; - -PROCEDURE hex* (n, width :INTEGER); - (* print width positions of n as hex string. If necessary, prefix with leading zeroes *) - (* note: if n needs more positions than width, the first hex digits are not printed *) -VAR j :INTEGER; - dig :ARRAY 9 OF CHAR; -BEGIN - ASSERT(width > 0); - ASSERT (width <= 8); - dig[width] := 0X; - REPEAT - j := n MOD 16; n := n DIV 16; - IF j < 10 THEN j := ORD("0") + j ELSE j := ORD("A") + j - 10 END; - DEC(width); dig[width] := CHR(j) - UNTIL width = 0; - str (dig); -END hex; - -PROCEDURE flush*; -(* this routine comes at the end. It won't hardly ever be called - because nl also flushes. It is present only in case you - want to write a flushed string which does not end with nl. *) -BEGIN writeChars END flush; - -(* note: global variable 'len' must be 0 on init. Within the core, bodies of imported modules - are not executed, so rely on zero initialisation by Modules.Load *) -END out. - diff --git a/programs/develop/oberon07/Samples/Linux/X11/filler/unix.ob07 b/programs/develop/oberon07/Samples/Linux/X11/filler/unix.ob07 deleted file mode 100644 index d74ed88c16..0000000000 --- a/programs/develop/oberon07/Samples/Linux/X11/filler/unix.ob07 +++ /dev/null @@ -1,74 +0,0 @@ -MODULE unix; (* connect to unix host *) -IMPORT SYSTEM, _unix; -(* provide some Oberon friendly POSIX without need for SYSTEM *) - -CONST RTLD_LAZY* = 1; - O_RDONLY* = 0; - O_NEWFILE* = 0C2H; (* O_RDWR | O_CREAT | O_EXCL *) - (* O_RDONLY=0, O_WRONLY=1, O_RDWR=2, O_CREAT=0x40, O_EXCL=0x80, O_TRUNC=0x200 *) - FD_SETSIZE* = 1024; (* fd for select() must be smaller than FD_SETSIZE *) - BIT_DEPTH* = _unix.BIT_DEPTH; - LEN_FD_SET = FD_SETSIZE DIV BIT_DEPTH; - -TYPE - timespec* = RECORD - tv_sec*, tv_usec* :INTEGER - END; - fd_set* = POINTER TO RECORD (* for select() *) - bits* :ARRAY LEN_FD_SET OF SET (* 1024 bits *) - END; - -VAR - dlopen* :PROCEDURE [linux] (name, flags :INTEGER) :INTEGER; - dlsym* :PROCEDURE [linux] (p, name :INTEGER) :INTEGER; - dlclose* :PROCEDURE [linux] (p :INTEGER) :INTEGER; - close* :PROCEDURE [linux] (fd :INTEGER) :INTEGER; - exit* :PROCEDURE [linux] (n :INTEGER); - malloc* :PROCEDURE [linux] (sz :INTEGER) :INTEGER; - -PROCEDURE open* (path :ARRAY OF CHAR; flag, perm :INTEGER) :INTEGER; -BEGIN RETURN _unix._open (SYSTEM.ADR(path[0]), flag, perm) END open; - -PROCEDURE read* (fd :INTEGER; VAR buf :ARRAY OF BYTE; len :INTEGER) :INTEGER; -BEGIN RETURN _unix._read (fd, SYSTEM.ADR(buf[0]), len) END read; - -PROCEDURE readByte* (fd :INTEGER; VAR n :BYTE) :INTEGER; -BEGIN RETURN _unix._read (fd, SYSTEM.ADR(n), 1) END readByte; - -PROCEDURE write* (fd :INTEGER; buf :ARRAY OF BYTE; len :INTEGER) :INTEGER; -BEGIN RETURN _unix._write (fd, SYSTEM.ADR(buf[0]), len) END write; - -PROCEDURE writeByte* (fd :INTEGER; n :BYTE) :INTEGER; -BEGIN RETURN _unix._write (fd, SYSTEM.ADR(n), 1) END writeByte; - - -PROCEDURE FD_ZERO* (VAR selectSet :fd_set); -VAR i :INTEGER; -BEGIN FOR i := 0 TO LEN_FD_SET-1 DO selectSet.bits[i] := {} END END FD_ZERO; - -PROCEDURE FD_SET* (fd :INTEGER; VAR selectSet :fd_set); (* set fd bit in a select() fd_set *) -BEGIN INCL(selectSet.bits[fd DIV BIT_DEPTH], fd MOD BIT_DEPTH) -END FD_SET; - -PROCEDURE select* (cnt :INTEGER; readfds, writefds, exceptfds :fd_set; timeout :timespec) :INTEGER; -VAR n1, n2, n3 :INTEGER; -BEGIN - n1 := 0; IF readfds # NIL THEN n1 := SYSTEM.ADR (readfds.bits[0]) END; - n2 := 0; IF writefds # NIL THEN n2 := SYSTEM.ADR (writefds.bits[0]) END; - n3 := 0; IF exceptfds # NIL THEN n3 := SYSTEM.ADR (exceptfds.bits[0]) END; -RETURN _unix._select (cnt, n1, n2, n3, SYSTEM.ADR(timeout)) -END select; - - -PROCEDURE finish*; -BEGIN _unix.finish; END finish; - -BEGIN - dlopen := _unix._dlopen; - dlsym := _unix._dlsym; - dlclose := _unix._dlclose; - close := _unix._close; - exit := _unix._exit; - malloc := _unix._malloc; -END unix. - diff --git a/programs/develop/oberon07/Samples/MSP430/Blink.ob07 b/programs/develop/oberon07/Samples/MSP430/Blink.ob07 deleted file mode 100644 index 0434b7e219..0000000000 --- a/programs/develop/oberon07/Samples/MSP430/Blink.ob07 +++ /dev/null @@ -1,43 +0,0 @@ -(* - -Пример для LaunchPad MSP-EXP430G2 Rev1.5 - - Мигает красный светодиод. - -*) -MODULE Blink; - -IMPORT SYSTEM, MSP430; - - -CONST - - REDLED = {0}; - - (* регистры порта P1 *) - P1OUT = 21H; - P1DIR = 22H; - - -PROCEDURE inv_bits (mem: INTEGER; bits: SET); -VAR - b: BYTE; - -BEGIN - SYSTEM.GET(mem, b); - SYSTEM.PUT8(mem, BITS(b) / bits) -END inv_bits; - - -BEGIN - (* инициализация регистра P1DIR *) - SYSTEM.PUT8(P1DIR, REDLED); - - (* бесконечный цикл *) - WHILE TRUE DO - (* изменить состояние светодиода *) - inv_bits(P1OUT, REDLED); - (* задержка *) - MSP430.Delay(800) - END -END Blink. diff --git a/programs/develop/oberon07/Samples/MSP430/Button.ob07 b/programs/develop/oberon07/Samples/MSP430/Button.ob07 deleted file mode 100644 index 2470ed4ee9..0000000000 --- a/programs/develop/oberon07/Samples/MSP430/Button.ob07 +++ /dev/null @@ -1,103 +0,0 @@ -(* - -Пример для LaunchPad MSP-EXP430G2 Rev1.5 - - Мигает зеленый светодиод. - При нажатии на кнопку P1.3, включается/выключается красный светодиод. - -*) - -MODULE Button; - -IMPORT SYSTEM, MSP430; - - -CONST - - REDLED = {0}; - GREENLED = {6}; - BUTTON = {3}; - - (* регистры порта P1 *) - P1OUT = 21H; - P1DIR = 22H; - P1IFG = 23H; - P1IE = 25H; - P1REN = 27H; - - -PROCEDURE test_bits (mem: INTEGER; bits: SET): SET; -VAR - b: BYTE; - -BEGIN - SYSTEM.GET(mem, b) - RETURN bits * BITS(b) -END test_bits; - - -PROCEDURE set_bits (mem: INTEGER; bits: SET); -VAR - b: BYTE; - -BEGIN - SYSTEM.GET(mem, b); - SYSTEM.PUT8(mem, BITS(b) + bits) -END set_bits; - - -PROCEDURE clr_bits (mem: INTEGER; bits: SET); -VAR - b: BYTE; - -BEGIN - SYSTEM.GET(mem, b); - SYSTEM.PUT8(mem, BITS(b) - bits) -END clr_bits; - - -PROCEDURE inv_bits (mem: INTEGER; bits: SET); -VAR - b: BYTE; - -BEGIN - SYSTEM.GET(mem, b); - SYSTEM.PUT8(mem, BITS(b) / bits) -END inv_bits; - - -(* обработчик прерываний *) -PROCEDURE int (priority: INTEGER; interrupt: MSP430.TInterrupt); -BEGIN - IF priority = 18 THEN (* прерывание от порта P1 *) - IF test_bits(P1IFG, BUTTON) = BUTTON THEN (* нажата кнопка *) - inv_bits(P1OUT, REDLED); (* изменить состояние светодиода *) - MSP430.Delay(500); (* задержка для отпускания кнопки *) - clr_bits(P1IFG, BUTTON) (* сбросить флаг прерывания *) - END - END -END int; - - -PROCEDURE main; -BEGIN - (* инициализация регистров порта P1 *) - SYSTEM.PUT8(P1DIR, REDLED + GREENLED); (* выход *) - set_bits(P1REN, BUTTON); (* включить подтягивающий резистор *) - set_bits(P1OUT, BUTTON); (* подтяжка к питанию *) - set_bits(P1IE, BUTTON); (* разрешить прерывания от кнопки *) - - MSP430.SetIntProc(int); (* назначить обработчик прерываний *) - MSP430.EInt; (* разрешить прерывания *) - - (* бесконечный цикл *) - WHILE TRUE DO - inv_bits(P1OUT, GREENLED); (* изменить состояние светодиода *) - MSP430.Delay(800) (* задержка *) - END -END main; - - -BEGIN - main -END Button. diff --git a/programs/develop/oberon07/Samples/MSP430/Flash.ob07 b/programs/develop/oberon07/Samples/MSP430/Flash.ob07 deleted file mode 100644 index 0b4e59bb52..0000000000 --- a/programs/develop/oberon07/Samples/MSP430/Flash.ob07 +++ /dev/null @@ -1,157 +0,0 @@ -(* - -Пример для LaunchPad MSP-EXP430G2 Rev1.5 - - Запись флэш-памяти. - При успешном завершении, включается зеленый светодиод, - иначе - красный. - -*) - -MODULE Flash; - -IMPORT SYSTEM, MSP430; - - -CONST - - REDLED = {0}; - GREENLED = {6}; - - (* регистры порта P1 *) - P1OUT = 21H; - P1DIR = 22H; - - FERASE = {1}; (* режим "стереть" *) - FWRITE = {6}; (* режим "записать" *) - - -PROCEDURE set_bits (mem: INTEGER; bits: SET); -VAR - b: BYTE; - -BEGIN - SYSTEM.GET(mem, b); - SYSTEM.PUT8(mem, BITS(b) + bits) -END set_bits; - - -PROCEDURE clr_bits (mem: INTEGER; bits: SET); -VAR - b: BYTE; - -BEGIN - SYSTEM.GET(mem, b); - SYSTEM.PUT8(mem, BITS(b) - bits) -END clr_bits; - - -(* - стирание и запись флэш-памяти - adr - адрес - value - значение для записи - mode - режим (стереть/записать) -*) -PROCEDURE Write (adr, value: INTEGER; mode: SET); -CONST - (* сторожевой таймер *) - WDTCTL = 0120H; - WDTHOLD = {7}; - WDTPW = {9, 11, 12, 14}; - - (* регистры контроллера флэш-памяти *) - FCTL1 = 0128H; - ERASE = {1}; - WRT = {6}; - - FCTL2 = 012AH; - FN0 = {0}; - FN1 = {1}; - FN2 = {2}; - FN3 = {3}; - FN4 = {4}; - FN5 = {5}; - FSSEL0 = {6}; - FSSEL1 = {7}; - - FCTL3 = 012CH; - LOCK = {4}; - - FWKEY = {8, 10, 13, 15}; - -VAR - wdt: SET; - -BEGIN - IF (mode = ERASE) OR (mode = WRT) THEN (* проверить заданный режим *) - SYSTEM.GET(WDTCTL, wdt); (* сохранить значение регистра сторожевого таймера *) - SYSTEM.PUT(WDTCTL, WDTPW + WDTHOLD); (* остановить сторожевой таймер *) - SYSTEM.PUT(FCTL2, FWKEY + FSSEL1 + FN0); (* тактовый генератор контроллера флэш-памяти = SMCLK, делитель = 2 *) - SYSTEM.PUT(FCTL3, FWKEY); (* сбросить флаг LOCK *) - SYSTEM.PUT(FCTL1, FWKEY + mode); (* установить режим (записать или стереть) *) - SYSTEM.PUT(adr, value); (* запись *) - SYSTEM.PUT(FCTL1, FWKEY); (* сбросить режим *) - SYSTEM.PUT(FCTL3, FWKEY + LOCK); (* установить LOCK *) - SYSTEM.PUT(WDTCTL, WDTPW + wdt * {0..7}) (* восстановить сторожевой таймер *) - END -END Write; - - -(* обработчик ошибок *) -PROCEDURE trap (modNum, modName, err, line: INTEGER); -BEGIN - set_bits(P1OUT, REDLED) (* включить красный светодиод *) -END trap; - - -PROCEDURE main; -CONST - seg_adr = 0FC00H; (* адрес сегмента для стирания и записи (ДОЛЖЕН БЫТЬ СВОБОДНЫМ!) *) - -VAR - adr, x, i: INTEGER; - - free: RECORD address, size: INTEGER END; - -BEGIN - (* инициализация регистров порта P1 *) - SYSTEM.PUT8(P1DIR, REDLED + GREENLED); (* выход *) - - (* выключить светодиоды *) - clr_bits(P1OUT, REDLED + GREENLED); - - MSP430.SetTrapProc(trap); (* назначить обработчик ошибок *) - - ASSERT(seg_adr MOD 512 = 0); (* адрес сегмента должен быть кратным 512 *) - - MSP430.GetFreeFlash(free.address, free.size); - - (* проверить, свободен ли сегмент *) - ASSERT(free.address <= seg_adr); - ASSERT(seg_adr + 511 <= free.address + free.size); - - Write(seg_adr, 0, FERASE); (* стереть сегмент *) - - (* записать в сегмент числа 0..255 (256 слов) *) - adr := seg_adr; - FOR i := 0 TO 255 DO - Write(adr, i, FWRITE); - INC(adr, 2) - END; - - (* проверить запись *) - adr := seg_adr; - FOR i := 0 TO 255 DO - SYSTEM.GET(adr, x); - ASSERT(x = i); (* если x # i, будет вызван обработчик ошибок *) - INC(adr, 2) - END; - - (* если нет ошибок, включить зеленый светодиод *) - set_bits(P1OUT, GREENLED) -END main; - - -BEGIN - main -END Flash. diff --git a/programs/develop/oberon07/Samples/MSP430/Restart.ob07 b/programs/develop/oberon07/Samples/MSP430/Restart.ob07 deleted file mode 100644 index 1f3f4c66aa..0000000000 --- a/programs/develop/oberon07/Samples/MSP430/Restart.ob07 +++ /dev/null @@ -1,106 +0,0 @@ -(* - -Пример для LaunchPad MSP-EXP430G2 Rev1.5 - - При нажатии на кнопку P1.3, инкрементируется - переменная-счетчик перезапусков и программа - перезапускается. - В зависимости от четности счетчика перезапусков, - включается зеленый или красный светодиод. - -*) - -MODULE Restart; - -IMPORT SYSTEM, MSP430; - - -CONST - - REDLED = {0}; - GREENLED = {6}; - BUTTON = {3}; - - (* регистры порта P1 *) - P1OUT = 21H; - P1DIR = 22H; - P1IFG = 23H; - P1IE = 25H; - P1REN = 27H; - - -VAR - - count: INTEGER; (* счетчик перезапусков *) - - -PROCEDURE set_bits (mem: INTEGER; bits: SET); -VAR - b: BYTE; - -BEGIN - SYSTEM.GET(mem, b); - SYSTEM.PUT8(mem, BITS(b) + bits) -END set_bits; - - -PROCEDURE clr_bits (mem: INTEGER; bits: SET); -VAR - b: BYTE; - -BEGIN - SYSTEM.GET(mem, b); - SYSTEM.PUT8(mem, BITS(b) - bits) -END clr_bits; - - -PROCEDURE test_bits (mem: INTEGER; bits: SET): SET; -VAR - b: BYTE; - -BEGIN - SYSTEM.GET(mem, b) - RETURN bits * BITS(b) -END test_bits; - - -(* обработчик прерываний *) -PROCEDURE int (priority: INTEGER; interrupt: MSP430.TInterrupt); -BEGIN - IF priority = 18 THEN (* прерывание от порта P1 *) - IF test_bits(P1IFG, BUTTON) = BUTTON THEN (* нажата кнопка *) - INC(count); (* увеличить счетчик *) - MSP430.Delay(500); (* задержка для отпускания кнопки *) - clr_bits(P1IFG, BUTTON); (* сбросить флаг прерывания *) - MSP430.Restart (* перезапустить программу *) - END - END -END int; - - -PROCEDURE main; -BEGIN - (* инициализация регистров порта P1 *) - SYSTEM.PUT8(P1DIR, REDLED + GREENLED); (* выход *) - set_bits(P1REN, BUTTON); (* включить подтягивающий резистор *) - set_bits(P1OUT, BUTTON); (* подтяжка к питанию *) - set_bits(P1IE, BUTTON); (* разрешить прерывания от кнопки *) - - (* выключить светодиоды *) - clr_bits(P1OUT, REDLED + GREENLED); - - MSP430.SetIntProc(int); (* назначить обработчик прерываний *) - MSP430.EInt; (* разрешить прерывания *) - - IF ODD(count) THEN - set_bits(P1OUT, GREENLED) (* нечетное - вкл. зеленый *) - ELSE - set_bits(P1OUT, REDLED) (* четное - вкл. красный *) - END - -END main; - - -BEGIN - main -END Restart. diff --git a/programs/develop/oberon07/Samples/MSP430/TimerA.ob07 b/programs/develop/oberon07/Samples/MSP430/TimerA.ob07 deleted file mode 100644 index e92090878e..0000000000 --- a/programs/develop/oberon07/Samples/MSP430/TimerA.ob07 +++ /dev/null @@ -1,118 +0,0 @@ -(* - -Пример для LaunchPad MSP-EXP430G2 Rev1.5 - - Светодиоды мигают по сигналам от таймера A - -*) - -MODULE TimerA; - -IMPORT SYSTEM, MSP430; - - -CONST - - REDLED = {0}; - GREENLED = {6}; - - (* регистры порта P1 *) - P1OUT = 21H; - P1DIR = 22H; - - - (* регистры таймера A *) - TACTL = 0160H; - - (* биты регистра TACTL *) - TAIFG = {0}; - TAIE = {1}; - TACLR = {2}; - MC0 = {4}; - MC1 = {5}; - ID0 = {6}; - ID1 = {7}; - TASSEL0 = {8}; - TASSEL1 = {9}; - - TAR = 0170H; - - TACCTL0 = 0162H; - - (* биты регистра TACCTL0 *) - CCIE = {4}; - CAP = {8}; - - TACCR0 = 0172H; - - -PROCEDURE set_bits (mem: INTEGER; bits: SET); -VAR - b: BYTE; - -BEGIN - SYSTEM.GET(mem, b); - SYSTEM.PUT8(mem, BITS(b) + bits) -END set_bits; - - -PROCEDURE clr_bits (mem: INTEGER; bits: SET); -VAR - b: BYTE; - -BEGIN - SYSTEM.GET(mem, b); - SYSTEM.PUT8(mem, BITS(b) - bits) -END clr_bits; - - -PROCEDURE inv_bits (mem: INTEGER; bits: SET); -VAR - b: BYTE; - -BEGIN - SYSTEM.GET(mem, b); - SYSTEM.PUT8(mem, BITS(b) / bits) -END inv_bits; - - -(* обработчик прерываний *) -PROCEDURE int (priority: INTEGER; interrupt: MSP430.TInterrupt); -VAR - x: SET; - -BEGIN - IF priority = 24 THEN (* прерывание от таймера A *) - SYSTEM.GET(TACTL, x); (* взять регистр TACTL *) - IF TAIFG * x = TAIFG THEN (* прерывание было *) - inv_bits(P1OUT, REDLED); (* изменить состояние светодиода *) - inv_bits(P1OUT, GREENLED); (* изменить состояние светодиода *) - SYSTEM.PUT(TACTL, x - TAIFG) (* сбросить флаг прерывания и обновить регистр TACTL *) - END - END -END int; - - -PROCEDURE main; -BEGIN - (* инициализация регистра P1DIR *) - SYSTEM.PUT8(P1DIR, REDLED + GREENLED); - - (* начальное состояние светодиодов *) - set_bits(P1OUT, GREENLED); (* включен *) - clr_bits(P1OUT, REDLED); (* выключен *) - - MSP430.SetIntProc(int); (* назначить обработчик прерываний *) - MSP430.EInt; (* разрешить прерывания *) - - (* инициализация регистров таймера A *) - SYSTEM.PUT(TAR, 0); - SYSTEM.PUT(TACCTL0, CCIE + CAP); - SYSTEM.PUT(TACCR0, 1000); - SYSTEM.PUT(TACTL, TAIE + MC0 + TASSEL0) -END main; - - -BEGIN - main -END TimerA. diff --git a/programs/develop/oberon07/Samples/MSP430/TwoTimers.ob07 b/programs/develop/oberon07/Samples/MSP430/TwoTimers.ob07 deleted file mode 100644 index 5dfcad16c9..0000000000 --- a/programs/develop/oberon07/Samples/MSP430/TwoTimers.ob07 +++ /dev/null @@ -1,143 +0,0 @@ -(* - -Пример для LaunchPad MSP-EXP430G2 Rev1.5 - - Зеленый светодиод мигает по сигналам от таймера A, - красный - по сигналам от сторожевого таймера в интервальном режиме - -*) - -MODULE TwoTimers; - -IMPORT SYSTEM, MSP430; - - -CONST - - REDLED = {0}; - GREENLED = {6}; - - (* регистры порта P1 *) - P1OUT = 21H; - P1DIR = 22H; - - - (* регистр разрешения прерываний 1 *) - IE1 = 00H; - - (* биты регистра IE1 *) - WDTIE = {0}; - NMIIE = {4}; - - - (* регистр флагов прерываний 1 *) - IFG1 = 02H; - - (* биты регистра IFG1 *) - WDTIFG = {0}; - NMIIFG = {4}; - - - WDTCTL = 0120H; (* регистр сторожевого таймера *) - - (* биты регистра WDTCTL *) - WDTIS0 = {0}; - WDTIS1 = {1}; - WDTSSEL = {2}; - WDTCNTCL = {3}; - WDTTMSEL = {4}; - WDTNMI = {5}; - WDTNMIES = {6}; - WDTHOLD = {7}; - WDTPW = {9, 11, 12, 14}; (* ключ защиты *) - - - (* регистры таймера A *) - TACTL = 0160H; - - (* биты регистра TACTL *) - TAIFG = {0}; - TAIE = {1}; - TACLR = {2}; - MC0 = {4}; - MC1 = {5}; - ID0 = {6}; - ID1 = {7}; - TASSEL0 = {8}; - TASSEL1 = {9}; - - TAR = 0170H; - - TACCTL0 = 0162H; - - (* биты регистра TACCTL0 *) - CCIE = {4}; - CAP = {8}; - - TACCR0 = 0172H; - - -PROCEDURE set_bits (mem: INTEGER; bits: SET); -VAR - b: BYTE; - -BEGIN - SYSTEM.GET(mem, b); - SYSTEM.PUT8(mem, BITS(b) + bits) -END set_bits; - - -PROCEDURE inv_bits (mem: INTEGER; bits: SET); -VAR - b: BYTE; - -BEGIN - SYSTEM.GET(mem, b); - SYSTEM.PUT8(mem, BITS(b) / bits) -END inv_bits; - - -(* обработчик прерываний *) -PROCEDURE int (priority: INTEGER; interrupt: MSP430.TInterrupt); -VAR - x: SET; - -BEGIN - IF priority = 26 THEN (* прерывание от сторожевого таймера *) - inv_bits(P1OUT, REDLED) (* изменить состояние светодиода *) - ELSIF priority = 24 THEN (* прерывание от таймера A *) - SYSTEM.GET(TACTL, x); (* взять регистр TACTL *) - IF TAIFG * x = TAIFG THEN (* прерывание было *) - inv_bits(P1OUT, GREENLED); (* изменить состояние светодиода *) - SYSTEM.PUT(TACTL, x - TAIFG) (* сбросить флаг прерывания и обновить регистр TACTL *) - END - END -END int; - - -PROCEDURE main; -BEGIN - (* инициализация регистра P1DIR *) - set_bits(P1DIR, REDLED + GREENLED); - - (* начальное состояние светодиодов - включены *) - set_bits(P1OUT, REDLED + GREENLED); - - MSP430.SetIntProc(int); (* назначить обработчик прерываний *) - MSP430.EInt; (* разрешить прерывания *) - - (* инициализация регистров таймера A *) - SYSTEM.PUT(TAR, 0); - SYSTEM.PUT(TACCTL0, CCIE + CAP); - SYSTEM.PUT(TACCR0, 1500); - SYSTEM.PUT(TACTL, TAIE + MC0 + TASSEL0); - - (* инициализация регистров сторожевого таймера *) - set_bits(IE1, WDTIE); - SYSTEM.PUT(WDTCTL, WDTPW + WDTIS1 + WDTSSEL + WDTCNTCL + WDTTMSEL) -END main; - - -BEGIN - main -END TwoTimers. diff --git a/programs/develop/oberon07/Samples/STM32CM3/Blink.ob07 b/programs/develop/oberon07/Samples/STM32CM3/Blink.ob07 deleted file mode 100644 index e2cd4939d3..0000000000 --- a/programs/develop/oberon07/Samples/STM32CM3/Blink.ob07 +++ /dev/null @@ -1,57 +0,0 @@ -(* - Пример для STM32L152C-DISCO - - В зависимости от значения константы LED, - мигает синий или зеленый светодиод. -*) - -MODULE Blink; - -IMPORT SYSTEM; - - -CONST - - GPIOB = 40020400H; - GPIOB_MODER = GPIOB; - GPIOB_BSRR = GPIOB + 18H; - - RCC = 40023800H; - RCC_AHBENR = RCC + 1CH; - - Blue = 6; (* PB6 *) - Green = 7; (* PB7 *) - - LED = Blue; - -VAR - - x: SET; - state: BOOLEAN; - - -PROCEDURE Delay (x: INTEGER); -BEGIN - REPEAT - DEC(x) - UNTIL x = 0 -END Delay; - - -BEGIN - (* подключить GPIOB *) - SYSTEM.GET(RCC_AHBENR, x); - SYSTEM.PUT(RCC_AHBENR, x + {1}); - - (* настроить PB6 или PB7 на выход *) - SYSTEM.GET(GPIOB_MODER, x); - SYSTEM.PUT(GPIOB_MODER, x - {LED * 2 - 1} + {LED * 2}); - - state := FALSE; - REPEAT - (* включить или выключить светодиод *) - SYSTEM.PUT(GPIOB_BSRR, {LED + 16 * ORD(state)}); - state := ~state; - Delay(200000) - UNTIL FALSE -END Blink. \ No newline at end of file diff --git a/programs/develop/oberon07/Samples/STM32CM3/Button.ob07 b/programs/develop/oberon07/Samples/STM32CM3/Button.ob07 deleted file mode 100644 index aee25eb014..0000000000 --- a/programs/develop/oberon07/Samples/STM32CM3/Button.ob07 +++ /dev/null @@ -1,114 +0,0 @@ -(* - Пример для STM32L152C-DISCO - - При нажатии на кнопку USER (PA0), меняется - состояние светодиодов. -*) - -MODULE Button; - -IMPORT SYSTEM; - - -CONST - - GPIOA = 40020000H; - GPIOAMODER = GPIOA; - GPIOAOTYPER = GPIOA + 04H; - GPIOAOSPEEDR = GPIOA + 08H; - GPIOAPUPDR = GPIOA + 0CH; - GPIOAIDR = GPIOA + 10H; - GPIOAODR = GPIOA + 14H; - GPIOABSRR = GPIOA + 18H; - GPIOALCKR = GPIOA + 1CH; - GPIOAAFRL = GPIOA + 20H; - GPIOAAFRH = GPIOA + 24H; - GPIOABRR = GPIOA + 28H; - - - GPIOB = 40020400H; - GPIOBMODER = GPIOB; - GPIOBOTYPER = GPIOB + 04H; - GPIOBOSPEEDR = GPIOB + 08H; - GPIOBPUPDR = GPIOB + 0CH; - GPIOBIDR = GPIOB + 10H; - GPIOBODR = GPIOB + 14H; - GPIOBBSRR = GPIOB + 18H; - GPIOBLCKR = GPIOB + 1CH; - GPIOBAFRL = GPIOB + 20H; - GPIOBAFRH = GPIOB + 24H; - GPIOBBRR = GPIOB + 28H; - - - RCC = 40023800H; - RCC_CR = RCC; - RCC_AHBENR = RCC + 1CH; - RCC_APB2ENR = RCC + 20H; - RCC_APB1ENR = RCC + 24H; - - - NVIC = 0E000E100H; - NVIC_ISER0 = NVIC; - NVIC_ISER1 = NVIC + 04H; - NVIC_ISER2 = NVIC + 08H; - - NVIC_ICER0 = NVIC + 80H; - NVIC_ICER1 = NVIC + 84H; - NVIC_ICER2 = NVIC + 88H; - - - EXTI = 040010400H; - EXTI_IMR = EXTI; - EXTI_RTSR = EXTI + 08H; - EXTI_FTSR = EXTI + 0CH; - EXTI_PR = EXTI + 14H; - - - LINE0 = {0}; - - Blue = 6; - Green = 7; - - -VAR - x: SET; - state: INTEGER; - - -(* обработчик прерываний от EXTI0 *) -PROCEDURE PushButton [22]; -BEGIN - SYSTEM.PUT(EXTI_PR, LINE0); (* сбросить флаг прерывания *) - state := (state + 1) MOD 4; - (* изменить состояние светодиодов *) - CASE state OF - |0: SYSTEM.PUT(GPIOBBSRR, {Blue + 16, Green + 16}) - |1: SYSTEM.PUT(GPIOBBSRR, {Blue, Green + 16}) - |2: SYSTEM.PUT(GPIOBBSRR, {Blue + 16, Green}) - |3: SYSTEM.PUT(GPIOBBSRR, {Blue, Green}) - END -END PushButton; - - -BEGIN - state := 0; - - (* подключить GPIOA и GPIOB *) - SYSTEM.GET(RCC_AHBENR, x); - SYSTEM.PUT(RCC_AHBENR, x + {0, 1}); - - (* настроить PB6 и PB7 на выход *) - SYSTEM.GET(GPIOBMODER, x); - SYSTEM.PUT(GPIOBMODER, x + {12, 14} - {13, 15}); - - (* настроить PA0 на вход *) - SYSTEM.GET(GPIOAMODER, x); - SYSTEM.PUT(GPIOAMODER, x - {0, 1}); - - (* разрешить прерывания от EXTI0 (позиция 6) *) - SYSTEM.PUT(NVIC_ISER0, {6}); - - (* разрешить прерывания от LINE0 по нарастающему краю импульса *) - SYSTEM.PUT(EXTI_IMR, LINE0); - SYSTEM.PUT(EXTI_RTSR, LINE0); -END Button. \ No newline at end of file diff --git a/programs/develop/oberon07/Samples/STM32CM3/LCD.ob07 b/programs/develop/oberon07/Samples/STM32CM3/LCD.ob07 deleted file mode 100644 index 7a3db33cf7..0000000000 --- a/programs/develop/oberon07/Samples/STM32CM3/LCD.ob07 +++ /dev/null @@ -1,366 +0,0 @@ -(* - Пример для STM32L152C-DISCO - - Работа со встроенным ЖКИ. - - использовано: - https://habr.com/ru/post/173709/ -*) - -MODULE LCD; - -IMPORT SYSTEM; - - -CONST - - GPIOA = 40020000H; - GPIOAMODER = GPIOA; - GPIOAOTYPER = GPIOA + 04H; - GPIOAOSPEEDR = GPIOA + 08H; - GPIOAPUPDR = GPIOA + 0CH; - GPIOAIDR = GPIOA + 10H; - GPIOAODR = GPIOA + 14H; - GPIOABSRR = GPIOA + 18H; - GPIOALCKR = GPIOA + 1CH; - GPIOAAFRL = GPIOA + 20H; - GPIOAAFRH = GPIOA + 24H; - GPIOABRR = GPIOA + 28H; - - - GPIOB = 40020400H; - GPIOBMODER = GPIOB; - GPIOBOTYPER = GPIOB + 04H; - GPIOBOSPEEDR = GPIOB + 08H; - GPIOBPUPDR = GPIOB + 0CH; - GPIOBIDR = GPIOB + 10H; - GPIOBODR = GPIOB + 14H; - GPIOBBSRR = GPIOB + 18H; - GPIOBLCKR = GPIOB + 1CH; - GPIOBAFRL = GPIOB + 20H; - GPIOBAFRH = GPIOB + 24H; - GPIOBBRR = GPIOB + 28H; - - - GPIOC = 40020800H; - GPIOCMODER = GPIOC; - GPIOCOTYPER = GPIOC + 04H; - GPIOCOSPEEDR = GPIOC + 08H; - GPIOCPUPDR = GPIOC + 0CH; - GPIOCIDR = GPIOC + 10H; - GPIOCODR = GPIOC + 14H; - GPIOCBSRR = GPIOC + 18H; - GPIOCLCKR = GPIOC + 1CH; - GPIOCAFRL = GPIOC + 20H; - GPIOCAFRH = GPIOC + 24H; - GPIOCBRR = GPIOC + 28H; - - - RCC = 40023800H; - RCC_CR = RCC; - RCC_AHBENR = RCC + 1CH; - RCC_APB2ENR = RCC + 20H; - RCC_APB1ENR = RCC + 24H; - RCC_CSR = RCC + 34H; - - - PWR = 40007000H; - PWR_CR = PWR; - - - LCD = 40002400H; - LCD_CR = LCD; - LCD_FCR = LCD + 04H; - LCD_SR = LCD + 08H; - LCD_RAM = LCD + 14H; - - - AFM = 2; - - AF11 = 11; - - PinsA = {1..3, 8..10, 15}; - PinsB = {3..5, 8..15}; - PinsC = {0..3, 6..11}; - - A = 0; H = 7; - B = 1; J = 8; - C = 2; K = 9; - D = 3; M = 10; - E = 4; N = 11; - F = 5; P = 12; - G = 6; Q = 13; - - DP = 14; COLON = 15; BAR = 16; - - -VAR - display: ARRAY 6, 17 OF INTEGER; - - digits: ARRAY 10 OF SET; - - -PROCEDURE SetPinsMode (reg: INTEGER; pins: SET; mode: INTEGER); -VAR - x: SET; - pin: INTEGER; - -BEGIN - mode := mode MOD 4; - SYSTEM.GET(reg, x); - FOR pin := 0 TO 30 BY 2 DO - IF (pin DIV 2) IN pins THEN - x := x - {pin, pin + 1} + BITS(LSL(mode, pin)) - END - END; - SYSTEM.PUT(reg, x) -END SetPinsMode; - - -PROCEDURE SRBits (adr: INTEGER; setbits, resetbits: SET); -VAR - x: SET; - -BEGIN - SYSTEM.GET(adr, x); - SYSTEM.PUT(adr, x - resetbits + setbits) -END SRBits; - - -PROCEDURE SetBits (adr: INTEGER; bits: SET); -VAR - x: SET; - -BEGIN - SYSTEM.GET(adr, x); - SYSTEM.PUT(adr, x + bits) -END SetBits; - - -PROCEDURE ResetBits (adr: INTEGER; bits: SET); -VAR - x: SET; - -BEGIN - SYSTEM.GET(adr, x); - SYSTEM.PUT(adr, x - bits) -END ResetBits; - - -PROCEDURE TestBits (adr: INTEGER; bits: SET): BOOLEAN; -VAR - x: SET; - -BEGIN - SYSTEM.GET(adr, x); - RETURN x * bits = bits -END TestBits; - - -PROCEDURE Init; -VAR - i, j: INTEGER; - seg: ARRAY 30 OF INTEGER; - -BEGIN - FOR i := 0 TO 29 DO - seg[i] := i - END; - - FOR i := 3 TO 11 DO - seg[i] := i + 4 - END; - - seg[18] := 17; - seg[19] := 16; - - FOR i := 20 TO 23 DO - seg[i] := i - 2 - END; - - j := 0; - FOR i := 0 TO 5 DO - display[i, A] := 256 + seg[28 - j]; - display[i, B] := 0 + seg[28 - j]; - display[i, C] := 256 + seg[j + 1]; - display[i, D] := 256 + seg[j]; - display[i, E] := 0 + seg[j]; - display[i, F] := 256 + seg[29 - j]; - display[i, G] := 0 + seg[29 - j]; - display[i, H] := 768 + seg[29 - j]; - display[i, J] := 768 + seg[28 - j]; - display[i, K] := 512 + seg[28 - j]; - display[i, M] := 0 + seg[j + 1]; - display[i, N] := 768 + seg[j]; - display[i, P] := 512 + seg[j]; - display[i, Q] := 512 + seg[29 - j]; - INC(j, 2) - END; - - display[0, DP] := 768 + 1; - display[1, DP] := 768 + 7; - display[2, DP] := 768 + 9; - display[3, DP] := 768 + 11; - - display[0, COLON] := 512 + 1; - display[1, COLON] := 512 + 7; - display[2, COLON] := 512 + 9; - display[3, COLON] := 512 + 11; - - display[0, BAR] := 768 + 15; - display[1, BAR] := 512 + 15; - display[2, BAR] := 768 + 13; - display[3, BAR] := 512 + 13; - - digits[0] := {A, B, C, D, E, F}; - digits[1] := {B, C}; - digits[2] := {A, B, M, G, E, D}; - digits[3] := {A, B, M, G, C, D}; - digits[4] := {F, G, M, B, C}; - digits[5] := {A, F, G, M, C, D}; - digits[6] := {A, F, G, M, C, D, E}; - digits[7] := {F, A, B, C}; - digits[8] := {A, B, C, D, E, F, G, M}; - digits[9] := {A, B, C, D, F, G, M}; -END Init; - - -PROCEDURE ResetSeg (seg: INTEGER); -BEGIN - ResetBits(LCD_RAM + (seg DIV 256) * 2 * 4, {seg MOD 256}) -END ResetSeg; - - -PROCEDURE SetSeg (seg: INTEGER); -BEGIN - SetBits(LCD_RAM + (seg DIV 256) * 2 * 4, {seg MOD 256}) -END SetSeg; - - -PROCEDURE Digit (pos, dgt: INTEGER); -VAR - s: SET; - i: INTEGER; - -BEGIN - s := digits[dgt]; - FOR i := 0 TO 13 DO - IF i IN s THEN - SetSeg(display[pos, i]) - ELSE - ResetSeg(display[pos, i]) - END - END -END Digit; - - -PROCEDURE WhileBits (adr: INTEGER; bits: SET); -BEGIN - WHILE TestBits(adr, bits) DO END -END WhileBits; - - -PROCEDURE UntilBits (adr: INTEGER; bits: SET); -BEGIN - REPEAT UNTIL TestBits(adr, bits) -END UntilBits; - - -PROCEDURE main; -VAR - i: INTEGER; - -BEGIN - Init; - - (* подключить GPIOA, GPIOB, GPIOC *) - SetBits(RCC_AHBENR, {0, 1, 2}); - - (* настроить на режим альтернативной функции *) - SetPinsMode(GPIOAMODER, PinsA, AFM); - - (* 400 кГц *) - SetPinsMode(GPIOAOSPEEDR, PinsA, 0); - - (* без подтягивающих резисторов *) - SetPinsMode(GPIOAPUPDR, PinsA, 0); - - (* режим push-pull *) - ResetBits(GPIOAOTYPER, PinsA); - - (* альтернативная функция AF11 = 0BH *) - SYSTEM.PUT(GPIOAAFRL, 0BBB0H); - SYSTEM.PUT(GPIOAAFRH, 0B0000BBBH); - - (* аналогично для GPIOB *) - SetPinsMode(GPIOBMODER, PinsB, AFM); - SetPinsMode(GPIOBOSPEEDR, PinsB, 0); - SetPinsMode(GPIOBPUPDR, PinsB, 0); - ResetBits(GPIOBOTYPER, PinsB); - SYSTEM.PUT(GPIOBAFRL, 000BBB000H); - SYSTEM.PUT(GPIOBAFRH, 0BBBBBBBBH); - - (* аналогично для GPIOC *) - SetPinsMode(GPIOCMODER, PinsC, AFM); - SetPinsMode(GPIOCOSPEEDR, PinsC, 0); - SetPinsMode(GPIOCPUPDR, PinsC, 0); - ResetBits(GPIOCOTYPER, PinsC); - SYSTEM.PUT(GPIOCAFRL, 0BB00BBBBH); - SYSTEM.PUT(GPIOCAFRH, 00000BBBBH); - - (* подключить контроллер ЖКИ *) - SetBits(RCC_APB1ENR, {9, 28}); (* LCDEN = {9}; PWREN = {28} *) - - (* разрешить запись в регистр RCC_CSR *) - SetBits(PWR_CR, {8}); (* DBP = {8} *) - - (* сбросить источник тактирования *) - SetBits(RCC_CSR, {23}); (* RTCRST = {23} *) - - (* выбрать новый источник *) - ResetBits(RCC_CSR, {23}); (* RTCRST = {23} *) - - (* включить НЧ генератор *) - SetBits(RCC_CSR, {8}); (* LSEON = {8} *) - - (* ждать готовность НЧ генератора *) - UntilBits(RCC_CSR, {9}); (* LSERDY = {9} *) - - (* выбрать НЧ генератор как источник тактирования *) - SRBits(RCC_CSR, {16}, {17}); (* RCC_CSR[17:16] := 01b *) - - (* настроить контроллер ЖКИ *) - SRBits(LCD_CR, {2, 3, 6, 7}, {4, 5}); (* MUX_SEG = {7}; BIAS1 = {6}; BIAS0 = {5}; DUTY2 = {4}; DUTY1 = {3}; DUTY0 = {2} *) - - (* Установить значения коэффициентов деления частоты тактового сигнала LCDCLK *) - SRBits(LCD_FCR, {11, 18, 24}, {10..12, 18..25}); (* LCD_FCR[12:10] := 010b; LCD_FCR[21:18] := 0001b; LCD_FCR[25:22] := 0100b *) - - (* ждать синхронизацию регистра LCD_FCR *) - UntilBits(LCD_SR, {5}); (* FCRSF = {5} *) - - (* выбрать внутренний источник напряжения для ЖКИ и разрешить его работу *) - SRBits(LCD_CR, {0}, {1}); (* LCD_CR_VSEL = {1}; LCD_CR_LCDEN = {0} *) - - (* ждать готовность контроллера ЖКИ *) - UntilBits(LCD_SR, {0, 4}); (* LCD_SR_RDY = {4}; LCD_SR_ENS = {0} *) - - (* ждать завершение предыдущей записи *) - WhileBits(LCD_SR, {2}); (* LCD_SR_UDR = {2} *) - - (* начать запись *) - FOR i := 0 TO 5 DO - Digit(i, i + 1) (* 123456 *) - END; - - SetSeg(display[1, DP]); (* 12.3456 *) - SetSeg(display[3, COLON]); (* 12.34:56 *) - SetSeg(display[0, BAR]); (* 12.34:56_ *) - - (* завершить запись *) - SetBits(LCD_SR, {2}) (* LCD_SR_UDR = {2} *) -END main; - - -BEGIN - main -END LCD. \ No newline at end of file diff --git a/programs/develop/oberon07/Samples/STM32CM3/SysTick.ob07 b/programs/develop/oberon07/Samples/STM32CM3/SysTick.ob07 deleted file mode 100644 index 7db04948f1..0000000000 --- a/programs/develop/oberon07/Samples/STM32CM3/SysTick.ob07 +++ /dev/null @@ -1,79 +0,0 @@ -(* - Пример для STM32L152C-DISCO - - Светодиоды мигают по прерыванию от системного таймера. -*) - -MODULE SysTick; - -IMPORT SYSTEM; - - -CONST - - GPIOB = 40020400H; - GPIOBMODER = GPIOB; - GPIOBOTYPER = GPIOB + 04H; - GPIOBOSPEEDR = GPIOB + 08H; - GPIOBPUPDR = GPIOB + 0CH; - GPIOBIDR = GPIOB + 10H; - GPIOBODR = GPIOB + 14H; - GPIOBBSRR = GPIOB + 18H; - GPIOBLCKR = GPIOB + 1CH; - GPIOBAFRL = GPIOB + 20H; - GPIOBAFRH = GPIOB + 24H; - GPIOBBRR = GPIOB + 28H; - - - RCC = 40023800H; - RCC_CR = RCC; - RCC_AHBENR = RCC + 1CH; - RCC_APB2ENR = RCC + 20H; - RCC_APB1ENR = RCC + 24H; - - - STK = 0E000E010H; - STK_CTRL = STK; - ENABLE = {0}; - TICKINT = {1}; - CLKSOURCE = {2}; - - STK_LOAD = STK + 04H; - STK_VAL = STK + 08H; - STK_CALIB = STK + 0CH; - - - Blue = 6; - Green = 7; - - -VAR - - x: SET; state: BOOLEAN; - - -(* обработчик прерываний от System tick timer *) -PROCEDURE tick [15]; -BEGIN - state := ~state; - (* включить или выключить светодиоды *) - SYSTEM.PUT(GPIOBBSRR, {Blue + 16 * ORD(state)}); - SYSTEM.PUT(GPIOBBSRR, {Green + 16 * ORD(state)}) -END tick; - - -BEGIN - state := FALSE; - - (* подключить GPIOB *) - SYSTEM.GET(RCC_AHBENR, x); - SYSTEM.PUT(RCC_AHBENR, x + {1}); - - (* настроить PB6 и PB7 на выход *) - SYSTEM.GET(GPIOBMODER, x); - SYSTEM.PUT(GPIOBMODER, x + {12, 14} - {13, 15}); - - (* настроить и запустить SysTick *) - SYSTEM.PUT(STK_LOAD, 1048576); - SYSTEM.PUT(STK_CTRL, ENABLE + TICKINT + CLKSOURCE); -END SysTick. \ No newline at end of file diff --git a/programs/develop/oberon07/Samples/STM32CM3/TIM67.ob07 b/programs/develop/oberon07/Samples/STM32CM3/TIM67.ob07 deleted file mode 100644 index 64b536ea96..0000000000 --- a/programs/develop/oberon07/Samples/STM32CM3/TIM67.ob07 +++ /dev/null @@ -1,143 +0,0 @@ -(* - Пример для STM32L152C-DISCO - - Синий светодиод мигает по прерыванию от таймера TIM6, - зеленый - от TIM7. -*) - -MODULE TIM67; - -IMPORT SYSTEM; - - -CONST - - GPIOB = 40020400H; - GPIOBMODER = GPIOB; - GPIOBOTYPER = GPIOB + 04H; - GPIOBOSPEEDR = GPIOB + 08H; - GPIOBPUPDR = GPIOB + 0CH; - GPIOBIDR = GPIOB + 10H; - GPIOBODR = GPIOB + 14H; - GPIOBBSRR = GPIOB + 18H; - GPIOBLCKR = GPIOB + 1CH; - GPIOBAFRL = GPIOB + 20H; - GPIOBAFRH = GPIOB + 24H; - GPIOBBRR = GPIOB + 28H; - - - RCC = 40023800H; - RCC_CR = RCC; - RCC_AHBENR = RCC + 1CH; - RCC_APB2ENR = RCC + 20H; - RCC_APB1ENR = RCC + 24H; - - - TIM6 = 40001000H; - TIM6_CR1 = TIM6; - CEN = {0}; - UDIS = {1}; - URS = {2}; - OPM = {3}; - ARPE = {7}; - - TIM6_CR2 = TIM6 + 04H; - - TIM6_DIER = TIM6 + 0CH; - UIE = {0}; - - TIM6_SR = TIM6 + 10H; - UIF = {0}; - - TIM6_EGR = TIM6 + 14H; - UG = {0}; - - TIM6_CNT = TIM6 + 24H; - TIM6_PSC = TIM6 + 28H; - TIM6_ARR = TIM6 + 2CH; - - - TIM7 = 40001400H; - TIM7_CR1 = TIM7; - TIM7_CR2 = TIM7 + 04H; - TIM7_DIER = TIM7 + 0CH; - TIM7_SR = TIM7 + 10H; - TIM7_EGR = TIM7 + 14H; - TIM7_CNT = TIM7 + 24H; - TIM7_PSC = TIM7 + 28H; - TIM7_ARR = TIM7 + 2CH; - - - NVIC = 0E000E100H; - NVIC_ISER0 = NVIC; - NVIC_ISER1 = NVIC + 04H; - NVIC_ISER2 = NVIC + 08H; - - NVIC_ICER0 = NVIC + 80H; - NVIC_ICER1 = NVIC + 84H; - NVIC_ICER2 = NVIC + 88H; - - - BLUELED = 6; - GREENLED = 7; - - -VAR - x: SET; - state1, state2: BOOLEAN; - - -(* обработчик прерываний от TIM6 *) -PROCEDURE tim6 [59]; -BEGIN - SYSTEM.PUT(TIM6_SR, 0); (* сбросить флаг прерывания *) - state1 := ~state1; - (* включить или выключить синий светодиод *) - SYSTEM.PUT(GPIOBBSRR, {BLUELED + 16 * ORD(state1)}) - -END tim6; - - -(* обработчик прерываний от TIM7 *) -PROCEDURE tim7 [60]; -BEGIN - SYSTEM.PUT(TIM7_SR, 0); (* сбросить флаг прерывания *) - state2 := ~state2; - (* включить или выключить зеленый светодиод *) - SYSTEM.PUT(GPIOBBSRR, {GREENLED + 16 * ORD(state2)}) -END tim7; - - -BEGIN - state1 := FALSE; - state2 := FALSE; - - (* подключить GPIOB *) - SYSTEM.GET(RCC_AHBENR, x); - SYSTEM.PUT(RCC_AHBENR, x + {1}); - - (* подключить TIM6 и TIM7 *) - SYSTEM.GET(RCC_APB1ENR, x); - SYSTEM.PUT(RCC_APB1ENR, x + {4, 5}); - - (* настроить PB6 и PB7 на выход *) - SYSTEM.GET(GPIOBMODER, x); - SYSTEM.PUT(GPIOBMODER, x + {12, 14} - {13, 15}); - - (* разрешить прерывания от таймеров TIM6 (позиция 43) и TIM7 (позиция 44) *) - SYSTEM.PUT(NVIC_ISER1, {11, 12}); - - (* настроить и запустить TIM6 *) - SYSTEM.PUT(TIM6_ARR, 31); - SYSTEM.PUT(TIM6_PSC, 65535); - SYSTEM.PUT(TIM6_DIER, UIE); - SYSTEM.GET(TIM6_CR1, x); - SYSTEM.PUT(TIM6_CR1, x + CEN - (UDIS + URS + OPM + ARPE)); - - (* настроить и запустить TIM7 *) - SYSTEM.PUT(TIM7_ARR, 8000); - SYSTEM.PUT(TIM7_PSC, 80); - SYSTEM.PUT(TIM7_DIER, UIE); - SYSTEM.GET(TIM7_CR1, x); - SYSTEM.PUT(TIM7_CR1, x + CEN - (UDIS + URS + OPM + ARPE)); -END TIM67. \ No newline at end of file diff --git a/programs/develop/oberon07/Samples/Windows/Console/Doors.ob07 b/programs/develop/oberon07/Samples/Windows/Console/Doors.ob07 deleted file mode 100644 index 838137411e..0000000000 --- a/programs/develop/oberon07/Samples/Windows/Console/Doors.ob07 +++ /dev/null @@ -1,58 +0,0 @@ -(* - adapted to Oberon-07 by 0CodErr, KolibriOS team - *) -(* - There are 100 doors in a row that are all initially closed. - You make 100 passes by the doors. - The first time through, visit every door and toggle the door (if the door is closed, open it; if it is open, close it). - The second time, only visit every 2nd door (door #2, #4, #6, ...), and toggle it. - The third time, visit every 3rd door (door #3, #6, #9, ...), etc, until you only visit the 100th door. - What state are the doors in after the last pass? Which are open, which are closed? -*) -MODULE Doors; - -IMPORT In, Out, Console; - - -CONST - CLOSED = FALSE; - OPEN = TRUE; - - -TYPE - List = ARRAY 101 OF BOOLEAN; - - -VAR - Doors: List; - I, J: INTEGER; - - -BEGIN - Console.open; - - FOR I := 1 TO 100 DO - FOR J := 1 TO 100 DO - IF J MOD I = 0 THEN - IF Doors[J] = CLOSED THEN - Doors[J] := OPEN - ELSE - Doors[J] := CLOSED - END - END - END - END; - FOR I := 1 TO 100 DO - Out.Int(I, 3); - Out.String(" is "); - IF Doors[I] = CLOSED THEN - Out.String("Closed.") - ELSE - Out.String("Open.") - END; - Out.Ln - END; - In.Ln; - - Console.exit(TRUE) -END Doors. \ No newline at end of file diff --git a/programs/develop/oberon07/Samples/Windows/Console/HeapSort.ob07 b/programs/develop/oberon07/Samples/Windows/Console/HeapSort.ob07 deleted file mode 100644 index 745970ee4d..0000000000 --- a/programs/develop/oberon07/Samples/Windows/Console/HeapSort.ob07 +++ /dev/null @@ -1,101 +0,0 @@ -(* - adapted to Oberon-07 by 0CodErr, KolibriOS team - *) -(* ********* Zonnon online collection *********** - * Sorting: Heap Sort (Chapter 2, Example 2.8) - * - * This example is a part of Prof. Nikalus Wirth's book - * www.zonnon.ethz.ch/usergroup - * (c) ETH Zurich - *) - -MODULE HeapSort; - -IMPORT In, Out, Console; - - -CONST - MAX_SIZE = 20; - - -TYPE - DefaultArray = ARRAY MAX_SIZE OF INTEGER; - - -VAR - MyArray: DefaultArray; - - (***** Implementation *****) - -PROCEDURE sift(VAR a: DefaultArray; L,R:INTEGER); -VAR - i, j, x: INTEGER; - -BEGIN - i := L; j:= 2 * L; x:= a[L]; - IF (j < R) & (a[j] < a[j + 1]) THEN j := j + 1 END; - WHILE (j <= R) & (x < a[j]) DO - a[i] := a[j]; i := j; j := 2 * j; - IF (j < R) & (a[j] < a[j + 1]) THEN j := j + 1 END - END; - a[i] := x -END sift; - - -PROCEDURE HeapSort(VAR a: DefaultArray; n: INTEGER); -VAR - L, R, x: INTEGER; - -BEGIN - L := (n DIV 2); R := n - 1; - WHILE L > 0 DO L := L - 1; sift(a, L, R) END; - WHILE R > 0 DO - x := a[0]; a[0] := a[R]; a[R]:= x; - R := R - 1; sift(a, L, R) - END -END HeapSort; - -(***** Example support *****) - -PROCEDURE FillTheArray; -VAR - i: INTEGER; - -BEGIN - FOR i := 0 TO MAX_SIZE - 1 DO - MyArray[i] := ABS(10 - i) - END -END FillTheArray; - - -PROCEDURE PrintTheArray; -VAR - i: INTEGER; - -BEGIN - Out.String("Array:"); Out.Ln; - FOR i := 0 TO MAX_SIZE - 1 DO - Out.Int(MyArray[i], 2); Out.String(", ") - END; - Out.Ln -END PrintTheArray; - - -PROCEDURE Execute; -BEGIN - HeapSort(MyArray, MAX_SIZE) -END Execute; - - -BEGIN - Console.open; - - Out.String("Example 2.8 (Heap sort)"); Out.Ln; - FillTheArray; - PrintTheArray; - Execute; - PrintTheArray; - Out.String("Press Enter to continue"); In.Ln; - - Console.exit(TRUE) -END HeapSort. \ No newline at end of file diff --git a/programs/develop/oberon07/Samples/Windows/Console/Hello.ob07 b/programs/develop/oberon07/Samples/Windows/Console/Hello.ob07 deleted file mode 100644 index e40d3fe04f..0000000000 --- a/programs/develop/oberon07/Samples/Windows/Console/Hello.ob07 +++ /dev/null @@ -1,13 +0,0 @@ -MODULE Hello; - -IMPORT Console, In, Out; - - -BEGIN - Console.open; - - Out.String("Hello, world!"); - In.Ln; - - Console.exit(TRUE) -END Hello. diff --git a/programs/develop/oberon07/Samples/Windows/Console/HelloRus.ob07 b/programs/develop/oberon07/Samples/Windows/Console/HelloRus.ob07 deleted file mode 100644 index 5036196bb8..0000000000 --- a/programs/develop/oberon07/Samples/Windows/Console/HelloRus.ob07 +++ /dev/null @@ -1,26 +0,0 @@ -MODULE HelloRus; - -IMPORT Console, In, Out; - - -PROCEDURE main; -VAR - str: ARRAY 10 OF WCHAR; - -BEGIN - str := "Привет!"; - Out.StringW(str); Out.Ln; - str[2] := "е"; - str[5] := "д"; - Out.StringW(str) -END main; - - -BEGIN - Console.open; - - main; - In.Ln; - - Console.exit(TRUE) -END HelloRus. \ No newline at end of file diff --git a/programs/develop/oberon07/Samples/Windows/Console/MagicSquares.ob07 b/programs/develop/oberon07/Samples/Windows/Console/MagicSquares.ob07 deleted file mode 100644 index 8dce198345..0000000000 --- a/programs/develop/oberon07/Samples/Windows/Console/MagicSquares.ob07 +++ /dev/null @@ -1,48 +0,0 @@ -(* - adapted to Oberon-07 by 0CodErr, KolibriOS team - *) -(* ********* Zonnon online collection *********** - * Magic Squares - * - * This example is a part of Prof. Nikalus Wirth's book - * www.zonnon.ethz.ch/usergroup - * (c) ETH Zurich - *) - -MODULE MagicSquares; (*NW 11.8.97*) - -IMPORT In, Out, Console; - - -PROCEDURE Generate; (*magic square of order 3, 5, 7, ... *) -VAR - i, j, x, nx, nsq, n: INTEGER; - M: ARRAY 13, 13 OF INTEGER; - -BEGIN - Out.String("Enter magic square order(3, 5, 7, ..., 13): "); In.Int(n); nsq := n * n; x := 0; - i := n DIV 2; j := n - 1; - WHILE x < nsq DO - nx := n + x; j := (j - 1) MOD n; INC(x); - Out.Int(i, 1); Out.Char(9X); - Out.Int(j, 1); Out.Ln; - M[i, j] := x; - WHILE x < nx DO - i := (i + 1) MOD n; j := (j + 1) MOD n; - INC(x); M[i, j] := x - END - END; - FOR i := 0 TO n - 1 DO - FOR j := 0 TO n - 1 DO Out.Int(M[i, j], 6) END; - Out.Ln - END -END Generate; - -BEGIN - Console.open; - - Generate; - Out.String("Press Enter to continue"); In.Ln; - - Console.exit(TRUE) -END MagicSquares. \ No newline at end of file diff --git a/programs/develop/oberon07/Samples/Windows/Console/MultiplicationTables.ob07 b/programs/develop/oberon07/Samples/Windows/Console/MultiplicationTables.ob07 deleted file mode 100644 index 434e3724d4..0000000000 --- a/programs/develop/oberon07/Samples/Windows/Console/MultiplicationTables.ob07 +++ /dev/null @@ -1,52 +0,0 @@ -(* - adapted to Oberon-07 by 0CodErr, KolibriOS team - *) -(* - Produce a formatted NxN multiplication table - Only print the top half triangle of products -*) - -MODULE MultiplicationTables; - -IMPORT In, Out, Console; - - -CONST - N = 18; - - -VAR - I, J: INTEGER; - - -BEGIN - Console.open; - - FOR J := 1 TO N - 1 DO - Out.Int(J, 3); - Out.String(" ") - END; - Out.Int(N, 3); - Out.Ln; - FOR J := 0 TO N - 1 DO - Out.String("----") - END; - Out.String("+"); - Out.Ln; - FOR I := 1 TO N DO - FOR J := 1 TO N DO - IF J < I THEN - Out.String(" ") - ELSE - Out.Int(I * J, 3); - Out.String(" ") - END - END; - Out.String("| "); - Out.Int(I, 2); - Out.Ln - END; - In.Ln; - - Console.exit(TRUE) -END MultiplicationTables. \ No newline at end of file diff --git a/programs/develop/oberon07/Samples/Windows/Console/SierpinskiCarpet.ob07 b/programs/develop/oberon07/Samples/Windows/Console/SierpinskiCarpet.ob07 deleted file mode 100644 index 53e48b1eb2..0000000000 --- a/programs/develop/oberon07/Samples/Windows/Console/SierpinskiCarpet.ob07 +++ /dev/null @@ -1,75 +0,0 @@ -(* - adapted to Oberon-07 by 0CodErr, KolibriOS team - *) -MODULE SierpinskiCarpet; - -IMPORT In, Out, Console; - - -VAR - order: INTEGER; - - -PROCEDURE pow(b, n: INTEGER): INTEGER; -VAR - i, res: INTEGER; - -BEGIN - res := 1; - FOR i := 1 TO n DO - res := res * b - END - - RETURN res -END pow; - - -PROCEDURE in_carpet(x, y: INTEGER): BOOLEAN; -VAR - res, exit: BOOLEAN; - -BEGIN - exit := FALSE; - res := TRUE; - WHILE (x > 0) & (y > 0) & (exit = FALSE) DO - IF (x MOD 3 = 1) & (y MOD 3 = 1) THEN - res := FALSE; - exit := TRUE - END; - y := y DIV 3; - x := x DIV 3 - END - - RETURN res -END in_carpet; - - -PROCEDURE PrintSierpinski(n: INTEGER); -VAR - i, j, l: INTEGER; - -BEGIN - l := pow(3, n) - 1; - FOR i := 0 TO l DO - FOR j := 0 TO l DO - IF in_carpet(i, j) THEN - Out.Char("#") - ELSE - Out.Char(" ") - END - END; - Out.Ln - END -END PrintSierpinski; - - -BEGIN - Console.open; - - Out.String("Input carpet order(0..3):"); - In.Int(order); - PrintSierpinski(order); - In.Ln; - - Console.exit(TRUE) -END SierpinskiCarpet. \ No newline at end of file diff --git a/programs/develop/oberon07/Samples/Windows/Console/SierpinskiTriangle.ob07 b/programs/develop/oberon07/Samples/Windows/Console/SierpinskiTriangle.ob07 deleted file mode 100644 index c72607ffec..0000000000 --- a/programs/develop/oberon07/Samples/Windows/Console/SierpinskiTriangle.ob07 +++ /dev/null @@ -1,44 +0,0 @@ -(* - adapted to Oberon-07 by 0CodErr, KolibriOS team - *) -MODULE SierpinskiTriangle; - -IMPORT In, Out, Console; - - -VAR - order: INTEGER; - - -PROCEDURE PrintSierpinski(order: INTEGER); -VAR - x, y, k, size: INTEGER; - -BEGIN - size := LSL(1, order) - 1; - FOR y := size TO 0 BY -1 DO - FOR k := 1 TO y DO - Out.Char(" ") - END; - FOR x := 0 TO size - y DO - IF BITS(x) * BITS(y) = {} THEN - Out.String("* ") - ELSE - Out.String(" ") - END - END; - Out.Ln - END -END PrintSierpinski; - - -BEGIN - Console.open; - - Out.String("Input triangle order(0..5):"); - In.Int(order); - PrintSierpinski(order); - In.Ln; - - Console.exit(TRUE) -END SierpinskiTriangle. \ No newline at end of file diff --git a/programs/develop/oberon07/Samples/Windows/Console/Sieve.ob07 b/programs/develop/oberon07/Samples/Windows/Console/Sieve.ob07 deleted file mode 100644 index a0a6460f38..0000000000 --- a/programs/develop/oberon07/Samples/Windows/Console/Sieve.ob07 +++ /dev/null @@ -1,51 +0,0 @@ -(* - adapted to Oberon-07 by 0CodErr, KolibriOS team - *) - -(* This was taken from the CRITICAL MASS MODULA-3 examples *) - -(* The "Sieve" program demonstrates the use of arrays, - loops and conditionals. *) - -MODULE Sieve; - -IMPORT In, Out, Console; - -(* Search in interval 2 to 1000 for prime numbers. *) -CONST - LastNum = 1000; - -(* "prime" is an array of booleans ranging from 2 to "LastNum". *) -VAR - prime: ARRAY LastNum + 2 OF BOOLEAN; - i, j: INTEGER; - -BEGIN - Console.open; - - Out.String("Primes in range 2.."); Out.Int(LastNum, 1); Out.Char(":"); Out.Ln; -(* Initialize all elements of the array to "TRUE". - (Note that we could have initialized the array during - the assignment.) *) - FOR i := 2 TO LastNum DO - prime[i] := TRUE - END; -(* Loop through all integers between 2 and "LastNum". Print each prime - number, starting from 2 and mark all numbers that are divisible by - that prime number to "FALSE". Repeat the step until we've exhausted - all the numbers in the interval.*) - FOR i := 2 TO LastNum DO - IF prime[i] THEN - Out.Int(i, 3); - Out.Char(" "); - FOR j := i TO LastNum DO - IF j MOD i = 0 THEN - prime[j] := FALSE - END - END - END - END; - Out.Ln; In.Ln; - - Console.exit(TRUE) -END Sieve. \ No newline at end of file diff --git a/programs/develop/oberon07/Samples/Windows/Console/SpiralMatrix.ob07 b/programs/develop/oberon07/Samples/Windows/Console/SpiralMatrix.ob07 deleted file mode 100644 index 223952085c..0000000000 --- a/programs/develop/oberon07/Samples/Windows/Console/SpiralMatrix.ob07 +++ /dev/null @@ -1,56 +0,0 @@ -(* - adapted to Oberon-07 by 0CodErr, KolibriOS team - *) -(* - Produce a spiral array. - A spiral array is a square arrangement of the first (Width * Height) natural numbers, - where the numbers increase sequentially as you go around the edges of the array spiraling inwards. -*) - -MODULE SpiralMatrix; - -IMPORT In, Out, Console; - - -VAR - Width, Height: INTEGER; - - -PROCEDURE spiral(w, h, x, y: INTEGER): INTEGER; -VAR - res: INTEGER; - -BEGIN - IF y # 0 THEN - res := w + spiral(h - 1, w, y - 1, w - x - 1) - ELSE - res := x - END - RETURN res -END spiral; - - -PROCEDURE print_spiral(w, h: INTEGER); -VAR - i, j: INTEGER; - -BEGIN - FOR i := 0 TO h - 1 DO - FOR j := 0 TO w - 1 DO - Out.Int(spiral(w, h, j, i), 4) - END; - Out.Ln - END -END print_spiral; - - -BEGIN - Console.open; - - Out.String("Input width of matrix(1, 2, 3, ...):"); In.Int(Width); - Out.String("Input height of matrix:(1, 2, 3, ...)"); In.Int(Height); - print_spiral(Width, Height); - In.Ln; - - Console.exit(TRUE) -END SpiralMatrix. \ No newline at end of file diff --git a/programs/develop/oberon07/Samples/Windows/Console/TempConv.ob07 b/programs/develop/oberon07/Samples/Windows/Console/TempConv.ob07 deleted file mode 100644 index 6906af1e7a..0000000000 --- a/programs/develop/oberon07/Samples/Windows/Console/TempConv.ob07 +++ /dev/null @@ -1,44 +0,0 @@ -(* - adapted to Oberon-07 by 0CodErr, KolibriOS team - *) -(* This program is a good example of proper formatting, it is *) -(* easy to read and very easy to understand. It should be a *) -(* snap to update a program that is well written like this. You *) -(* should begin to develop good formatting practice early in *) -(* your programming career. *) - -MODULE TempConv; - -IMPORT In, Out, Console; - - -VAR - Count : INTEGER; (* a variable used for counting *) - Centigrade : INTEGER; (* the temperature in centigrade *) - Farenheit : INTEGER; (* the temperature in farenheit *) - -BEGIN - Console.open; - - Out.String("Farenheit to Centigrade temperature table"); - Out.Ln; - Out.Ln; - FOR Count := -2 TO 12 DO - Centigrade := 10 * Count; - Farenheit := 32 + Centigrade * 9 DIV 5; - Out.String(" C ="); - Out.Int(Centigrade, 5); - Out.String(" F ="); - Out.Int(Farenheit, 5); - IF Centigrade = 0 THEN - Out.String(" Freezing point of water"); - END; - IF Centigrade = 100 THEN - Out.String(" Boiling point of water"); - END; - Out.Ln; - END; (* of main loop *) - In.Ln; - - Console.exit(TRUE) -END TempConv. \ No newline at end of file diff --git a/programs/develop/oberon07/Samples/Windows/Console/exp.ob07 b/programs/develop/oberon07/Samples/Windows/Console/exp.ob07 deleted file mode 100644 index 39807377a5..0000000000 --- a/programs/develop/oberon07/Samples/Windows/Console/exp.ob07 +++ /dev/null @@ -1,117 +0,0 @@ -(* - adapted to Oberon-07 by 0CodErr, KolibriOS team - *) -(* Print first 'PRINT' digits of 'e'. - * - * Originally written in Pascal by Scott Hemphill - * Rewritten in Modula-2 and modified by Andrew Cadach - * - *) - -MODULE exp; - -IMPORT In, Out, Console; - - -CONST - PRINT = 1024; - DIGITS = PRINT + (PRINT + 31) DIV 32; - - -TYPE - number = ARRAY DIGITS + 1 OF INTEGER; - - -VAR - s, x: number; - xs, i: INTEGER; - - -PROCEDURE init (VAR x: number; n: INTEGER); -VAR - i: INTEGER; - -BEGIN - x[0] := n; - FOR i := 1 TO DIGITS DO x[i] := 0 END -END init; - - -PROCEDURE divide (VAR x: number; xs, n: INTEGER; - VAR y: number; VAR ys: INTEGER); -VAR - i, c: INTEGER; - -BEGIN - c := 0; - FOR i := xs TO DIGITS DO - c := 10 * c + x[i]; - y[i] := c DIV n; - c := c MOD n - END; - ys := xs; - WHILE (ys <= DIGITS) & (y[ys] = 0) DO INC(ys) END -END divide; - - -PROCEDURE add (VAR s, x: number; xs: INTEGER); -VAR - i, c: INTEGER; -BEGIN - c := 0; - FOR i := DIGITS TO xs BY -1 DO - c := c + s[i] + x[i]; - IF c >= 10 THEN - s[i] := c - 10; - c := 1 - ELSE - s[i] := c; - c := 0 - END - END; - i := xs; - WHILE c # 0 DO - DEC(i); - c := c + s[i]; - IF c >= 10 THEN - s[i] := c - 10; - c := 1 - ELSE - s[i] := c; - c := 0 - END - END -END add; - - -BEGIN - Console.open; - - init(s, 0); - init(x, 1); - xs := 0; - add(s, x, xs); - i := 0; - REPEAT - INC(i); - divide(x, xs, i, x, xs); - add(s, x, xs); - UNTIL xs > DIGITS; - Out.Ln; - Out.String (" e = "); - Out.Char (CHR(s[0] + ORD("0"))); - Out.Char ("."); - FOR i := 1 TO PRINT DO - Out.Char (CHR(s[i] + ORD("0"))); - IF i MOD 64 = 0 THEN - Out.Ln; - Out.Int (i, 5); - Out.String (" ") - END - END; - Out.Ln; - Out.Ln; - In.Ln; - - Console.exit(TRUE) -END exp. \ No newline at end of file diff --git a/programs/develop/oberon07/Samples/Windows/Console/fact.ob07 b/programs/develop/oberon07/Samples/Windows/Console/fact.ob07 deleted file mode 100644 index 7f059811aa..0000000000 --- a/programs/develop/oberon07/Samples/Windows/Console/fact.ob07 +++ /dev/null @@ -1,59 +0,0 @@ -(* - adapted to Oberon-07 by 0CodErr, KolibriOS team - *) -(* - * Written by Andrew Cadach - * - * Recursive (extremely uneficient:-) implementation of factorial - * - * n * (n-1)!, n <> 0 - * By definition, n! = - * 1, n = 0 - * - *) - -MODULE fact; - -IMPORT In, Out, Console; - - -CONST - MAX_INTEGER = ROR(-2, 1); - - -VAR - i, r: INTEGER; - - -PROCEDURE f (n: INTEGER): INTEGER; -VAR - Res: INTEGER; - -BEGIN - IF n = 0 THEN - Res := 1 - ELSE - Res := n * f (n - 1) - END - - RETURN Res -END f; - - -BEGIN - Console.open; - - i := 0; - REPEAT - r := f(i); - Out.String ("The factorial of "); - Out.Int (i, 2); - Out.String (" is "); - Out.Int (r, 0); - Out.Ln; - INC(i) - UNTIL r >= MAX_INTEGER DIV i; - In.Ln; - - Console.exit(TRUE) -END fact. \ No newline at end of file diff --git a/programs/develop/oberon07/Samples/Windows/Console/hailst.ob07 b/programs/develop/oberon07/Samples/Windows/Console/hailst.ob07 deleted file mode 100644 index ebe93f3da4..0000000000 --- a/programs/develop/oberon07/Samples/Windows/Console/hailst.ob07 +++ /dev/null @@ -1,117 +0,0 @@ -(* - adapted to Oberon-07 by 0CodErr, KolibriOS team - *) -(* - The Hailstone sequence of numbers can be generated - from a starting positive integer, n by: - IF n is 1 THEN the sequence ends. - IF n is even THEN the next n of the sequence = n / 2 - IF n is odd THEN the next n of the sequence = (3 * n) + 1 - The (unproven) Collatz conjecture is that the hailstone sequence - for any starting number always terminates. -*) - -MODULE hailst; - -IMPORT In, Out, API, Console; - - -CONST - maxCard = ROR(-2, 1) DIV 3; - List = 1; - Count = 2; - Max = 3; - - -VAR - a: INTEGER; - - -PROCEDURE HALT(code: INTEGER); -BEGIN - In.Ln; Console.exit(TRUE); API.exit(code) -END HALT; - - -PROCEDURE HailStone(start, _type: INTEGER): INTEGER; -VAR - n, max, count, res: INTEGER; - exit: BOOLEAN; - -BEGIN - count := 1; - n := start; - max := n; - exit := FALSE; - WHILE exit # TRUE DO - IF _type = List THEN - Out.Int (n, 12); - IF count MOD 6 = 0 THEN Out.Ln END - END; - IF n # 1 THEN - IF ODD(n) THEN - IF n < maxCard THEN - n := 3 * n + 1; - IF n > max THEN max := n END - ELSE - Out.String("Exceeding max value for type INTEGER at:"); - Out.Ln; - Out.String("n = "); Out.Int(start, 1); - Out.String(", count = "); Out.Int(count, 1); - Out.String(", intermediate value "); - Out.Int(n, 1); - Out.String(". Aborting."); - Out.Ln; - HALT(2) - END - ELSE - n := n DIV 2 - END; - INC(count) - ELSE - exit := TRUE - END - END; - IF _type = Max THEN res := max ELSE res := count END - - RETURN res -END HailStone; - - -PROCEDURE FindMax(num: INTEGER); -VAR - val, maxCount, maxVal, cnt: INTEGER; - -BEGIN - maxCount := 0; - maxVal := 0; - FOR val := 2 TO num DO - cnt := HailStone(val, Count); - IF cnt > maxCount THEN - maxVal := val; - maxCount := cnt - END - END; - Out.String("Longest sequence below "); Out.Int(num, 1); - Out.String(" is "); Out.Int(HailStone(maxVal, Count), 1); - Out.String(" for n = "); Out.Int(maxVal, 1); - Out.String(" with an intermediate maximum of "); - Out.Int(HailStone(maxVal, Max), 1); - Out.Ln -END FindMax; - - -BEGIN - Console.open; - - a := HailStone(27, List); - Out.Ln; - Out.String("Iterations total = "); Out.Int(HailStone(27, Count), 1); - Out.String(" max value = "); Out.Int(HailStone(27, Max), 1); - Out.Ln; - FindMax(100000); - Out.String("Done."); - Out.Ln; In.Ln; - - Console.exit(TRUE) -END hailst. \ No newline at end of file diff --git a/programs/develop/oberon07/Samples/Windows/Console/postfix.ob07 b/programs/develop/oberon07/Samples/Windows/Console/postfix.ob07 deleted file mode 100644 index 309011d06d..0000000000 --- a/programs/develop/oberon07/Samples/Windows/Console/postfix.ob07 +++ /dev/null @@ -1,123 +0,0 @@ -(* - adapted to Oberon-07 by 0CodErr, KolibriOS team - *) -(* Example program from Programming In Modula-2, N. Wirth., pg. 56, *) -(* - no WINDOWS in this example *) - -(* this program translates a small language into postfix form - * the language is - * - * expression = term { [ "+" | "-" ] term } - * - * term = factor { [ "*" | "/" ] factor } - * - * factor = letter | "(" expression ")" - * - * letter = "a" | 'b" | … | "z" - * - * try as input - * a+b - * a*b+c - * a+b*c - * a*(b/(c-d)) - *) - -MODULE postfix; - -IMPORT In, Out, Console; - - -CONST - OUT_LINE_SIZE = 80; - IN_LINE_SIZE = 80; - - -VAR - ch : CHAR; - i, index : INTEGER; - out_line : ARRAY OUT_LINE_SIZE OF CHAR; - in_line : ARRAY IN_LINE_SIZE OF CHAR; - cur_ch : INTEGER; - - -PROCEDURE NextChar(): CHAR; -BEGIN - INC(cur_ch) - RETURN in_line[cur_ch - 1] -END NextChar; - - -PROCEDURE expression; -VAR - addop :CHAR; - - - PROCEDURE term; - VAR - mulop :CHAR; - - - PROCEDURE factor; - BEGIN (* factor *) - IF ch = "(" THEN - ch := NextChar(); - expression; - WHILE ch # ")" DO - ch := NextChar() - END (* WHILE *) - ELSE - WHILE (ch < "a") OR (ch > "z") DO - ch := NextChar() - END; (* WHILE *) - out_line[index] := ch; - index := index + 1 - END; (* IF *) - ch := NextChar() - END factor; - - - BEGIN (* term *) - factor; - WHILE (ch = "*") OR (ch = "/") DO - mulop := ch; - ch := NextChar(); - factor; - out_line[index] := mulop; - index := index + 1 - END (* WHILE *) - END term; - - -BEGIN (* expression *) - term; - WHILE (ch = "+") OR (ch = "-") DO - addop := ch; - ch := NextChar(); - term; - out_line[index] := addop; - index := index + 1 - END (* WHILE *) -END expression; - - -BEGIN (* Postfix *) - Console.open; - - index := 1; cur_ch := 0; - Out.String("Enter expression:"); - In.String(in_line); - ch := NextChar(); - WHILE ch > " " DO - expression; - FOR i := 1 TO index - 1 DO - Out.Char(out_line[i]) - END; (* FOR *) - Out.Ln; - index := 1; cur_ch := 0; - Out.String("Enter expression:"); - In.String(in_line); - ch := NextChar() - END; (* WHILE *) - - Console.exit(TRUE) -END postfix. \ No newline at end of file diff --git a/programs/develop/oberon07/Samples/Windows/Console/sequence012.ob07 b/programs/develop/oberon07/Samples/Windows/Console/sequence012.ob07 deleted file mode 100644 index 782b26708c..0000000000 --- a/programs/develop/oberon07/Samples/Windows/Console/sequence012.ob07 +++ /dev/null @@ -1,79 +0,0 @@ -(* - adapted to Oberon-07 by 0CodErr, KolibriOS team - *) -(* Find sequence of digits 0, 1, 2 and of lengths 1 ... 90, such - that they contain no two adjacent subsequences that are equal *) - -MODULE sequence012; - -IMPORT In, Out, Console; - - -CONST - maxlength = 75; - - -VAR - n: INTEGER; - good: BOOLEAN; - s: ARRAY maxlength OF INTEGER; - - -PROCEDURE printsequence; -VAR - k: INTEGER; -BEGIN - Out.Char(" "); - FOR k := 1 TO n DO Out.Int(s[k], 1) END; - Out.Ln -END printsequence; - - -PROCEDURE changesequence; -BEGIN - IF s[n] = 3 THEN - DEC(n); - changesequence - ELSE - s[n] := s[n] + 1 - END -END changesequence; - - -PROCEDURE try; -VAR - i, l, nhalf: INTEGER; - -BEGIN - IF n <= 1 THEN - good := TRUE - ELSE - l := 0; nhalf := n DIV 2; - REPEAT - INC(l); i := 0; - REPEAT - good := s[n - i] # s[n - l - i]; - INC(i) - UNTIL good OR (i = l) - UNTIL ~good OR (l >= nhalf) - END -END try; - - -BEGIN - Console.open; - - n := 0; - REPEAT - INC(n); - s[n] := 1; try; - WHILE ~good DO - changesequence; - try - END; - printsequence - UNTIL n >= maxlength - 1; - In.Ln; - - Console.exit(TRUE) -END sequence012. \ No newline at end of file diff --git a/programs/develop/oberon07/SelfKolibriOS.cmd b/programs/develop/oberon07/SelfKolibriOS.cmd new file mode 100644 index 0000000000..069ab78cdb --- /dev/null +++ b/programs/develop/oberon07/SelfKolibriOS.cmd @@ -0,0 +1,2 @@ +Compiler.exe source\Compiler.ob07 kosexe -out source\Compiler.kex -stk 2 +@pause \ No newline at end of file diff --git a/programs/develop/oberon07/doc/CC.txt b/programs/develop/oberon07/doc/CC.txt new file mode 100644 index 0000000000..0df944219f --- /dev/null +++ b/programs/develop/oberon07/doc/CC.txt @@ -0,0 +1,61 @@ +Условная компиляция + +синтаксис: + + $IF "(" ident {"|" ident} ")" + <...> + {$ELSIF "(" ident {"|" ident} ")"} + <...> + [$ELSE] + <...> + $END + + где ident: + - одно из возможных значений параметра в командной строке + - пользовательский идентификатор, переданный с ключом -def при компиляции + - один из возможных предопределенных идентификаторов: + + WINDOWS - приложение Windows + LINUX - приложение Linux + KOLIBRIOS - приложение KolibriOS + CPU_X86 - приложение для процессора x86 (32-бит) + CPU_X8664 - приложение для процессора x86_64 + + +примеры: + + $IF (win64con | win64gui | win64dll) + OS := "WIN64"; + $ELSIF (win32con | win32gui | win32dll) + OS := "WIN32"; + $ELSIF (linux64exe | linux64so) + OS := "LINUX64"; + $ELSIF (linux32exe | linux32so) + OS := "LINUX32"; + $ELSE + OS := "UNKNOWN"; + $END + + + $IF (debug) (* -def debug *) + print("debug"); + $END + + + $IF (WINDOWS) + $IF (CPU_X86) + (*windows 32*) + + $ELSIF (CPU_X8664) + (*windows 64*) + + $END + $ELSIF (LINUX) + $IF (CPU_X86) + (*linux 32*) + + $ELSIF (CPU_X8664) + (*linux 64*) + + $END + $END \ No newline at end of file diff --git a/programs/develop/oberon07/Docs/KOSLib.txt b/programs/develop/oberon07/doc/KOSLib.txt similarity index 100% rename from programs/develop/oberon07/Docs/KOSLib.txt rename to programs/develop/oberon07/doc/KOSLib.txt diff --git a/programs/develop/oberon07/Docs/Oberon07.Report_2016_05_03.pdf b/programs/develop/oberon07/doc/Oberon07.Report_2016_05_03.pdf similarity index 100% rename from programs/develop/oberon07/Docs/Oberon07.Report_2016_05_03.pdf rename to programs/develop/oberon07/doc/Oberon07.Report_2016_05_03.pdf diff --git a/programs/develop/oberon07/Docs/WinLib.txt b/programs/develop/oberon07/doc/WinLib.txt similarity index 100% rename from programs/develop/oberon07/Docs/WinLib.txt rename to programs/develop/oberon07/doc/WinLib.txt diff --git a/programs/develop/oberon07/Docs/x86.txt b/programs/develop/oberon07/doc/x86.txt similarity index 83% rename from programs/develop/oberon07/Docs/x86.txt rename to programs/develop/oberon07/doc/x86.txt index e26976fda6..0fe277a8a5 100644 --- a/programs/develop/oberon07/Docs/x86.txt +++ b/programs/develop/oberon07/doc/x86.txt @@ -25,6 +25,9 @@ UTF-8 с BOM-сигнатурой. -stk размер стэка в мегабайтах (по умолчанию 2 Мб, допустимо от 1 до 32 Мб) -nochk <"ptibcwra"> отключить проверки при выполнении (см. ниже) + -lower разрешить ключевые слова и встроенные идентификаторы в + нижнем регистре + -def <имя> задать символ условной компиляции -ver версия программы (только для kosdll) параметр -nochk задается в виде строки из символов: @@ -71,6 +74,10 @@ UTF-8 с BOM-сигнатурой. 9. Добавлен синтаксис для импорта процедур из внешних библиотек 10. "Строки" можно заключать также в одиночные кавычки: 'строка' 11. Добавлен тип WCHAR +12. Добавлена операция конкатенации строковых и символьных констант +13. Возможен импорт модулей с указанием пути и имени файла +14. Добавлен специальный синтаксис для условной компиляции (см. CC.txt) +15. Имя процедуры в конце объявления (после END) необязательно ------------------------------------------------------------------------------ Особенности реализации @@ -87,8 +94,8 @@ UTF-8 с BOM-сигнатурой. BYTE 0 .. 255 1 WCHAR символ юникода (0X .. 0FFFFX) 2 -2. Максимальная длина идентификаторов - 1024 символов -3. Максимальная длина строковых констант - 1024 символов (UTF-8) +2. Максимальная длина идентификаторов - 255 символов +3. Максимальная длина строковых констант - 511 символов (UTF-8) 4. Максимальная размерность открытых массивов - 5 5. Процедура NEW заполняет нулями выделенный блок памяти 6. Глобальные и локальные переменные инициализируются нулями @@ -137,25 +144,45 @@ UTF-8 с BOM-сигнатурой. PROCEDURE INF(): REAL возвращает специальное вещественное значение "бесконечность" + PROCEDURE MOVE(Source, Dest, n: INTEGER) + Копирует n байт памяти из Source в Dest, + области Source и Dest не могут перекрываться + PROCEDURE GET(a: INTEGER; VAR v: любой основной тип, PROCEDURE, POINTER) v := Память[a] + PROCEDURE GET8(a: INTEGER; + VAR x: INTEGER, SET, BYTE, CHAR, WCHAR, SYSTEM.CARD32) + Эквивалентно + SYSTEM.MOVE(a, SYSTEM.ADR(x), 1) + + PROCEDURE GET16(a: INTEGER; + VAR x: INTEGER, SET, WCHAR, SYSTEM.CARD32) + Эквивалентно + SYSTEM.MOVE(a, SYSTEM.ADR(x), 2) + + PROCEDURE GET32(a: INTEGER; VAR x: INTEGER, SET, SYSTEM.CARD32) + Эквивалентно + SYSTEM.MOVE(a, SYSTEM.ADR(x), 4) + PROCEDURE PUT(a: INTEGER; x: любой основной тип, PROCEDURE, POINTER) Память[a] := x; Если x: BYTE или x: WCHAR, то значение x будет расширено до 32 бит, для записи байтов использовать SYSTEM.PUT8, для WCHAR -- SYSTEM.PUT16 - PROCEDURE PUT8(a: INTEGER; x: INTEGER, SET, BYTE, CHAR, WCHAR) + PROCEDURE PUT8(a: INTEGER; + x: INTEGER, SET, BYTE, CHAR, WCHAR, SYSTEM.CARD32) Память[a] := младшие 8 бит (x) - PROCEDURE PUT16(a: INTEGER; x: INTEGER, SET, BYTE, CHAR, WCHAR) + PROCEDURE PUT16(a: INTEGER; + x: INTEGER, SET, BYTE, CHAR, WCHAR, SYSTEM.CARD32) Память[a] := младшие 16 бит (x) - PROCEDURE MOVE(Source, Dest, n: INTEGER) - Копирует n байт памяти из Source в Dest, - области Source и Dest не могут перекрываться + PROCEDURE PUT32(a: INTEGER; + x: INTEGER, SET, BYTE, CHAR, WCHAR, SYSTEM.CARD32) + Память[a] := младшие 32 бит (x) PROCEDURE COPY(VAR Source: любой тип; VAR Dest: любой тип; n: INTEGER) Копирует n байт памяти из Source в Dest. @@ -168,6 +195,8 @@ UTF-8 с BOM-сигнатурой. например: SYSTEM.CODE(08BH, 045H, 008H) (* mov eax, dword [ebp + 08h] *) + Также, в модуле SYSTEM определен тип CARD32 (4 байта). Для типа CARD32 не +допускаются никакие явные операции, за исключением присваивания. Функции псевдомодуля SYSTEM нельзя использовать в константных выражениях. @@ -176,15 +205,17 @@ UTF-8 с BOM-сигнатурой. При объявлении процедурных типов и глобальных процедур, после ключевого слова PROCEDURE может быть указан флаг соглашения о вызове: [stdcall], -[ccall], [ccall16], [windows], [linux]. Например: +[cdecl], [ccall], [windows], [linux], [oberon]. Например: PROCEDURE [ccall] MyProc (x, y, z: INTEGER): INTEGER; - Если указан флаг [ccall16], то принимается соглашение ccall, но перед + Если указан флаг [ccall], то принимается соглашение cdecl, но перед вызовом указатель стэка будет выравнен по границе 16 байт. - Флаг [windows] - синоним для [stdcall], [linux] - синоним для [ccall16]. + Флаг [windows] - синоним для [stdcall], [linux] - синоним для [ccall]. Знак "-" после имени флага ([stdcall-], [linux-], ...) означает, что результат процедуры можно игнорировать (не допускается для типа REAL). + Если флаг не указан или указан флаг [oberon], то принимается внутреннее +соглашение о вызове. При объявлении типов-записей, после ключевого слова RECORD может быть указан флаг [noalign]. Флаг [noalign] означает отсутствие выравнивания полей @@ -198,7 +229,7 @@ UTF-8 с BOM-сигнатурой. Синтаксис оператора CASE: CaseStatement = - CASE Expression OF Сase {"|" Сase} + CASE Expression OF Case {"|" Case} [ELSE StatementSequence] END. Case = [CaseLabelList ":" StatementSequence]. CaseLabelList = CaseLabels {"," CaseLabels}. @@ -226,7 +257,16 @@ ARRAY OF WCHAR допускаются все те же операции, как ARRAY OF CHAR, за исключением встроенной процедуры CHR, которая возвращает только тип CHAR. Для получения значения типа WCHAR, следует использовать процедуру WCHR вместо CHR. Для правильной работы с типом, необходимо сохранять -исходный код в кодировке UTF-8 c BOM. +исходный код в кодировке UTF-8 с BOM. + +------------------------------------------------------------------------------ + Конкатенация строковых и символьных констант + + Допускается конкатенация ("+") константных строк и символов типа CHAR: + + str = CHR(39) + "string" + CHR(39); (* str = "'string'" *) + + newline = 0DX + 0AX; ------------------------------------------------------------------------------ Проверка и охрана типа нулевого указателя @@ -272,20 +312,30 @@ Oberon-реализациях выполнение такой операции WCHR (n: INTEGER): WCHAR Преобразование типа, аналогично CHR(n: INTEGER): CHAR +------------------------------------------------------------------------------ + Импорт модулей с указанием пути и имени файла + +Примеры: + + IMPORT Math IN "./lib/math.ob07"; (* относительно текущего модуля *) + + IMPORT M1 IN "C:\lib\math.ob07"; (* абсолютный путь *) + ------------------------------------------------------------------------------ Импортированные процедуры Синтаксис импорта: - PROCEDURE [callconv, "library", "function"] proc_name (FormalParam): Type; + PROCEDURE [callconv, library, function] proc_name (FormalParam): Type; - callconv -- соглашение о вызове - - "library" -- имя файла динамической библиотеки - - "function" -- имя импортируемой процедуры + - library -- имя файла динамической библиотеки (строковая константа) + - function -- имя импортируемой процедуры (строковая константа), если + указана пустая строка, то имя процедуры = proc_name например: - PROCEDURE [windows, "kernel32.dll", "ExitProcess"] exit (code: INTEGER); + PROCEDURE [windows, "kernel32.dll", ""] ExitProcess (code: INTEGER); PROCEDURE [stdcall, "Console.obj", "con_exit"] exit (bCloseWindow: BOOLEAN); @@ -327,6 +377,8 @@ Oberon-реализациях выполнение такой операции Вызов транслируется так: Proc(SYSTEM.TYPEID(Rec), SYSTEM.ADR(x)) + Скрытые параметры необходимо учитывать при связи с внешними приложениями. + ------------------------------------------------------------------------------ Модуль RTL @@ -349,8 +401,11 @@ Oberon-реализациях выполнение такой операции Разрешается экспортировать только процедуры. Для этого, процедура должна находиться в главном модуле программы, и ее имя должно быть отмечено символом -экспорта ("*"). KolibriOS DLL всегда экспортируют идентификаторы "version" -(версия программы) и "lib_init" - адрес процедуры инициализации DLL: +экспорта ("*"). Нельзя экспортировать процедуры, которые импортированы из +других dll-библиотек. + + KolibriOS DLL всегда экспортируют идентификаторы "version" (версия +программы) и "lib_init" - адрес процедуры инициализации DLL: PROCEDURE [stdcall] lib_init (): INTEGER diff --git a/programs/develop/oberon07/Docs/x86_64.txt b/programs/develop/oberon07/doc/x86_64.txt similarity index 83% rename from programs/develop/oberon07/Docs/x86_64.txt rename to programs/develop/oberon07/doc/x86_64.txt index 9655412ac4..c4a523f8cf 100644 --- a/programs/develop/oberon07/Docs/x86_64.txt +++ b/programs/develop/oberon07/doc/x86_64.txt @@ -23,6 +23,9 @@ UTF-8 с BOM-сигнатурой. -stk размер стэка в мегабайтах (по умолчанию 2 Мб, допустимо от 1 до 32 Мб) -nochk <"ptibcwra"> отключить проверки при выполнении + -lower разрешить ключевые слова и встроенные идентификаторы в + нижнем регистре + -def <имя> задать символ условной компиляции параметр -nochk задается в виде строки из символов: "p" - указатели @@ -63,6 +66,10 @@ UTF-8 с BOM-сигнатурой. 9. Добавлен синтаксис для импорта процедур из внешних библиотек 10. "Строки" можно заключать также в одиночные кавычки: 'строка' 11. Добавлен тип WCHAR +12. Добавлена операция конкатенации строковых и символьных констант +13. Возможен импорт модулей с указанием пути и имени файла +14. Добавлен специальный синтаксис для условной компиляции (см. CC.txt) +15. Имя процедуры в конце объявления (после END) необязательно ------------------------------------------------------------------------------ Особенности реализации @@ -79,8 +86,8 @@ UTF-8 с BOM-сигнатурой. BYTE 0 .. 255 1 WCHAR символ юникода (0X .. 0FFFFX) 2 -2. Максимальная длина идентификаторов - 1024 символов -3. Максимальная длина строковых констант - 1024 символов (UTF-8) +2. Максимальная длина идентификаторов - 255 символов +3. Максимальная длина строковых констант - 511 символов (UTF-8) 4. Максимальная размерность открытых массивов - 5 5. Процедура NEW заполняет нулями выделенный блок памяти 6. Глобальные и локальные переменные инициализируются нулями @@ -129,29 +136,46 @@ UTF-8 с BOM-сигнатурой. PROCEDURE INF(): REAL возвращает специальное вещественное значение "бесконечность" + PROCEDURE MOVE(Source, Dest, n: INTEGER) + Копирует n байт памяти из Source в Dest, + области Source и Dest не могут перекрываться + PROCEDURE GET(a: INTEGER; VAR v: любой основной тип, PROCEDURE, POINTER) v := Память[a] + PROCEDURE GET8(a: INTEGER; + VAR x: INTEGER, SET, BYTE, CHAR, WCHAR, SYSTEM.CARD32) + Эквивалентно + SYSTEM.MOVE(a, SYSTEM.ADR(x), 1) + + PROCEDURE GET16(a: INTEGER; + VAR x: INTEGER, SET, WCHAR, SYSTEM.CARD32) + Эквивалентно + SYSTEM.MOVE(a, SYSTEM.ADR(x), 2) + + PROCEDURE GET32(a: INTEGER; VAR x: INTEGER, SET, SYSTEM.CARD32) + Эквивалентно + SYSTEM.MOVE(a, SYSTEM.ADR(x), 4) + PROCEDURE PUT(a: INTEGER; x: любой основной тип, PROCEDURE, POINTER) Память[a] := x; Если x: BYTE или x: WCHAR, то значение x будет расширено до 64 бит, для записи байтов использовать SYSTEM.PUT8, для WCHAR -- SYSTEM.PUT16 - PROCEDURE PUT8(a: INTEGER; x: INTEGER, SET, BYTE, CHAR, WCHAR) + PROCEDURE PUT8(a: INTEGER; + x: INTEGER, SET, BYTE, CHAR, WCHAR, SYSTEM.CARD32) Память[a] := младшие 8 бит (x) - PROCEDURE PUT16(a: INTEGER; x: INTEGER, SET, BYTE, CHAR, WCHAR) + PROCEDURE PUT16(a: INTEGER; + x: INTEGER, SET, BYTE, CHAR, WCHAR, SYSTEM.CARD32) Память[a] := младшие 16 бит (x) - PROCEDURE PUT32(a: INTEGER; x: INTEGER, SET, BYTE, CHAR, WCHAR) + PROCEDURE PUT32(a: INTEGER; + x: INTEGER, SET, BYTE, CHAR, WCHAR, SYSTEM.CARD32) Память[a] := младшие 32 бит (x) - PROCEDURE MOVE(Source, Dest, n: INTEGER) - Копирует n байт памяти из Source в Dest, - области Source и Dest не могут перекрываться - PROCEDURE COPY(VAR Source: любой тип; VAR Dest: любой тип; n: INTEGER) Копирует n байт памяти из Source в Dest. Эквивалентно @@ -173,18 +197,19 @@ UTF-8 с BOM-сигнатурой. Системные флаги При объявлении процедурных типов и глобальных процедур, после ключевого -слова PROCEDURE может быть указан флаг соглашения о вызове: [win64], [systemv], -[windows], [linux]. +слова PROCEDURE может быть указан флаг соглашения о вызове: +[win64], [systemv], [windows], [linux], [oberon], [ccall]. Например: PROCEDURE [win64] MyProc (x, y, z: INTEGER): INTEGER; Флаг [windows] - синоним для [win64], [linux] - синоним для [systemv]. + Флаг [ccall] - синоним для [win64] или [systemv] (зависит от целевой ОС). Знак "-" после имени флага ([win64-], [linux-], ...) означает, что результат процедуры можно игнорировать (не допускается для типа REAL). - Если флаг не указан, то принимается внутреннее соглашение о вызове. -[win64] и [systemv] используются для связи с операционной системой и внешними -приложениями. + Если флаг не указан или указан флаг [oberon], то принимается внутреннее +соглашение о вызове. [win64] и [systemv] используются для связи с +операционной системой и внешними приложениями. При объявлении типов-записей, после ключевого слова RECORD может быть указан флаг [noalign]. Флаг [noalign] означает отсутствие выравнивания полей @@ -198,7 +223,7 @@ UTF-8 с BOM-сигнатурой. Синтаксис оператора CASE: CaseStatement = - CASE Expression OF Сase {"|" Сase} + CASE Expression OF Case {"|" Case} [ELSE StatementSequence] END. Case = [CaseLabelList ":" StatementSequence]. CaseLabelList = CaseLabels {"," CaseLabels}. @@ -226,7 +251,16 @@ ARRAY OF WCHAR допускаются все те же операции, как ARRAY OF CHAR, за исключением встроенной процедуры CHR, которая возвращает только тип CHAR. Для получения значения типа WCHAR, следует использовать процедуру WCHR вместо CHR. Для правильной работы с типом, необходимо сохранять -исходный код в кодировке UTF-8 c BOM. +исходный код в кодировке UTF-8 с BOM. + +------------------------------------------------------------------------------ + Конкатенация строковых и символьных констант + + Допускается конкатенация ("+") константных строк и символов типа CHAR: + + str = CHR(39) + "string" + CHR(39); (* str = "'string'" *) + + newline = 0DX + 0AX; ------------------------------------------------------------------------------ Проверка и охрана типа нулевого указателя @@ -272,21 +306,32 @@ Oberon-реализациях выполнение такой операции WCHR (n: INTEGER): WCHAR Преобразование типа, аналогично CHR(n: INTEGER): CHAR +------------------------------------------------------------------------------ + Импорт модулей с указанием пути и имени файла + +Примеры: + + IMPORT Math IN "./lib/math.ob07"; (* относительно текущего модуля *) + + IMPORT M1 IN "C:\lib\math.ob07"; (* абсолютный путь *) + ------------------------------------------------------------------------------ Импортированные процедуры Синтаксис импорта: - PROCEDURE [callconv, "library", "function"] proc_name (FormalParam): Type; + PROCEDURE [callconv, library, function] proc_name (FormalParam): Type; - callconv -- соглашение о вызове - - "library" -- имя файла динамической библиотеки - - "function" -- имя импортируемой процедуры + - library -- имя файла динамической библиотеки (строковая константа) + - function -- имя импортируемой процедуры (строковая константа), если + указана пустая строка, то имя процедуры = proc_name например: - PROCEDURE [win64, "kernel32.dll", "ExitProcess"] exit (code: INTEGER); + PROCEDURE [windows, "kernel32.dll", "ExitProcess"] exit (code: INTEGER); + PROCEDURE [windows, "kernel32.dll", ""] GetTickCount (): INTEGER; В конце объявления может быть добавлено (необязательно) "END proc_name;" @@ -301,7 +346,7 @@ Oberon-реализациях выполнение такой операции соглашения о вызове: VAR - ExitProcess: PROCEDURE [win64] (code: INTEGER); + ExitProcess: PROCEDURE [windows] (code: INTEGER); Для Linux, импортированные процедуры не реализованы. @@ -321,6 +366,8 @@ Oberon-реализациях выполнение такой операции Вызов транслируется так: Proc(SYSTEM.TYPEID(Rec), SYSTEM.ADR(x)) + Скрытые параметры необходимо учитывать при связи с внешними приложениями. + ------------------------------------------------------------------------------ Модуль RTL @@ -343,4 +390,5 @@ Oberon-реализациях выполнение такой операции Разрешается экспортировать только процедуры. Для этого, процедура должна находиться в главном модуле программы, ее имя должно быть отмечено символом -экспорта ("*") и должно быть указано соглашение о вызове. \ No newline at end of file +экспорта ("*") и должно быть указано соглашение о вызове. Нельзя +экспортировать процедуры, которые импортированы из других dll-библиотек. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/KolibriOS/API.ob07 b/programs/develop/oberon07/lib/KolibriOS/API.ob07 similarity index 94% rename from programs/develop/oberon07/Lib/KolibriOS/API.ob07 rename to programs/develop/oberon07/lib/KolibriOS/API.ob07 index 3e1619a157..c740a95f36 100644 --- a/programs/develop/oberon07/Lib/KolibriOS/API.ob07 +++ b/programs/develop/oberon07/lib/KolibriOS/API.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2018, 2020, Anton Krotov + Copyright (c) 2018, 2020-2021, Anton Krotov All rights reserved. *) @@ -13,6 +13,7 @@ IMPORT SYSTEM, K := KOSAPI; CONST eol* = 0DX + 0AX; + BIT_DEPTH* = 32; MAX_SIZE = 16 * 400H; HEAP_SIZE = 1 * 100000H; diff --git a/programs/develop/oberon07/Lib/KolibriOS/Args.ob07 b/programs/develop/oberon07/lib/KolibriOS/Args.ob07 similarity index 100% rename from programs/develop/oberon07/Lib/KolibriOS/Args.ob07 rename to programs/develop/oberon07/lib/KolibriOS/Args.ob07 diff --git a/programs/develop/oberon07/Lib/KolibriOS/ColorDlg.ob07 b/programs/develop/oberon07/lib/KolibriOS/ColorDlg.ob07 similarity index 100% rename from programs/develop/oberon07/Lib/KolibriOS/ColorDlg.ob07 rename to programs/develop/oberon07/lib/KolibriOS/ColorDlg.ob07 diff --git a/programs/develop/oberon07/Lib/KolibriOS/Console.ob07 b/programs/develop/oberon07/lib/KolibriOS/Console.ob07 similarity index 100% rename from programs/develop/oberon07/Lib/KolibriOS/Console.ob07 rename to programs/develop/oberon07/lib/KolibriOS/Console.ob07 diff --git a/programs/develop/oberon07/Lib/KolibriOS/ConsoleLib.ob07 b/programs/develop/oberon07/lib/KolibriOS/ConsoleLib.ob07 similarity index 100% rename from programs/develop/oberon07/Lib/KolibriOS/ConsoleLib.ob07 rename to programs/develop/oberon07/lib/KolibriOS/ConsoleLib.ob07 diff --git a/programs/develop/oberon07/Lib/KolibriOS/DateTime.ob07 b/programs/develop/oberon07/lib/KolibriOS/DateTime.ob07 similarity index 100% rename from programs/develop/oberon07/Lib/KolibriOS/DateTime.ob07 rename to programs/develop/oberon07/lib/KolibriOS/DateTime.ob07 diff --git a/programs/develop/oberon07/Lib/KolibriOS/Debug.ob07 b/programs/develop/oberon07/lib/KolibriOS/Debug.ob07 similarity index 100% rename from programs/develop/oberon07/Lib/KolibriOS/Debug.ob07 rename to programs/develop/oberon07/lib/KolibriOS/Debug.ob07 diff --git a/programs/develop/oberon07/Lib/KolibriOS/File.ob07 b/programs/develop/oberon07/lib/KolibriOS/File.ob07 similarity index 91% rename from programs/develop/oberon07/Lib/KolibriOS/File.ob07 rename to programs/develop/oberon07/lib/KolibriOS/File.ob07 index d25a8d6938..dc99a0c680 100644 --- a/programs/develop/oberon07/Lib/KolibriOS/File.ob07 +++ b/programs/develop/oberon07/lib/KolibriOS/File.ob07 @@ -1,5 +1,5 @@ (* - Copyright 2016, 2018 Anton Krotov + Copyright 2016, 2018, 2021 Anton Krotov This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -91,6 +91,20 @@ BEGIN END GetFileInfo; +PROCEDURE FileSize* (FName: ARRAY OF CHAR): INTEGER; +VAR + Info: rFD; + res: INTEGER; +BEGIN + IF GetFileInfo(FName, Info) THEN + res := Info.size + ELSE + res := -1 + END + RETURN res +END FileSize; + + PROCEDURE Exists* (FName: ARRAY OF CHAR): BOOLEAN; VAR fd: rFD; diff --git a/programs/develop/oberon07/Lib/KolibriOS/HOST.ob07 b/programs/develop/oberon07/lib/KolibriOS/HOST.ob07 similarity index 92% rename from programs/develop/oberon07/Lib/KolibriOS/HOST.ob07 rename to programs/develop/oberon07/lib/KolibriOS/HOST.ob07 index a3280b46f8..28c5561005 100644 --- a/programs/develop/oberon07/Lib/KolibriOS/HOST.ob07 +++ b/programs/develop/oberon07/lib/KolibriOS/HOST.ob07 @@ -1,13 +1,13 @@ (* BSD 2-Clause License - Copyright (c) 2018-2020, Anton Krotov + Copyright (c) 2018-2021, Anton Krotov All rights reserved. *) MODULE HOST; -IMPORT SYSTEM, K := KOSAPI, API, RTL; +IMPORT SYSTEM, K := KOSAPI, API; CONST @@ -15,9 +15,9 @@ CONST slash* = "/"; eol* = 0DX + 0AX; - bit_depth* = RTL.bit_depth; - maxint* = RTL.maxint; - minint* = RTL.minint; + bit_depth* = API.BIT_DEPTH; + maxint* = ROR(-2, 1); + minint* = ROR(1, 1); MAX_PARAM = 1024; @@ -400,12 +400,9 @@ VAR n: INTEGER; BEGIN - GetArg(0, path); - n := LENGTH(path) - 1; - WHILE path[n] # slash DO - DEC(n) - END; - path[n + 1] := 0X + n := K.sysfunc4(30, 2, SYSTEM.ADR(path[0]), LEN(path) - 2); + path[n - 1] := slash; + path[n] := 0X END GetCurrentDirectory; diff --git a/programs/develop/oberon07/Lib/KolibriOS/In.ob07 b/programs/develop/oberon07/lib/KolibriOS/In.ob07 similarity index 100% rename from programs/develop/oberon07/Lib/KolibriOS/In.ob07 rename to programs/develop/oberon07/lib/KolibriOS/In.ob07 diff --git a/programs/develop/oberon07/Lib/KolibriOS/KOSAPI.ob07 b/programs/develop/oberon07/lib/KolibriOS/KOSAPI.ob07 similarity index 100% rename from programs/develop/oberon07/Lib/KolibriOS/KOSAPI.ob07 rename to programs/develop/oberon07/lib/KolibriOS/KOSAPI.ob07 diff --git a/programs/develop/oberon07/Lib/KolibriOS/Math.ob07 b/programs/develop/oberon07/lib/KolibriOS/Math.ob07 similarity index 100% rename from programs/develop/oberon07/Lib/KolibriOS/Math.ob07 rename to programs/develop/oberon07/lib/KolibriOS/Math.ob07 diff --git a/programs/develop/oberon07/Lib/KolibriOS/NetDevices.ob07 b/programs/develop/oberon07/lib/KolibriOS/NetDevices.ob07 similarity index 100% rename from programs/develop/oberon07/Lib/KolibriOS/NetDevices.ob07 rename to programs/develop/oberon07/lib/KolibriOS/NetDevices.ob07 diff --git a/programs/develop/oberon07/Lib/KolibriOS/OpenDlg.ob07 b/programs/develop/oberon07/lib/KolibriOS/OpenDlg.ob07 similarity index 93% rename from programs/develop/oberon07/Lib/KolibriOS/OpenDlg.ob07 rename to programs/develop/oberon07/lib/KolibriOS/OpenDlg.ob07 index 82d6bfbc3a..819d34dc70 100644 --- a/programs/develop/oberon07/Lib/KolibriOS/OpenDlg.ob07 +++ b/programs/develop/oberon07/lib/KolibriOS/OpenDlg.ob07 @@ -1,5 +1,5 @@ (* - Copyright 2016, 2018, 2020 Anton Krotov + Copyright 2016, 2018, 2020, 2021 Anton Krotov This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -19,12 +19,17 @@ MODULE OpenDlg; IMPORT sys := SYSTEM, KOSAPI; +CONST + topen* = 0; + tsave* = 1; + tdir* = 2; + TYPE DRAW_WINDOW = PROCEDURE; TDialog = RECORD - _type, + _type*, procinfo, com_area_name, com_area, diff --git a/programs/develop/oberon07/Lib/KolibriOS/Out.ob07 b/programs/develop/oberon07/lib/KolibriOS/Out.ob07 similarity index 100% rename from programs/develop/oberon07/Lib/KolibriOS/Out.ob07 rename to programs/develop/oberon07/lib/KolibriOS/Out.ob07 diff --git a/programs/develop/oberon07/Lib/Linux32/RTL.ob07 b/programs/develop/oberon07/lib/KolibriOS/RTL.ob07 similarity index 79% rename from programs/develop/oberon07/Lib/Linux32/RTL.ob07 rename to programs/develop/oberon07/lib/KolibriOS/RTL.ob07 index 5f9e168085..0818bca97d 100644 --- a/programs/develop/oberon07/Lib/Linux32/RTL.ob07 +++ b/programs/develop/oberon07/lib/KolibriOS/RTL.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2018-2020, Anton Krotov + Copyright (c) 2018-2021, Anton Krotov All rights reserved. *) @@ -12,12 +12,9 @@ IMPORT SYSTEM, API; CONST - bit_depth* = 32; - maxint* = 7FFFFFFFH; - minint* = 80000000H; + minint = ROR(1, 1); - WORD = bit_depth DIV 8; - MAX_SET = bit_depth - 1; + WORD = API.BIT_DEPTH DIV 8; VAR @@ -72,37 +69,63 @@ BEGIN END _strcpy; -PROCEDURE [stdcall] _rot* (VAR A: ARRAY OF INTEGER); -VAR - i, n, k: INTEGER; - +PROCEDURE [stdcall] _rot* (Len, Ptr: INTEGER); BEGIN - k := LEN(A) - 1; - n := A[0]; - i := 0; - WHILE i < k DO - A[i] := A[i + 1]; - INC(i) - END; - A[k] := n + SYSTEM.CODE( + 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 8] *) (* ecx <- Len *) + 08BH, 045H, 00CH, (* mov eax, dword [ebp + 12] *) (* eax <- Ptr *) + 049H, (* dec ecx *) + 053H, (* push ebx *) + 08BH, 018H, (* mov ebx, dword [eax] *) + (* L: *) + 08BH, 050H, 004H, (* mov edx, dword [eax + 4] *) + 089H, 010H, (* mov dword [eax], edx *) + 083H, 0C0H, 004H, (* add eax, 4 *) + 049H, (* dec ecx *) + 075H, 0F5H, (* jnz L *) + 089H, 018H, (* mov dword [eax], ebx *) + 05BH, (* pop ebx *) + 05DH, (* pop ebp *) + 0C2H, 008H, 000H (* ret 8 *) + ) END _rot; -PROCEDURE [stdcall] _set* (b, a: INTEGER): INTEGER; +PROCEDURE [stdcall] _set* (b, a: INTEGER); (* {a..b} -> eax *) BEGIN - IF (a <= b) & (a <= MAX_SET) & (b >= 0) THEN - IF b > MAX_SET THEN - b := MAX_SET - END; - IF a < 0 THEN - a := 0 - END; - a := LSR(ASR(minint, b - a), MAX_SET - b) - ELSE - a := 0 - END - - RETURN a + SYSTEM.CODE( + 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 8] *) (* ecx <- b *) + 08BH, 045H, 00CH, (* mov eax, dword [ebp + 12] *) (* eax <- a *) + 039H, 0C8H, (* cmp eax, ecx *) + 07FH, 033H, (* jg L1 *) + 083H, 0F8H, 01FH, (* cmp eax, 31 *) + 07FH, 02EH, (* jg L1 *) + 085H, 0C9H, (* test ecx, ecx *) + 07CH, 02AH, (* jl L1 *) + 083H, 0F9H, 01FH, (* cmp ecx, 31 *) + 07EH, 005H, (* jle L3 *) + 0B9H, 01FH, 000H, 000H, 000H, (* mov ecx, 31 *) + (* L3: *) + 085H, 0C0H, (* test eax, eax *) + 07DH, 002H, (* jge L2 *) + 031H, 0C0H, (* xor eax, eax *) + (* L2: *) + 089H, 0CAH, (* mov edx, ecx *) + 029H, 0C2H, (* sub edx, eax *) + 0B8H, 000H, 000H, 000H, 080H, (* mov eax, 0x80000000 *) + 087H, 0CAH, (* xchg edx, ecx *) + 0D3H, 0F8H, (* sar eax, cl *) + 087H, 0CAH, (* xchg edx, ecx *) + 083H, 0E9H, 01FH, (* sub ecx, 31 *) + 0F7H, 0D9H, (* neg ecx *) + 0D3H, 0E8H, (* shr eax, cl *) + 05DH, (* pop ebp *) + 0C2H, 008H, 000H, (* ret 8 *) + (* L1: *) + 031H, 0C0H, (* xor eax, eax *) + 05DH, (* pop ebp *) + 0C2H, 008H, 000H (* ret 8 *) + ) END _set; diff --git a/programs/develop/oberon07/Lib/KolibriOS/RasterWorks.ob07 b/programs/develop/oberon07/lib/KolibriOS/RasterWorks.ob07 similarity index 100% rename from programs/develop/oberon07/Lib/KolibriOS/RasterWorks.ob07 rename to programs/develop/oberon07/lib/KolibriOS/RasterWorks.ob07 diff --git a/programs/develop/oberon07/Lib/KolibriOS/Read.ob07 b/programs/develop/oberon07/lib/KolibriOS/Read.ob07 similarity index 100% rename from programs/develop/oberon07/Lib/KolibriOS/Read.ob07 rename to programs/develop/oberon07/lib/KolibriOS/Read.ob07 diff --git a/programs/develop/oberon07/Lib/KolibriOS/UnixTime.ob07 b/programs/develop/oberon07/lib/KolibriOS/UnixTime.ob07 similarity index 100% rename from programs/develop/oberon07/Lib/KolibriOS/UnixTime.ob07 rename to programs/develop/oberon07/lib/KolibriOS/UnixTime.ob07 diff --git a/programs/develop/oberon07/Lib/KolibriOS/Vector.ob07 b/programs/develop/oberon07/lib/KolibriOS/Vector.ob07 similarity index 100% rename from programs/develop/oberon07/Lib/KolibriOS/Vector.ob07 rename to programs/develop/oberon07/lib/KolibriOS/Vector.ob07 diff --git a/programs/develop/oberon07/Lib/KolibriOS/Write.ob07 b/programs/develop/oberon07/lib/KolibriOS/Write.ob07 similarity index 100% rename from programs/develop/oberon07/Lib/KolibriOS/Write.ob07 rename to programs/develop/oberon07/lib/KolibriOS/Write.ob07 diff --git a/programs/develop/oberon07/Lib/KolibriOS/kfonts.ob07 b/programs/develop/oberon07/lib/KolibriOS/kfonts.ob07 similarity index 100% rename from programs/develop/oberon07/Lib/KolibriOS/kfonts.ob07 rename to programs/develop/oberon07/lib/KolibriOS/kfonts.ob07 diff --git a/programs/develop/oberon07/Lib/KolibriOS/libimg.ob07 b/programs/develop/oberon07/lib/KolibriOS/libimg.ob07 similarity index 100% rename from programs/develop/oberon07/Lib/KolibriOS/libimg.ob07 rename to programs/develop/oberon07/lib/KolibriOS/libimg.ob07 diff --git a/programs/develop/oberon07/Lib/Math/CMath.ob07 b/programs/develop/oberon07/lib/Math/CMath.ob07 similarity index 100% rename from programs/develop/oberon07/Lib/Math/CMath.ob07 rename to programs/develop/oberon07/lib/Math/CMath.ob07 diff --git a/programs/develop/oberon07/Lib/Math/MathBits.ob07 b/programs/develop/oberon07/lib/Math/MathBits.ob07 similarity index 100% rename from programs/develop/oberon07/Lib/Math/MathBits.ob07 rename to programs/develop/oberon07/lib/Math/MathBits.ob07 diff --git a/programs/develop/oberon07/Lib/Math/MathRound.ob07 b/programs/develop/oberon07/lib/Math/MathRound.ob07 similarity index 100% rename from programs/develop/oberon07/Lib/Math/MathRound.ob07 rename to programs/develop/oberon07/lib/Math/MathRound.ob07 diff --git a/programs/develop/oberon07/Lib/Math/MathStat.ob07 b/programs/develop/oberon07/lib/Math/MathStat.ob07 similarity index 100% rename from programs/develop/oberon07/Lib/Math/MathStat.ob07 rename to programs/develop/oberon07/lib/Math/MathStat.ob07 diff --git a/programs/develop/oberon07/Lib/Math/Rand.ob07 b/programs/develop/oberon07/lib/Math/Rand.ob07 similarity index 100% rename from programs/develop/oberon07/Lib/Math/Rand.ob07 rename to programs/develop/oberon07/lib/Math/Rand.ob07 diff --git a/programs/develop/oberon07/Lib/Math/RandExt.ob07 b/programs/develop/oberon07/lib/Math/RandExt.ob07 similarity index 100% rename from programs/develop/oberon07/Lib/Math/RandExt.ob07 rename to programs/develop/oberon07/lib/Math/RandExt.ob07 diff --git a/programs/develop/oberon07/Lib/RVM32I/FPU.ob07 b/programs/develop/oberon07/lib/RVM32I/FPU.ob07 similarity index 100% rename from programs/develop/oberon07/Lib/RVM32I/FPU.ob07 rename to programs/develop/oberon07/lib/RVM32I/FPU.ob07 diff --git a/programs/develop/oberon07/Lib/RVM32I/HOST.ob07 b/programs/develop/oberon07/lib/RVM32I/HOST.ob07 similarity index 100% rename from programs/develop/oberon07/Lib/RVM32I/HOST.ob07 rename to programs/develop/oberon07/lib/RVM32I/HOST.ob07 diff --git a/programs/develop/oberon07/Lib/RVM32I/Out.ob07 b/programs/develop/oberon07/lib/RVM32I/Out.ob07 similarity index 100% rename from programs/develop/oberon07/Lib/RVM32I/Out.ob07 rename to programs/develop/oberon07/lib/RVM32I/Out.ob07 diff --git a/programs/develop/oberon07/Lib/RVM32I/RTL.ob07 b/programs/develop/oberon07/lib/RVM32I/RTL.ob07 similarity index 100% rename from programs/develop/oberon07/Lib/RVM32I/RTL.ob07 rename to programs/develop/oberon07/lib/RVM32I/RTL.ob07 diff --git a/programs/develop/oberon07/Lib/RVM32I/Trap.ob07 b/programs/develop/oberon07/lib/RVM32I/Trap.ob07 similarity index 100% rename from programs/develop/oberon07/Lib/RVM32I/Trap.ob07 rename to programs/develop/oberon07/lib/RVM32I/Trap.ob07 diff --git a/programs/develop/oberon07/Lib/STM32CM3/FPU.ob07 b/programs/develop/oberon07/lib/RVMxI/32/FPU.ob07 similarity index 70% rename from programs/develop/oberon07/Lib/STM32CM3/FPU.ob07 rename to programs/develop/oberon07/lib/RVMxI/32/FPU.ob07 index da30e4ea7c..28069c4feb 100644 --- a/programs/develop/oberon07/Lib/STM32CM3/FPU.ob07 +++ b/programs/develop/oberon07/lib/RVMxI/32/FPU.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2020, Anton Krotov + Copyright (c) 2020-2021, Anton Krotov All rights reserved. *) @@ -98,12 +98,12 @@ END mul2; PROCEDURE add2 (b, a: INTEGER): INTEGER; VAR - ea, eb, e, d, r: INTEGER; + t, e, d: INTEGER; BEGIN - ea := (a DIV 800000H) MOD 256; - eb := (b DIV 800000H) MOD 256; - d := ea - eb; + e := (a DIV 800000H) MOD 256; + t := (b DIV 800000H) MOD 256; + d := e - t; a := a MOD 800000H + 800000H; b := b MOD 800000H + 800000H; @@ -113,61 +113,56 @@ BEGIN b := LSR(b, d) ELSE b := 0 - END; - e := ea + END ELSIF d < 0 THEN IF d > -24 THEN a := LSR(a, -d) ELSE a := 0 END; - e := eb - ELSE - e := ea + e := t END; - r := a + b; + INC(a, b); - IF r >= 1000000H THEN - r := r DIV 2; + IF a >= 1000000H THEN + a := a DIV 2; INC(e) END; IF e >= 255 THEN e := 255; - r := 800000H + a := 800000H END - RETURN (r - 800000H) + e * 800000H + RETURN (a - 800000H) + e * 800000H END add2; PROCEDURE sub2 (b, a: INTEGER): INTEGER; VAR - ea, eb, e, d, r, s: INTEGER; + t, e, d, s: INTEGER; BEGIN - ea := (a DIV 800000H) MOD 256; - eb := (b DIV 800000H) MOD 256; + e := (a DIV 800000H) MOD 256; + t := (b DIV 800000H) MOD 256; a := a MOD 800000H + 800000H; b := b MOD 800000H + 800000H; - d := ea - eb; + d := e - t; IF (d > 0) OR (d = 0) & (a >= b) THEN s := 0 ELSE - ea := eb; + e := t; d := -d; - r := a; + t := a; a := b; - b := r; + b := t; s := 80000000H END; - e := ea; - IF d > 0 THEN IF d < 24 THEN b := LSR(b, d) @@ -176,32 +171,32 @@ BEGIN END END; - r := a - b; + DEC(a, b); - IF r = 0 THEN + IF a = 0 THEN e := 0; - r := 800000H; + a := 800000H; s := 0 ELSE - WHILE r < 800000H DO - r := r * 2; + WHILE a < 800000H DO + a := a * 2; DEC(e) END END; IF e <= 0 THEN e := 0; - r := 800000H; + a := 800000H; s := 0 END - RETURN (r - 800000H) + e * 800000H + s + RETURN (a - 800000H) + e * 800000H + s END sub2; PROCEDURE zero (VAR x: INTEGER); BEGIN - IF BITS(x) * {23..30} = {} THEN + IF LSR(LSL(x, 1), 24) = 0 THEN x := 0 END END zero; @@ -213,12 +208,13 @@ END isNaN; PROCEDURE isInf (a: INTEGER): BOOLEAN; - RETURN (a = INF) OR (a = NINF) + RETURN LSL(a, 1) = 0FF000000H END isInf; -PROCEDURE isNormal (a: INTEGER): BOOLEAN; - RETURN (BITS(a) * {23..30} # {23..30}) & (BITS(a) * {23..30} # {}) +PROCEDURE isNormal (a, b: INTEGER): BOOLEAN; + RETURN (LSR(LSL(a, 1), 24) # 255) & (LSR(LSL(a, 1), 24) # 0) & + (LSR(LSL(b, 1), 24) # 255) & (LSR(LSL(b, 1), 24) # 0) END isNormal; @@ -229,16 +225,20 @@ VAR BEGIN zero(a); zero(b); - IF isNormal(a) & isNormal(b) THEN + IF isNormal(a, b) THEN - IF (a > 0) & (b > 0) THEN - r := add2(b, a) - ELSIF (a < 0) & (b < 0) THEN - r := add2(b, a) + 80000000H - ELSIF (a > 0) & (b < 0) THEN - r := sub2(b, a) - ELSIF (a < 0) & (b > 0) THEN - r := sub2(a, b) + IF a > 0 THEN + IF b > 0 THEN + r := add2(b, a) + ELSE + r := sub2(b, a) + END + ELSE + IF b > 0 THEN + r := sub2(a, b) + ELSE + r := add2(b, a) + 80000000H + END END ELSIF isNaN(a) OR isNaN(b) THEN @@ -270,16 +270,20 @@ VAR BEGIN zero(a); zero(b); - IF isNormal(a) & isNormal(b) THEN + IF isNormal(a, b) THEN - IF (a > 0) & (b > 0) THEN - r := sub2(b, a) - ELSIF (a < 0) & (b < 0) THEN - r := sub2(a, b) - ELSIF (a > 0) & (b < 0) THEN - r := add2(b, a) - ELSIF (a < 0) & (b > 0) THEN - r := add2(b, a) + 80000000H + IF a > 0 THEN + IF b > 0 THEN + r := sub2(b, a) + ELSE + r := add2(b, a) + END + ELSE + IF b > 0 THEN + r := add2(b, a) + 80000000H + ELSE + r := sub2(a, b) + END END ELSIF isNaN(a) OR isNaN(b) THEN @@ -313,11 +317,9 @@ VAR BEGIN zero(a); zero(b); - IF isNormal(a) & isNormal(b) THEN + IF isNormal(a, b) THEN r := mul2(b, a) - ELSIF isNaN(a) OR isNaN(b) THEN - r := NAN - ELSIF (isInf(a) & (b = 0)) OR (isInf(b) & (a = 0)) THEN + ELSIF isNaN(a) OR isNaN(b) OR (isInf(a) & (b = 0)) OR (isInf(b) & (a = 0)) THEN r := NAN ELSIF isInf(a) OR isInf(b) THEN r := INF + ORD(BITS(a) / BITS(b) - {0..30}) @@ -336,11 +338,9 @@ VAR BEGIN zero(a); zero(b); - IF isNormal(a) & isNormal(b) THEN + IF isNormal(a, b) THEN r := div2(b, a) - ELSIF isNaN(a) OR isNaN(b) THEN - r := NAN - ELSIF isInf(a) & isInf(b) THEN + ELSIF isNaN(a) OR isNaN(b) OR isInf(a) & isInf(b) THEN r := NAN ELSIF isInf(a) THEN r := INF + ORD(BITS(a) / BITS(b) - {0..30}) @@ -373,23 +373,18 @@ BEGIN IF isNaN(a) OR isNaN(b) THEN res := op = 1 - ELSIF (a < 0) & (b < 0) THEN - CASE op OF - |0: res := a = b - |1: res := a # b - |2: res := a > b - |3: res := a >= b - |4: res := a < b - |5: res := a <= b - END ELSE + IF (a < 0) & (b < 0) THEN + INC(op, 6) + END; + CASE op OF - |0: res := a = b - |1: res := a # b - |2: res := a < b - |3: res := a <= b - |4: res := a > b - |5: res := a >= b + |0, 6: res := a = b + |1, 7: res := a # b + |2, 10: res := a < b + |3, 11: res := a <= b + |4, 8: res := a > b + |5, 9: res := a >= b END END @@ -399,38 +394,38 @@ END cmp; PROCEDURE flt* (x: INTEGER): INTEGER; VAR - n, y, r, s: INTEGER; + n, y, s: INTEGER; BEGIN IF x = 0 THEN s := 0; - r := 800000H; + x := 800000H; n := -126 ELSIF x = 80000000H THEN s := 80000000H; - r := 800000H; + x := 800000H; n := 32 ELSE IF x < 0 THEN - s := 80000000H + s := 80000000H; + x := -x ELSE s := 0 END; n := 0; - y := ABS(x); - r := y; + y := x; WHILE y > 0 DO y := y DIV 2; INC(n) END; IF n > 24 THEN - r := LSR(r, n - 24) + x := LSR(x, n - 24) ELSE - r := LSL(r, 24 - n) + x := LSL(x, 24 - n) END END - RETURN (r - 800000H) + (n + 126) * 800000H + s + RETURN (x - 800000H) + (n + 126) * 800000H + s END flt; diff --git a/programs/develop/oberon07/lib/RVMxI/32/HOST.ob07 b/programs/develop/oberon07/lib/RVMxI/32/HOST.ob07 new file mode 100644 index 0000000000..6d35610929 --- /dev/null +++ b/programs/develop/oberon07/lib/RVMxI/32/HOST.ob07 @@ -0,0 +1,185 @@ +(* + BSD 2-Clause License + + Copyright (c) 2020-2021, Anton Krotov + All rights reserved. +*) + +MODULE HOST; + +IMPORT SYSTEM, Trap; + + +CONST + + $IF (host_linux) + + slash* = "/"; + eol* = 0AX; + + $ELSE + + slash* = "\"; + eol* = 0DX + 0AX; + + $END + + bit_depth* = 32; + maxint* = 7FFFFFFFH; + minint* = 80000000H; + + +VAR + + maxreal*: REAL; + + +PROCEDURE syscall0 (fn: INTEGER): INTEGER; +BEGIN + Trap.syscall(SYSTEM.ADR(fn)) + RETURN fn +END syscall0; + + +PROCEDURE syscall1 (fn, p1: INTEGER): INTEGER; +BEGIN + Trap.syscall(SYSTEM.ADR(fn)) + RETURN fn +END syscall1; + + +PROCEDURE syscall2 (fn, p1, p2: INTEGER): INTEGER; +BEGIN + Trap.syscall(SYSTEM.ADR(fn)) + RETURN fn +END syscall2; + + +PROCEDURE syscall3 (fn, p1, p2, p3: INTEGER): INTEGER; +BEGIN + Trap.syscall(SYSTEM.ADR(fn)) + RETURN fn +END syscall3; + + +PROCEDURE syscall4 (fn, p1, p2, p3, p4: INTEGER): INTEGER; +BEGIN + Trap.syscall(SYSTEM.ADR(fn)) + RETURN fn +END syscall4; + + +PROCEDURE ExitProcess* (code: INTEGER); +BEGIN + code := syscall1(0, code) +END ExitProcess; + + +PROCEDURE GetCurrentDirectory* (VAR path: ARRAY OF CHAR); +VAR + a: INTEGER; +BEGIN + a := syscall2(1, LEN(path), SYSTEM.ADR(path[0])) +END GetCurrentDirectory; + + +PROCEDURE GetArg* (n: INTEGER; VAR s: ARRAY OF CHAR); +BEGIN + n := syscall3(2, n, LEN(s), SYSTEM.ADR(s[0])) +END GetArg; + + +PROCEDURE FileRead* (F: INTEGER; VAR Buffer: ARRAY OF CHAR; bytes: INTEGER): INTEGER; + RETURN syscall4(3, F, LEN(Buffer), SYSTEM.ADR(Buffer[0]), bytes) +END FileRead; + + +PROCEDURE FileWrite* (F: INTEGER; Buffer: ARRAY OF BYTE; bytes: INTEGER): INTEGER; + RETURN syscall4(4, F, LEN(Buffer), SYSTEM.ADR(Buffer[0]), bytes) +END FileWrite; + + +PROCEDURE FileCreate* (FName: ARRAY OF CHAR): INTEGER; + RETURN syscall2(5, LEN(FName), SYSTEM.ADR(FName[0])) +END FileCreate; + + +PROCEDURE FileClose* (F: INTEGER); +BEGIN + F := syscall1(6, F) +END FileClose; + + +PROCEDURE FileOpen* (FName: ARRAY OF CHAR): INTEGER; + RETURN syscall2(7, LEN(FName), SYSTEM.ADR(FName[0])) +END FileOpen; + + +PROCEDURE chmod* (FName: ARRAY OF CHAR); +VAR + a: INTEGER; +BEGIN + a := syscall2(12, LEN(FName), SYSTEM.ADR(FName[0])) +END chmod; + + +PROCEDURE OutChar* (c: CHAR); +VAR + a: INTEGER; +BEGIN + a := syscall1(8, ORD(c)) +END OutChar; + + +PROCEDURE GetTickCount* (): INTEGER; + RETURN syscall0(9) +END GetTickCount; + + +PROCEDURE isRelative* (path: ARRAY OF CHAR): BOOLEAN; + RETURN syscall2(11, LEN(path), SYSTEM.ADR(path[0])) # 0 +END isRelative; + + +PROCEDURE UnixTime* (): INTEGER; + RETURN syscall0(10) +END UnixTime; + + +PROCEDURE s2d (x: INTEGER; VAR h, l: INTEGER); +VAR + s, e, f: INTEGER; +BEGIN + s := ASR(x, 31) MOD 2; + f := x MOD 800000H; + e := (x DIV 800000H) MOD 256; + IF e = 255 THEN + e := 2047 + ELSE + INC(e, 896) + END; + h := LSL(s, 31) + LSL(e, 20) + (f DIV 8); + l := (f MOD 8) * 20000000H +END s2d; + + +PROCEDURE d2s* (x: REAL): INTEGER; +VAR + i: INTEGER; +BEGIN + SYSTEM.GET(SYSTEM.ADR(x), i) + RETURN i +END d2s; + + +PROCEDURE splitf* (x: REAL; VAR a, b: INTEGER): INTEGER; +BEGIN + s2d(d2s(x), b, a) + RETURN a +END splitf; + + +BEGIN + maxreal := 1.9; + PACK(maxreal, 127) +END HOST. \ No newline at end of file diff --git a/programs/develop/oberon07/lib/RVMxI/32/Out.ob07 b/programs/develop/oberon07/lib/RVMxI/32/Out.ob07 new file mode 100644 index 0000000000..aad7567e73 --- /dev/null +++ b/programs/develop/oberon07/lib/RVMxI/32/Out.ob07 @@ -0,0 +1,273 @@ +(* + BSD 2-Clause License + + Copyright (c) 2016, 2018, 2020, Anton Krotov + All rights reserved. +*) + +MODULE Out; + +IMPORT HOST, SYSTEM; + + +PROCEDURE Char* (c: CHAR); +BEGIN + HOST.OutChar(c) +END Char; + + +PROCEDURE String* (s: ARRAY OF CHAR); +VAR + i, n: INTEGER; + +BEGIN + n := LENGTH(s) - 1; + FOR i := 0 TO n DO + Char(s[i]) + END +END String; + + +PROCEDURE Int* (x, width: INTEGER); +VAR + i, a: INTEGER; + str: ARRAY 12 OF CHAR; + +BEGIN + IF x = 80000000H THEN + COPY("-2147483648", str); + DEC(width, 11) + ELSE + i := 0; + IF x < 0 THEN + x := -x; + i := 1; + str[0] := "-" + END; + + a := x; + REPEAT + INC(i); + a := a DIV 10 + UNTIL a = 0; + + str[i] := 0X; + DEC(width, i); + + REPEAT + DEC(i); + str[i] := CHR(x MOD 10 + ORD("0")); + x := x DIV 10 + UNTIL x = 0 + END; + + WHILE width > 0 DO + Char(20X); + DEC(width) + END; + + String(str) +END Int; + + +PROCEDURE Inf (x: REAL; width: INTEGER); +VAR + s: ARRAY 5 OF CHAR; + +BEGIN + DEC(width, 4); + IF x # x THEN + s := " Nan" + ELSIF x = SYSTEM.INF() THEN + s := "+Inf" + ELSIF x = -SYSTEM.INF() THEN + s := "-Inf" + END; + + WHILE width > 0 DO + Char(20X); + DEC(width) + END; + + String(s) +END Inf; + + +PROCEDURE Ln*; +BEGIN + Char(0DX); + Char(0AX) +END Ln; + + +PROCEDURE unpk10 (VAR x: REAL; VAR n: INTEGER); +VAR + a, b: REAL; + +BEGIN + ASSERT(x > 0.0); + n := 0; + WHILE x < 1.0 DO + x := x * 10.0; + DEC(n) + END; + + a := 10.0; + b := 1.0; + + WHILE a <= x DO + b := a; + a := a * 10.0; + INC(n) + END; + x := x / b +END unpk10; + + +PROCEDURE _Real (x: REAL; width: INTEGER); +VAR + n, k, p: INTEGER; + +BEGIN + p := MIN(MAX(width - 7, 1), 10); + + width := width - p - 7; + WHILE width > 0 DO + Char(20X); + DEC(width) + END; + + IF x < 0.0 THEN + Char("-"); + x := -x + ELSE + Char(20X) + END; + + unpk10(x, n); + + k := FLOOR(x); + Char(CHR(k + 30H)); + Char("."); + + WHILE p > 0 DO + x := (x - FLT(k)) * 10.0; + k := FLOOR(x); + Char(CHR(k + 30H)); + DEC(p) + END; + + Char("E"); + IF n >= 0 THEN + Char("+") + ELSE + Char("-") + END; + n := ABS(n); + Char(CHR(n DIV 10 + 30H)); + Char(CHR(n MOD 10 + 30H)) +END _Real; + + +PROCEDURE Real* (x: REAL; width: INTEGER); +BEGIN + IF (x # x) OR (ABS(x) = SYSTEM.INF()) THEN + Inf(x, width) + ELSIF x = 0.0 THEN + WHILE width > 17 DO + Char(20X); + DEC(width) + END; + DEC(width, 8); + String(" 0.0"); + WHILE width > 0 DO + Char("0"); + DEC(width) + END; + String("E+00") + ELSE + _Real(x, width) + END +END Real; + + +PROCEDURE _FixReal (x: REAL; width, p: INTEGER); +VAR + n, k: INTEGER; + minus: BOOLEAN; + +BEGIN + minus := x < 0.0; + IF minus THEN + x := -x + END; + + unpk10(x, n); + + DEC(width, 3 + MAX(p, 0) + MAX(n, 0)); + WHILE width > 0 DO + Char(20X); + DEC(width) + END; + + IF minus THEN + Char("-") + ELSE + Char(20X) + END; + + IF n < 0 THEN + INC(n); + Char("0"); + Char("."); + WHILE (n < 0) & (p > 0) DO + Char("0"); + INC(n); + DEC(p) + END + ELSE + WHILE n >= 0 DO + k := FLOOR(x); + Char(CHR(k + 30H)); + x := (x - FLT(k)) * 10.0; + DEC(n) + END; + Char(".") + END; + + WHILE p > 0 DO + k := FLOOR(x); + Char(CHR(k + 30H)); + x := (x - FLT(k)) * 10.0; + DEC(p) + END + +END _FixReal; + + +PROCEDURE FixReal* (x: REAL; width, p: INTEGER); +BEGIN + IF (x # x) OR (ABS(x) = SYSTEM.INF()) THEN + Inf(x, width) + ELSIF x = 0.0 THEN + DEC(width, 3 + MAX(p, 0)); + WHILE width > 0 DO + Char(20X); + DEC(width) + END; + String(" 0."); + WHILE p > 0 DO + Char("0"); + DEC(p) + END + ELSE + _FixReal(x, width, p) + END +END FixReal; + + +PROCEDURE Open*; +END Open; + + +END Out. \ No newline at end of file diff --git a/programs/develop/oberon07/Lib/STM32CM3/RTL.ob07 b/programs/develop/oberon07/lib/RVMxI/32/RTL.ob07 similarity index 79% rename from programs/develop/oberon07/Lib/STM32CM3/RTL.ob07 rename to programs/develop/oberon07/lib/RVMxI/32/RTL.ob07 index 255f812885..d23ad3735e 100644 --- a/programs/develop/oberon07/Lib/STM32CM3/RTL.ob07 +++ b/programs/develop/oberon07/lib/RVMxI/32/RTL.ob07 @@ -1,13 +1,13 @@ (* BSD 2-Clause License - Copyright (c) 2019-2020, Anton Krotov + Copyright (c) 2019-2021, Anton Krotov All rights reserved. *) MODULE RTL; -IMPORT SYSTEM, F := FPU; +IMPORT SYSTEM, F := FPU, Trap; CONST @@ -25,8 +25,10 @@ VAR Heap, Types, TypesCount: INTEGER; -PROCEDURE [code] sp (): INTEGER - 4668H; (* mov r0, sp *) +PROCEDURE _error* (modnum, _module, err, line: INTEGER); +BEGIN + Trap.trap(modnum, _module, err, line) +END _error; PROCEDURE _fmul* (b, a: INTEGER): INTEGER; @@ -157,20 +159,14 @@ VAR i: INTEGER; BEGIN - WHILE ((source MOD WORD # 0) OR (dest MOD WORD # 0)) & (bytes > 0) DO - SYSTEM.GET(source, b); - SYSTEM.PUT8(dest, b); - INC(source); - INC(dest); - DEC(bytes) - END; - - WHILE bytes >= WORD DO - SYSTEM.GET(source, i); - SYSTEM.PUT(dest, i); - INC(source, WORD); - INC(dest, WORD); - DEC(bytes, WORD) + IF (source MOD WORD = 0) & (dest MOD WORD = 0) THEN + WHILE bytes >= WORD DO + SYSTEM.GET(source, i); + SYSTEM.PUT(dest, i); + INC(source, WORD); + INC(dest, WORD); + DEC(bytes, WORD) + END END; WHILE bytes > 0 DO @@ -207,7 +203,7 @@ VAR res: INTEGER; BEGIN - res := 0; + res := minint; WHILE n > 0 DO SYSTEM.GET(a, A); INC(a); SYSTEM.GET(b, B); INC(b); @@ -216,6 +212,7 @@ BEGIN res := ORD(A) - ORD(B); n := 0 ELSIF A = 0X THEN + res := 0; n := 0 END END @@ -225,13 +222,22 @@ END strncmp; PROCEDURE _strcmp* (op, len2, str2, len1, str1: INTEGER): BOOLEAN; VAR - res: INTEGER; + res: INTEGER; bRes: BOOLEAN; + c: CHAR; BEGIN res := strncmp(str1, str2, MIN(len1, len2)); - IF res = 0 THEN - res := _length(len1, str1) - _length(len2, str2) + IF res = minint THEN + IF len1 > len2 THEN + SYSTEM.GET(str1 + len2, c); + res := ORD(c) + ELSIF len1 < len2 THEN + SYSTEM.GET(str2 + len1, c); + res := -ORD(c) + ELSE + res := 0 + END END; CASE op OF @@ -253,7 +259,7 @@ VAR res: INTEGER; BEGIN - res := 0; + res := minint; WHILE n > 0 DO SYSTEM.GET(a, A); INC(a, 2); SYSTEM.GET(b, B); INC(b, 2); @@ -261,7 +267,8 @@ BEGIN IF A # B THEN res := ORD(A) - ORD(B); n := 0 - ELSIF A = WCHR(0) THEN + ELSIF A = 0X THEN + res := 0; n := 0 END END @@ -271,13 +278,22 @@ END strncmpw; PROCEDURE _strcmpw* (op, len2, str2, len1, str1: INTEGER): BOOLEAN; VAR - res: INTEGER; + res: INTEGER; bRes: BOOLEAN; + c: WCHAR; BEGIN res := strncmpw(str1, str2, MIN(len1, len2)); - IF res = 0 THEN - res := _lengthw(len1, str1) - _lengthw(len2, str2) + IF res = minint THEN + IF len1 > len2 THEN + SYSTEM.GET(str1 + len2 * 2, c); + res := ORD(c) + ELSIF len1 < len2 THEN + SYSTEM.GET(str2 + len1 * 2, c); + res := -ORD(c) + ELSE + res := 0 + END END; CASE op OF @@ -316,15 +332,22 @@ END _strcpy; PROCEDURE _new* (t, size: INTEGER; VAR p: INTEGER); +VAR + ptr: INTEGER; + BEGIN - IF Heap + size < sp() - 64 THEN - p := Heap + WORD; - REPEAT - SYSTEM.PUT(Heap, t); - INC(Heap, WORD); - DEC(size, WORD); - t := 0 - UNTIL size = 0 + ptr := Heap; + IF ptr + size < Trap.sp() - 64 THEN + INC(Heap, size); + p := ptr + WORD; + SYSTEM.PUT(ptr, t); + INC(ptr, WORD); + DEC(size, WORD); + WHILE size > 0 DO + SYSTEM.PUT(ptr, 0); + INC(ptr, WORD); + DEC(size, WORD) + END ELSE p := 0 END diff --git a/programs/develop/oberon07/lib/RVMxI/32/Trap.ob07 b/programs/develop/oberon07/lib/RVMxI/32/Trap.ob07 new file mode 100644 index 0000000000..3148602620 --- /dev/null +++ b/programs/develop/oberon07/lib/RVMxI/32/Trap.ob07 @@ -0,0 +1,133 @@ +(* + BSD 2-Clause License + + Copyright (c) 2020-2021, Anton Krotov + All rights reserved. +*) + +MODULE Trap; + +IMPORT SYSTEM; + + +CONST + + SP = 4; + + +PROCEDURE [code] sp* (): INTEGER + 22, 0, SP; (* MOV R0, SP *) + + +PROCEDURE [code] syscall* (ptr: INTEGER) + 22, 0, SP, (* MOV R0, SP *) + 27, 0, 4, (* ADD R0, 4 *) + 9, 0, 0, (* LDW R0, R0 *) + 67, 0, 0; (* SYSCALL R0 *) + + +PROCEDURE Char (c: CHAR); +VAR + a: ARRAY 2 OF INTEGER; + +BEGIN + a[0] := 8; + a[1] := ORD(c); + syscall(SYSTEM.ADR(a[0])) +END Char; + + +PROCEDURE String (s: ARRAY OF CHAR); +VAR + i: INTEGER; + +BEGIN + i := 0; + WHILE s[i] # 0X DO + Char(s[i]); + INC(i) + END +END String; + + +PROCEDURE PString (ptr: INTEGER); +VAR + c: CHAR; + +BEGIN + SYSTEM.GET(ptr, c); + WHILE c # 0X DO + Char(c); + INC(ptr); + SYSTEM.GET(ptr, c) + END +END PString; + + +PROCEDURE Ln; +BEGIN + String(0DX + 0AX) +END Ln; + + +PROCEDURE IntToStr (x: INTEGER; VAR str: ARRAY OF CHAR); +VAR + i, a: INTEGER; + +BEGIN + i := 0; + a := x; + REPEAT + INC(i); + a := a DIV 10 + UNTIL a = 0; + + str[i] := 0X; + + REPEAT + DEC(i); + str[i] := CHR(x MOD 10 + ORD("0")); + x := x DIV 10 + UNTIL x = 0 +END IntToStr; + + +PROCEDURE Int (x: INTEGER); +VAR + s: ARRAY 32 OF CHAR; + +BEGIN + IntToStr(x, s); + String(s) +END Int; + + +PROCEDURE trap* (modnum, _module, err, line: INTEGER); +VAR + s: ARRAY 32 OF CHAR; + +BEGIN + CASE err OF + | 1: s := "assertion failure" + | 2: s := "NIL dereference" + | 3: s := "bad divisor" + | 4: s := "NIL procedure call" + | 5: s := "type guard error" + | 6: s := "index out of range" + | 7: s := "invalid CASE" + | 8: s := "array assignment error" + | 9: s := "CHR out of range" + |10: s := "WCHR out of range" + |11: s := "BYTE out of range" + END; + + Ln; + String("error ("); Int(err); String("): "); String(s); Ln; + String("module: "); PString(_module); Ln; + String("line: "); Int(line); Ln; + + SYSTEM.CODE(0, 0, 0) (* STOP *) +END trap; + + +END Trap. \ No newline at end of file diff --git a/programs/develop/oberon07/lib/RVMxI/64/HOST.ob07 b/programs/develop/oberon07/lib/RVMxI/64/HOST.ob07 new file mode 100644 index 0000000000..ac5ba4f798 --- /dev/null +++ b/programs/develop/oberon07/lib/RVMxI/64/HOST.ob07 @@ -0,0 +1,201 @@ +(* + BSD 2-Clause License + + Copyright (c) 2020-2021, Anton Krotov + All rights reserved. +*) + +MODULE HOST; + +IMPORT SYSTEM, Trap; + + +CONST + + $IF (host_linux) + + slash* = "/"; + eol* = 0AX; + + $ELSE + + slash* = "\"; + eol* = 0DX + 0AX; + + $END + + bit_depth* = 64; + maxint* = ROR(-2, 1); + minint* = ROR(1, 1); + + +VAR + + maxreal*: REAL; + + +PROCEDURE syscall0 (fn: INTEGER): INTEGER; +BEGIN + Trap.syscall(SYSTEM.ADR(fn)) + RETURN fn +END syscall0; + + +PROCEDURE syscall1 (fn, p1: INTEGER): INTEGER; +BEGIN + Trap.syscall(SYSTEM.ADR(fn)) + RETURN fn +END syscall1; + + +PROCEDURE syscall2 (fn, p1, p2: INTEGER): INTEGER; +BEGIN + Trap.syscall(SYSTEM.ADR(fn)) + RETURN fn +END syscall2; + + +PROCEDURE syscall3 (fn, p1, p2, p3: INTEGER): INTEGER; +BEGIN + Trap.syscall(SYSTEM.ADR(fn)) + RETURN fn +END syscall3; + + +PROCEDURE syscall4 (fn, p1, p2, p3, p4: INTEGER): INTEGER; +BEGIN + Trap.syscall(SYSTEM.ADR(fn)) + RETURN fn +END syscall4; + + +PROCEDURE ExitProcess* (code: INTEGER); +BEGIN + code := syscall1(0, code) +END ExitProcess; + + +PROCEDURE GetCurrentDirectory* (VAR path: ARRAY OF CHAR); +VAR + a: INTEGER; +BEGIN + a := syscall2(1, LEN(path), SYSTEM.ADR(path[0])) +END GetCurrentDirectory; + + +PROCEDURE GetArg* (n: INTEGER; VAR s: ARRAY OF CHAR); +BEGIN + n := syscall3(2, n, LEN(s), SYSTEM.ADR(s[0])) +END GetArg; + + +PROCEDURE FileRead* (F: INTEGER; VAR Buffer: ARRAY OF CHAR; bytes: INTEGER): INTEGER; + RETURN syscall4(3, F, LEN(Buffer), SYSTEM.ADR(Buffer[0]), bytes) +END FileRead; + + +PROCEDURE FileWrite* (F: INTEGER; Buffer: ARRAY OF BYTE; bytes: INTEGER): INTEGER; + RETURN syscall4(4, F, LEN(Buffer), SYSTEM.ADR(Buffer[0]), bytes) +END FileWrite; + + +PROCEDURE FileCreate* (FName: ARRAY OF CHAR): INTEGER; + RETURN syscall2(5, LEN(FName), SYSTEM.ADR(FName[0])) +END FileCreate; + + +PROCEDURE FileClose* (F: INTEGER); +BEGIN + F := syscall1(6, F) +END FileClose; + + +PROCEDURE FileOpen* (FName: ARRAY OF CHAR): INTEGER; + RETURN syscall2(7, LEN(FName), SYSTEM.ADR(FName[0])) +END FileOpen; + + +PROCEDURE chmod* (FName: ARRAY OF CHAR); +VAR + a: INTEGER; +BEGIN + a := syscall2(12, LEN(FName), SYSTEM.ADR(FName[0])) +END chmod; + + +PROCEDURE OutChar* (c: CHAR); +VAR + a: INTEGER; +BEGIN + a := syscall1(8, ORD(c)) +END OutChar; + + +PROCEDURE GetTickCount* (): INTEGER; + RETURN syscall0(9) +END GetTickCount; + + +PROCEDURE isRelative* (path: ARRAY OF CHAR): BOOLEAN; + RETURN syscall2(11, LEN(path), SYSTEM.ADR(path[0])) # 0 +END isRelative; + + +PROCEDURE UnixTime* (): INTEGER; + RETURN syscall0(10) +END UnixTime; + + +PROCEDURE splitf* (x: REAL; VAR a, b: INTEGER): INTEGER; +VAR + res: INTEGER; + +BEGIN + a := 0; + b := 0; + SYSTEM.GET32(SYSTEM.ADR(x), a); + SYSTEM.GET32(SYSTEM.ADR(x) + 4, b); + SYSTEM.GET(SYSTEM.ADR(x), res) + RETURN res +END splitf; + + +PROCEDURE d2s* (x: REAL): INTEGER; +VAR + h, l, s, e: INTEGER; + +BEGIN + e := splitf(x, l, h); + + s := ASR(h, 31) MOD 2; + e := (h DIV 100000H) MOD 2048; + IF e <= 896 THEN + h := (h MOD 100000H) * 8 + (l DIV 20000000H) MOD 8 + 800000H; + REPEAT + h := h DIV 2; + INC(e) + UNTIL e = 897; + e := 896; + l := (h MOD 8) * 20000000H; + h := h DIV 8 + ELSIF (1151 <= e) & (e < 2047) THEN + e := 1151; + h := 0; + l := 0 + ELSIF e = 2047 THEN + e := 1151; + IF (h MOD 100000H # 0) OR (BITS(l) * {0..31} # {}) THEN + h := 80000H; + l := 0 + END + END; + DEC(e, 896) + + RETURN LSL(s, 31) + LSL(e, 23) + (h MOD 100000H) * 8 + (l DIV 20000000H) MOD 8 +END d2s; + + +BEGIN + maxreal := 1.9; + PACK(maxreal, 1023) +END HOST. \ No newline at end of file diff --git a/programs/develop/oberon07/lib/RVMxI/64/Out.ob07 b/programs/develop/oberon07/lib/RVMxI/64/Out.ob07 new file mode 100644 index 0000000000..5fbf92cc2f --- /dev/null +++ b/programs/develop/oberon07/lib/RVMxI/64/Out.ob07 @@ -0,0 +1,288 @@ +(* + BSD 2-Clause License + + Copyright (c) 2016, 2018, 2020-2021 Anton Krotov + All rights reserved. +*) + +MODULE Out; + +IMPORT HOST, SYSTEM; + + +PROCEDURE Char* (c: CHAR); +BEGIN + HOST.OutChar(c) +END Char; + + +PROCEDURE String* (s: ARRAY OF CHAR); +VAR + i, n: INTEGER; + +BEGIN + n := LENGTH(s) - 1; + FOR i := 0 TO n DO + Char(s[i]) + END +END String; + + +PROCEDURE Int* (x, width: INTEGER); +VAR + i, a: INTEGER; + str: ARRAY 21 OF CHAR; + +BEGIN + IF x = ROR(1, 1) THEN + str := "-9223372036854775808"; + DEC(width, 20) + ELSE + i := 0; + IF x < 0 THEN + x := -x; + i := 1; + str[0] := "-" + END; + + a := x; + REPEAT + INC(i); + a := a DIV 10 + UNTIL a = 0; + + str[i] := 0X; + DEC(width, i); + + REPEAT + DEC(i); + str[i] := CHR(x MOD 10 + ORD("0")); + x := x DIV 10 + UNTIL x = 0 + END; + + WHILE width > 0 DO + Char(20X); + DEC(width) + END; + + String(str) +END Int; + + +PROCEDURE IsNan (x: REAL): BOOLEAN; +CONST + INF = LSR(ASR(ROR(1, 1), 10), 1); + NINF = ASR(ASR(ROR(1, 1), 10), 1); + +VAR + a: INTEGER; + +BEGIN + SYSTEM.GET(SYSTEM.ADR(x), a) + RETURN (a > INF) OR (a < 0) & (a > NINF) +END IsNan; + + +PROCEDURE Inf (x: REAL; width: INTEGER); +VAR + s: ARRAY 5 OF CHAR; + +BEGIN + DEC(width, 4); + IF IsNan(x) THEN + s := " Nan" + ELSIF x = SYSTEM.INF() THEN + s := "+Inf" + ELSIF x = -SYSTEM.INF() THEN + s := "-Inf" + END; + + WHILE width > 0 DO + Char(20X); + DEC(width) + END; + + String(s) +END Inf; + + +PROCEDURE Ln*; +BEGIN + Char(0DX); + Char(0AX) +END Ln; + + +PROCEDURE unpk10 (VAR x: REAL; VAR n: INTEGER); +VAR + a, b: REAL; + +BEGIN + ASSERT(x > 0.0); + n := 0; + WHILE x < 1.0 DO + x := x * 10.0; + DEC(n) + END; + + a := 10.0; + b := 1.0; + + WHILE a <= x DO + b := a; + a := a * 10.0; + INC(n) + END; + x := x / b +END unpk10; + + +PROCEDURE _Real (x: REAL; width: INTEGER); +VAR + n, k, p: INTEGER; + +BEGIN + p := MIN(MAX(width - 8, 1), 15); + + width := width - p - 8; + WHILE width > 0 DO + Char(20X); + DEC(width) + END; + + IF x < 0.0 THEN + Char("-"); + x := -x + ELSE + Char(20X) + END; + + unpk10(x, n); + + k := FLOOR(x); + Char(CHR(k + 30H)); + Char("."); + + WHILE p > 0 DO + x := (x - FLT(k)) * 10.0; + k := FLOOR(x); + Char(CHR(k + 30H)); + DEC(p) + END; + + Char("E"); + IF n >= 0 THEN + Char("+") + ELSE + Char("-") + END; + n := ABS(n); + Char(CHR(n DIV 100 + 30H)); n := n MOD 100; + Char(CHR(n DIV 10 + 30H)); + Char(CHR(n MOD 10 + 30H)) +END _Real; + + +PROCEDURE Real* (x: REAL; width: INTEGER); +BEGIN + IF IsNan(x) OR (ABS(x) = SYSTEM.INF()) THEN + Inf(x, width) + ELSIF x = 0.0 THEN + WHILE width > 23 DO + Char(20X); + DEC(width) + END; + DEC(width, 9); + String(" 0.0"); + WHILE width > 0 DO + Char("0"); + DEC(width) + END; + String("E+000") + ELSE + _Real(x, width) + END +END Real; + + +PROCEDURE _FixReal (x: REAL; width, p: INTEGER); +VAR + n, k: INTEGER; + minus: BOOLEAN; + +BEGIN + minus := x < 0.0; + IF minus THEN + x := -x + END; + + unpk10(x, n); + + DEC(width, 3 + MAX(p, 0) + MAX(n, 0)); + WHILE width > 0 DO + Char(20X); + DEC(width) + END; + + IF minus THEN + Char("-") + ELSE + Char(20X) + END; + + IF n < 0 THEN + INC(n); + Char("0"); + Char("."); + WHILE (n < 0) & (p > 0) DO + Char("0"); + INC(n); + DEC(p) + END + ELSE + WHILE n >= 0 DO + k := FLOOR(x); + Char(CHR(k + 30H)); + x := (x - FLT(k)) * 10.0; + DEC(n) + END; + Char(".") + END; + + WHILE p > 0 DO + k := FLOOR(x); + Char(CHR(k + 30H)); + x := (x - FLT(k)) * 10.0; + DEC(p) + END + +END _FixReal; + + +PROCEDURE FixReal* (x: REAL; width, p: INTEGER); +BEGIN + IF IsNan(x) OR (ABS(x) = SYSTEM.INF()) THEN + Inf(x, width) + ELSIF x = 0.0 THEN + DEC(width, 3 + MAX(p, 0)); + WHILE width > 0 DO + Char(20X); + DEC(width) + END; + String(" 0."); + WHILE p > 0 DO + Char("0"); + DEC(p) + END + ELSE + _FixReal(x, width, p) + END +END FixReal; + + +PROCEDURE Open*; +END Open; + + +END Out. \ No newline at end of file diff --git a/programs/develop/oberon07/lib/RVMxI/64/RTL.ob07 b/programs/develop/oberon07/lib/RVMxI/64/RTL.ob07 new file mode 100644 index 0000000000..2c32d51ba8 --- /dev/null +++ b/programs/develop/oberon07/lib/RVMxI/64/RTL.ob07 @@ -0,0 +1,432 @@ +(* + BSD 2-Clause License + + Copyright (c) 2019-2021, Anton Krotov + All rights reserved. +*) + +MODULE RTL; + +IMPORT SYSTEM, Trap; + + +CONST + + bit_depth = 64; + maxint = ROR(-2, 1); + minint = ROR(1, 1); + + WORD = bit_depth DIV 8; + MAX_SET = bit_depth - 1; + + +VAR + + Heap, Types, TypesCount: INTEGER; + + +PROCEDURE _error* (modnum, _module, err, line: INTEGER); +BEGIN + Trap.trap(modnum, _module, err, line) +END _error; + + +PROCEDURE syscall1 (fn, p1: INTEGER): INTEGER; +BEGIN + Trap.syscall(SYSTEM.ADR(fn)) + RETURN fn +END syscall1; + + +PROCEDURE syscall2 (fn, p1, p2: INTEGER): INTEGER; +BEGIN + Trap.syscall(SYSTEM.ADR(fn)) + RETURN fn +END syscall2; + + +PROCEDURE syscall3 (fn, p1, p2, p3: INTEGER): INTEGER; +BEGIN + Trap.syscall(SYSTEM.ADR(fn)) + RETURN fn +END syscall3; + + +PROCEDURE _fmul* (b, a: INTEGER): INTEGER; + RETURN syscall2(100, b, a) +END _fmul; + + +PROCEDURE _fdiv* (b, a: INTEGER): INTEGER; + RETURN syscall2(101, b, a) +END _fdiv; + + +PROCEDURE _fdivi* (b, a: INTEGER): INTEGER; + RETURN syscall2(101, a, b) +END _fdivi; + + +PROCEDURE _fadd* (b, a: INTEGER): INTEGER; + RETURN syscall2(102, b, a) +END _fadd; + + +PROCEDURE _fsub* (b, a: INTEGER): INTEGER; + RETURN syscall2(103, b, a) +END _fsub; + + +PROCEDURE _fsubi* (b, a: INTEGER): INTEGER; + RETURN syscall2(103, a, b) +END _fsubi; + + +PROCEDURE _fcmp* (op, b, a: INTEGER): BOOLEAN; + RETURN syscall3(104, op, b, a) # 0 +END _fcmp; + + +PROCEDURE _floor* (x: INTEGER): INTEGER; + RETURN syscall1(105, x) +END _floor; + + +PROCEDURE _flt* (x: INTEGER): INTEGER; + RETURN syscall1(106, x) +END _flt; + + +PROCEDURE _pack* (n: INTEGER; VAR x: SET); +BEGIN + n := LSL((LSR(ORD(x), 52) MOD 2048 + n) MOD 2048, 52); + x := x - {52..62} + BITS(n) +END _pack; + + +PROCEDURE _unpk* (VAR n: INTEGER; VAR x: SET); +BEGIN + n := LSR(ORD(x), 52) MOD 2048 - 1023; + x := x - {62} + {52..61} +END _unpk; + + +PROCEDURE _rot* (VAR A: ARRAY OF INTEGER); +VAR + i, n, k: INTEGER; + +BEGIN + k := LEN(A) - 1; + n := A[0]; + i := 0; + WHILE i < k DO + A[i] := A[i + 1]; + INC(i) + END; + A[k] := n +END _rot; + + +PROCEDURE _set* (b, a: INTEGER): INTEGER; +BEGIN + IF (a <= b) & (a <= MAX_SET) & (b >= 0) THEN + IF b > MAX_SET THEN + b := MAX_SET + END; + IF a < 0 THEN + a := 0 + END; + a := LSR(ASR(minint, b - a), MAX_SET - b) + ELSE + a := 0 + END + + RETURN a +END _set; + + +PROCEDURE _set1* (a: INTEGER): INTEGER; +BEGIN + IF ASR(a, 6) = 0 THEN + a := LSL(1, a) + ELSE + a := 0 + END + RETURN a +END _set1; + + +PROCEDURE _length* (len, str: INTEGER): INTEGER; +VAR + c: CHAR; + res: INTEGER; + +BEGIN + res := 0; + REPEAT + SYSTEM.GET(str, c); + INC(str); + DEC(len); + INC(res) + UNTIL (len = 0) OR (c = 0X); + + RETURN res - ORD(c = 0X) +END _length; + + +PROCEDURE _move* (bytes, dest, source: INTEGER); +VAR + b: BYTE; + i: INTEGER; + +BEGIN + IF (source MOD WORD = 0) & (dest MOD WORD = 0) THEN + WHILE bytes >= WORD DO + SYSTEM.GET(source, i); + SYSTEM.PUT(dest, i); + INC(source, WORD); + INC(dest, WORD); + DEC(bytes, WORD) + END + END; + + WHILE bytes > 0 DO + SYSTEM.GET(source, b); + SYSTEM.PUT8(dest, b); + INC(source); + INC(dest); + DEC(bytes) + END +END _move; + + +PROCEDURE _lengthw* (len, str: INTEGER): INTEGER; +VAR + c: WCHAR; + res: INTEGER; + +BEGIN + res := 0; + REPEAT + SYSTEM.GET(str, c); + INC(str, 2); + DEC(len); + INC(res) + UNTIL (len = 0) OR (c = 0X); + + RETURN res - ORD(c = 0X) +END _lengthw; + + +PROCEDURE strncmp (a, b, n: INTEGER): INTEGER; +VAR + A, B: CHAR; + res: INTEGER; + +BEGIN + res := minint; + WHILE n > 0 DO + SYSTEM.GET(a, A); INC(a); + SYSTEM.GET(b, B); INC(b); + DEC(n); + IF A # B THEN + res := ORD(A) - ORD(B); + n := 0 + ELSIF A = 0X THEN + res := 0; + n := 0 + END + END + RETURN res +END strncmp; + + +PROCEDURE _strcmp* (op, len2, str2, len1, str1: INTEGER): BOOLEAN; +VAR + res: INTEGER; + bRes: BOOLEAN; + c: CHAR; + +BEGIN + res := strncmp(str1, str2, MIN(len1, len2)); + IF res = minint THEN + IF len1 > len2 THEN + SYSTEM.GET(str1 + len2, c); + res := ORD(c) + ELSIF len1 < len2 THEN + SYSTEM.GET(str2 + len1, c); + res := -ORD(c) + ELSE + res := 0 + END + END; + + CASE op OF + |0: bRes := res = 0 + |1: bRes := res # 0 + |2: bRes := res < 0 + |3: bRes := res <= 0 + |4: bRes := res > 0 + |5: bRes := res >= 0 + END + + RETURN bRes +END _strcmp; + + +PROCEDURE strncmpw (a, b, n: INTEGER): INTEGER; +VAR + A, B: WCHAR; + res: INTEGER; + +BEGIN + res := minint; + WHILE n > 0 DO + SYSTEM.GET(a, A); INC(a, 2); + SYSTEM.GET(b, B); INC(b, 2); + DEC(n); + IF A # B THEN + res := ORD(A) - ORD(B); + n := 0 + ELSIF A = 0X THEN + res := 0; + n := 0 + END + END + RETURN res +END strncmpw; + + +PROCEDURE _strcmpw* (op, len2, str2, len1, str1: INTEGER): BOOLEAN; +VAR + res: INTEGER; + bRes: BOOLEAN; + c: WCHAR; + +BEGIN + res := strncmpw(str1, str2, MIN(len1, len2)); + IF res = minint THEN + IF len1 > len2 THEN + SYSTEM.GET(str1 + len2 * 2, c); + res := ORD(c) + ELSIF len1 < len2 THEN + SYSTEM.GET(str2 + len1 * 2, c); + res := -ORD(c) + ELSE + res := 0 + END + END; + + CASE op OF + |0: bRes := res = 0 + |1: bRes := res # 0 + |2: bRes := res < 0 + |3: bRes := res <= 0 + |4: bRes := res > 0 + |5: bRes := res >= 0 + END + + RETURN bRes +END _strcmpw; + + +PROCEDURE _arrcpy* (base_size, len_dst, dst, len_src, src: INTEGER): BOOLEAN; +VAR + res: BOOLEAN; + +BEGIN + IF len_src > len_dst THEN + res := FALSE + ELSE + _move(len_src * base_size, dst, src); + res := TRUE + END + + RETURN res +END _arrcpy; + + +PROCEDURE _strcpy* (chr_size, len_src, src, len_dst, dst: INTEGER); +BEGIN + _move(MIN(len_dst, len_src) * chr_size, dst, src) +END _strcpy; + + +PROCEDURE _new* (t, size: INTEGER; VAR p: INTEGER); +VAR + ptr: INTEGER; + +BEGIN + ptr := Heap; + IF ptr + size < Trap.sp() - 128 THEN + INC(Heap, size); + p := ptr + WORD; + SYSTEM.PUT(ptr, t); + INC(ptr, WORD); + DEC(size, WORD); + WHILE size > 0 DO + SYSTEM.PUT(ptr, 0); + INC(ptr, WORD); + DEC(size, WORD) + END + ELSE + p := 0 + END +END _new; + + +PROCEDURE _guard* (t, p: INTEGER): BOOLEAN; +VAR + _type: INTEGER; + +BEGIN + SYSTEM.GET(p, p); + IF p # 0 THEN + SYSTEM.GET(p - WORD, _type); + WHILE (_type # t) & (_type # 0) DO + SYSTEM.GET(Types + _type * WORD, _type) + END + ELSE + _type := t + END + + RETURN _type = t +END _guard; + + +PROCEDURE _is* (t, p: INTEGER): BOOLEAN; +VAR + _type: INTEGER; + +BEGIN + _type := 0; + IF p # 0 THEN + SYSTEM.GET(p - WORD, _type); + WHILE (_type # t) & (_type # 0) DO + SYSTEM.GET(Types + _type * WORD, _type) + END + END + + RETURN _type = t +END _is; + + +PROCEDURE _guardrec* (t0, t1: INTEGER): BOOLEAN; +BEGIN + WHILE (t1 # t0) & (t1 # 0) DO + SYSTEM.GET(Types + t1 * WORD, t1) + END + + RETURN t1 = t0 +END _guardrec; + + +PROCEDURE _init* (tcount, heap, types: INTEGER); +BEGIN + Heap := heap; + TypesCount := tcount; + Types := types +END _init; + + +END RTL. \ No newline at end of file diff --git a/programs/develop/oberon07/lib/RVMxI/64/Trap.ob07 b/programs/develop/oberon07/lib/RVMxI/64/Trap.ob07 new file mode 100644 index 0000000000..a1c2fb0800 --- /dev/null +++ b/programs/develop/oberon07/lib/RVMxI/64/Trap.ob07 @@ -0,0 +1,133 @@ +(* + BSD 2-Clause License + + Copyright (c) 2020-2021, Anton Krotov + All rights reserved. +*) + +MODULE Trap; + +IMPORT SYSTEM; + + +CONST + + SP = 4; + + +PROCEDURE [code] sp* (): INTEGER + 22, 0, SP; (* MOV R0, SP *) + + +PROCEDURE [code] syscall* (ptr: INTEGER) + 22, 0, SP, (* MOV R0, SP *) + 27, 0, 8, (* ADD R0, 8 *) + 16, 0, 0, (* LDD R0, R0 *) + 67, 0, 0; (* SYSCALL R0 *) + + +PROCEDURE Char (c: CHAR); +VAR + a: ARRAY 2 OF INTEGER; + +BEGIN + a[0] := 8; + a[1] := ORD(c); + syscall(SYSTEM.ADR(a[0])) +END Char; + + +PROCEDURE String (s: ARRAY OF CHAR); +VAR + i: INTEGER; + +BEGIN + i := 0; + WHILE s[i] # 0X DO + Char(s[i]); + INC(i) + END +END String; + + +PROCEDURE PString (ptr: INTEGER); +VAR + c: CHAR; + +BEGIN + SYSTEM.GET(ptr, c); + WHILE c # 0X DO + Char(c); + INC(ptr); + SYSTEM.GET(ptr, c) + END +END PString; + + +PROCEDURE Ln; +BEGIN + String(0DX + 0AX) +END Ln; + + +PROCEDURE IntToStr (x: INTEGER; VAR str: ARRAY OF CHAR); +VAR + i, a: INTEGER; + +BEGIN + i := 0; + a := x; + REPEAT + INC(i); + a := a DIV 10 + UNTIL a = 0; + + str[i] := 0X; + + REPEAT + DEC(i); + str[i] := CHR(x MOD 10 + ORD("0")); + x := x DIV 10 + UNTIL x = 0 +END IntToStr; + + +PROCEDURE Int (x: INTEGER); +VAR + s: ARRAY 32 OF CHAR; + +BEGIN + IntToStr(x, s); + String(s) +END Int; + + +PROCEDURE trap* (modnum, _module, err, line: INTEGER); +VAR + s: ARRAY 32 OF CHAR; + +BEGIN + CASE err OF + | 1: s := "assertion failure" + | 2: s := "NIL dereference" + | 3: s := "bad divisor" + | 4: s := "NIL procedure call" + | 5: s := "type guard error" + | 6: s := "index out of range" + | 7: s := "invalid CASE" + | 8: s := "array assignment error" + | 9: s := "CHR out of range" + |10: s := "WCHR out of range" + |11: s := "BYTE out of range" + END; + + Ln; + String("error ("); Int(err); String("): "); String(s); Ln; + String("module: "); PString(_module); Ln; + String("line: "); Int(line); Ln; + + SYSTEM.CODE(0, 0, 0) (* STOP *) +END trap; + + +END Trap. \ No newline at end of file diff --git a/programs/develop/oberon07/Samples/KolibriOS/Dialogs.ob07 b/programs/develop/oberon07/samples/KolibriOS/Dialogs.ob07 similarity index 100% rename from programs/develop/oberon07/Samples/KolibriOS/Dialogs.ob07 rename to programs/develop/oberon07/samples/KolibriOS/Dialogs.ob07 diff --git a/programs/develop/oberon07/Samples/KolibriOS/HW.ob07 b/programs/develop/oberon07/samples/KolibriOS/HW.ob07 similarity index 100% rename from programs/develop/oberon07/Samples/KolibriOS/HW.ob07 rename to programs/develop/oberon07/samples/KolibriOS/HW.ob07 diff --git a/programs/develop/oberon07/Samples/KolibriOS/HW_con.ob07 b/programs/develop/oberon07/samples/KolibriOS/HW_con.ob07 similarity index 100% rename from programs/develop/oberon07/Samples/KolibriOS/HW_con.ob07 rename to programs/develop/oberon07/samples/KolibriOS/HW_con.ob07 diff --git a/programs/develop/oberon07/Source/AMD64.ob07 b/programs/develop/oberon07/source/AMD64.ob07 similarity index 79% rename from programs/develop/oberon07/Source/AMD64.ob07 rename to programs/develop/oberon07/source/AMD64.ob07 index 899b7e953c..09d171f778 100644 --- a/programs/develop/oberon07/Source/AMD64.ob07 +++ b/programs/develop/oberon07/source/AMD64.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2018-2020, Anton Krotov + Copyright (c) 2018-2021, Anton Krotov All rights reserved. *) @@ -272,11 +272,6 @@ PROCEDURE GetAnyReg (): INTEGER; END GetAnyReg; -PROCEDURE GetVarReg (offs: INTEGER): INTEGER; - RETURN REG.GetVarReg(R, offs) -END GetVarReg; - - PROCEDURE callimp (label: INTEGER); BEGIN OutByte2(0FFH, 15H); (* call qword[rip + label + IMP] *) @@ -301,14 +296,12 @@ VAR label: INTEGER; BEGIN - REG.Store(R); label := IL.codes.rtl[proc]; IF label < 0 THEN callimp(-label) ELSE X86.call(label) - END; - REG.Restore(R) + END END CallRTL; @@ -567,142 +560,6 @@ BEGIN END shiftrc; -PROCEDURE getVar (variables: LISTS.LIST; offset: INTEGER): IL.LOCALVAR; -VAR - cur: IL.LOCALVAR; - -BEGIN - cur := variables.first(IL.LOCALVAR); - WHILE (cur # NIL) & (cur.offset # offset) DO - cur := cur.next(IL.LOCALVAR) - END - - RETURN cur -END getVar; - - -PROCEDURE allocReg (cmd: COMMAND); -VAR - leave: BOOLEAN; - leaf: BOOLEAN; - cur: COMMAND; - variables: LISTS.LIST; - lvar, rvar: IL.LOCALVAR; - reg: INTEGER; - max: INTEGER; - loop: INTEGER; - -BEGIN - loop := 1; - variables := cmd.variables; - leave := FALSE; - leaf := TRUE; - - cur := cmd.next(COMMAND); - REPEAT - CASE cur.opcode OF - |IL.opLLOAD64, - IL.opLLOAD8, - IL.opLLOAD16, - IL.opLLOAD32, - IL.opLLOAD64_PARAM, - IL.opLLOAD32_PARAM, - IL.opLADR_SAVE, - IL.opLADR_INC, - IL.opLADR_DEC, - IL.opLADR_INCB, - IL.opLADR_DECB, - IL.opLADR_INCL, - IL.opLADR_EXCL, - IL.opLADR_UNPK: - lvar := getVar(variables, cur.param2); - IF (lvar # NIL) & (lvar.count # -1) THEN - INC(lvar.count, loop) - END - - |IL.opLADR_SAVEC, - IL.opLADR_INCC, - IL.opLADR_INCCB, - IL.opLADR_DECCB, - IL.opLADR_INCLC, - IL.opLADR_EXCLC: - lvar := getVar(variables, cur.param1); - IF (lvar # NIL) & (lvar.count # -1) THEN - INC(lvar.count, loop) - END - - |IL.opLADR: - lvar := getVar(variables, cur.param2); - IF (lvar # NIL) & (lvar.count # -1) THEN - lvar.count := -1 - END - - |IL.opLOOP: - INC(loop, 10) - - |IL.opENDLOOP: - DEC(loop, 10) - - |IL.opLEAVE, - IL.opLEAVER, - IL.opLEAVEF: - leave := TRUE - - |IL.opCALL, IL.opCALLP, IL.opCALLI, - IL.opWIN64CALL, IL.opWIN64CALLP, IL.opWIN64CALLI, - IL.opSYSVCALL, IL.opSYSVCALLP, IL.opSYSVCALLI, - - IL.opSAVES, IL.opRSET, IL.opRSETR, - IL.opRSETL, IL.opRSET1, - IL.opEQS .. IL.opGES, - IL.opEQSW .. IL.opGESW, - IL.opCOPY, IL.opMOVE, IL.opCOPYA, - IL.opCOPYS, IL.opROT, - IL.opNEW, IL.opDISP, IL.opISREC, - IL.opIS, IL.opTYPEGR, IL.opTYPEGP, - IL.opTYPEGD, IL.opCASET, IL.opDIV, - IL.opDIVL, IL.opMOD, - IL.opMODL, IL.opLENGTH, IL.opLENGTHW: - leaf := FALSE - - |IL.opDIVR, IL.opMODR: - leaf := UTILS.Log2(cur.param2) >= 0 - - ELSE - - END; - cur := cur.next(COMMAND) - UNTIL leave OR ~leaf; - - IF leaf THEN - REPEAT - reg := -1; - max := -1; - rvar := NIL; - lvar := variables.first(IL.LOCALVAR); - WHILE lvar # NIL DO - IF lvar.count > max THEN - max := lvar.count; - rvar := lvar - END; - lvar := lvar.next(IL.LOCALVAR) - END; - - IF rvar # NIL THEN - reg := REG.GetAnyVarReg(R); - IF reg # -1 THEN - REG.Lock(R, reg, rvar.offset, rvar.size); - REG.Load(R, reg); - rvar.count := -1 - END - END - - UNTIL (rvar = NIL) OR (reg = -1) - END - -END allocReg; - - PROCEDURE GetRegA; BEGIN ASSERT(REG.GetReg(R, rax)) @@ -733,7 +590,7 @@ VAR reg: BOOLEAN; BEGIN - ASSERT(r10 IN R.regs); + ASSERT(r11 IN R.regs); n := params MOD 32; params := params DIV 32; s := 0; @@ -772,8 +629,8 @@ BEGIN END; IF ~reg THEN - movrm(r10, rsp, ofs); - movmr(rsp, p, r10); + movrm(r11, rsp, ofs); + movmr(rsp, p, r11); INC(p, 8) END END @@ -828,8 +685,6 @@ VAR float: REAL; - regVar: BOOLEAN; - BEGIN xmm := -1; cmd := commands.first(COMMAND); @@ -846,42 +701,34 @@ BEGIN X86.jmp(param1) |IL.opCALL, IL.opWIN64CALL, IL.opSYSVCALL: - REG.Store(R); CASE opcode OF |IL.opCALL: |IL.opWIN64CALL: Win64Passing(param2) |IL.opSYSVCALL: SysVPassing(param2) END; - X86.call(param1); - REG.Restore(R) + X86.call(param1) |IL.opCALLP, IL.opWIN64CALLP, IL.opSYSVCALLP: UnOp(reg1); IF reg1 # rax THEN - GetRegA; - ASSERT(REG.Exchange(R, reg1, rax)); - drop + mov(rax, reg1) END; drop; - REG.Store(R); CASE opcode OF |IL.opCALLP: |IL.opWIN64CALLP: Win64Passing(param2) |IL.opSYSVCALLP: SysVPassing(param2) END; OutByte2(0FFH, 0D0H); (* call rax *) - REG.Restore(R); ASSERT(R.top = -1) |IL.opCALLI, IL.opWIN64CALLI, IL.opSYSVCALLI: - REG.Store(R); CASE opcode OF |IL.opCALLI: |IL.opWIN64CALLI: Win64Passing(param2) |IL.opSYSVCALLI: SysVPassing(param2) END; - callimp(param1); - REG.Restore(R) + callimp(param1) |IL.opLABEL: X86.SetLabel(param1) @@ -978,9 +825,9 @@ BEGIN param3 := -param3; n := (param3 MOD 32) * 8; param3 := param3 DIV 32; - pop(r10); + pop(r11); subrc(rsp, n); - push(r10); + push(r11); push(rbp); mov(rbp, rsp); @@ -996,8 +843,8 @@ BEGIN movsdmr(rbp, i, b); INC(b) ELSE - movrm(r10, rbp, n + c); - movmr(rbp, i, r10); + movrm(r11, rbp, n + c); + movmr(rbp, i, r11); INC(c, 8) END ELSE @@ -1005,8 +852,8 @@ BEGIN movmr(rbp, i, SystemVRegPar[a]); INC(a) ELSE - movrm(r10, rbp, n + c); - movmr(rbp, i, r10); + movrm(r11, rbp, n + c); + movmr(rbp, i, r11); INC(c, 8) END END; @@ -1028,19 +875,13 @@ BEGIN pushc(0); DEC(n) END - END; - - IF cmd.allocReg THEN - allocReg(cmd) END |IL.opLEAVE, IL.opLEAVER, IL.opLEAVEF: IF opcode = IL.opLEAVER THEN UnOp(reg1); IF reg1 # rax THEN - GetRegA; - ASSERT(REG.Exchange(R, reg1, rax)); - drop + mov(rax, reg1) END; drop END; @@ -1059,11 +900,10 @@ BEGIN pop(rbp); IF param2 > 0 THEN - OutByte3(0C2H, (param2 * 8) MOD 256, (param2 * 8) DIV 256) (* ret param2 *) + OutByte3(0C2H, (param2 * 8) MOD 256, (param2 * 8) DIV 256) (* ret param2*8 *) ELSE X86.ret - END; - REG.Reset(R) + END |IL.opSAVES: UnOp(reg1); @@ -1097,31 +937,16 @@ BEGIN |IL.opLLOAD64: reg1 := GetAnyReg(); - reg2 := GetVarReg(param2); - IF reg2 # -1 THEN - mov(reg1, reg2) - ELSE - movrm(reg1, rbp, param2 * 8) - END + movrm(reg1, rbp, param2 * 8) |IL.opLLOAD8, IL.opLLOAD16: reg1 := GetAnyReg(); - reg2 := GetVarReg(param2); - IF reg2 # -1 THEN - mov(reg1, reg2) - ELSE - movzx(reg1, rbp, param2 * 8, opcode = IL.opLLOAD16) - END + movzx(reg1, rbp, param2 * 8, opcode = IL.opLLOAD16) |IL.opLLOAD32: reg1 := GetAnyReg(); - reg2 := GetVarReg(param2); - IF reg2 # -1 THEN - mov(reg1, reg2) - ELSE - movrm32(reg1, rbp, param2 * 8) - END; + movrm32(reg1, rbp, param2 * 8); shiftrc(shl, reg1, 32); shiftrc(shr, reg1, 32) @@ -1490,8 +1315,8 @@ BEGIN |IL.opNEW: PushAll(1); - n := param2 + 16; - ASSERT(UTILS.Align(n, 64)); + n := param2 + 8; + ASSERT(UTILS.Align(n, 8)); pushc(n); pushc(param1); CallRTL(IL._new) @@ -1502,8 +1327,7 @@ BEGIN |IL.opPUSHT: UnOp(reg1); - reg2 := GetAnyReg(); - movrm(reg2, reg1, -8) + movrm(GetAnyReg(), reg1, -8) |IL.opISREC: PushAll(2); @@ -1540,11 +1364,11 @@ BEGIN GetRegA |IL.opCASET: - push(r10); - push(r10); + push(rcx); + push(rcx); pushc(param2 * tcount); CallRTL(IL._guardrec); - pop(r10); + pop(rcx); test(rax); jcc(jne, param1) @@ -1714,6 +1538,7 @@ BEGIN END END ELSIF isLong(param2) THEN + UnOp(reg1); addrc(reg1, param2) END @@ -1848,7 +1673,7 @@ BEGIN IF param2 = 0 THEN reg2 := rax ELSE - reg2 := r10 + reg2 := rcx END; IF reg1 # reg2 THEN ASSERT(REG.GetReg(R, reg2)); @@ -1874,28 +1699,44 @@ BEGIN |IL.opCASELR: GetRegA; cmprc(rax, param1); - jcc(jl, param2); - jcc(jg, cmd.param3); + IF param2 = cmd.param3 THEN + jcc(jne, param2) + ELSE + jcc(jl, param2); + jcc(jg, cmd.param3) + END; drop |IL.opASR, IL.opROR, IL.opLSL, IL.opLSR: + UnOp(reg1); + IF reg1 # rcx THEN + ASSERT(REG.GetReg(R, rcx)); + ASSERT(REG.Exchange(R, reg1, rcx)); + drop + END; + BinOp(reg1, reg2); - xchg(reg2, rcx); + ASSERT(reg2 = rcx); Rex(reg1, 0); OutByte(0D3H); X86.shift(opcode, reg1 MOD 8); (* shift reg1, cl *) - xchg(reg2, rcx); drop |IL.opASR1, IL.opROR1, IL.opLSL1, IL.opLSR1: + UnOp(reg1); + IF reg1 # rcx THEN + ASSERT(REG.GetReg(R, rcx)); + ASSERT(REG.Exchange(R, reg1, rcx)); + drop + END; + reg1 := GetAnyReg(); movrc(reg1, param2); BinOp(reg1, reg2); - xchg(reg1, rcx); + ASSERT(reg1 = rcx); Rex(reg2, 0); OutByte(0D3H); X86.shift(opcode, reg2 MOD 8); (* shift reg2, cl *) - xchg(reg1, rcx); drop; drop; ASSERT(REG.GetReg(R, reg2)) @@ -2189,17 +2030,12 @@ BEGIN IF opcode = IL.opLADR_UNPK THEN n := param2 * 8; UnOp(reg1); - reg2 := GetVarReg(param2); - regVar := reg2 # -1; - IF ~regVar THEN - reg2 := GetAnyReg(); - Rex(0, reg2); - OutByte2(8DH, 45H + long(n) + (reg2 MOD 8) * 8); (* lea reg2, qword[rbp+n] *) - OutIntByte(n) - END + reg2 := GetAnyReg(); + Rex(0, reg2); + OutByte2(8DH, 45H + long(n) + (reg2 MOD 8) * 8); (* lea reg2, qword[rbp+n] *) + OutIntByte(n) ELSE - BinOp(reg1, reg2); - regVar := FALSE + BinOp(reg1, reg2) END; push(reg1); @@ -2208,12 +2044,7 @@ BEGIN shiftrc(shr, reg1, 53); subrc(reg1, 1023); - IF regVar THEN - mov(reg2, reg1); - reg2 := GetAnyReg() - ELSE - movmr(reg2, 0, reg1) - END; + movmr(reg2, 0, reg1); pop(reg2); movrm(reg1, reg2, 0); @@ -2243,12 +2074,7 @@ BEGIN drop |IL.opLLOAD64_PARAM: - reg1 := GetVarReg(param2); - IF reg1 # -1 THEN - push(reg1) - ELSE - X86.pushm(rbp, param2 * 8) - END + X86.pushm(rbp, param2 * 8) |IL.opGLOAD64_PARAM: OutByte2(0FFH, 35H); (* push qword[rip + param2 + BSS] *) @@ -2272,12 +2098,7 @@ BEGIN |IL.opLLOAD32_PARAM: reg1 := GetAnyReg(); - reg2 := GetVarReg(param2); - IF reg2 # -1 THEN - mov(reg1, reg2) - ELSE - movrm32(reg1, rbp, param2 * 8) - END; + movrm32(reg1, rbp, param2 * 8); shiftrc(shl, reg1, 32); shiftrc(shr, reg1, 32); push(reg1); @@ -2285,20 +2106,15 @@ BEGIN |IL.opLADR_SAVEC: n := param1 * 8; - reg1 := GetVarReg(param1); - IF reg1 # -1 THEN - movrc(reg1, param2) + IF isLong(param2) THEN + reg2 := GetAnyReg(); + movrc(reg2, param2); + movmr(rbp, n, reg2); + drop ELSE - IF isLong(param2) THEN - reg2 := GetAnyReg(); - movrc(reg2, param2); - movmr(rbp, n, reg2); - drop - ELSE - OutByte3(48H, 0C7H, 45H + long(n)); (* mov qword[rbp+n], param2 *) - OutIntByte(n); - OutInt(param2) - END + OutByte3(48H, 0C7H, 45H + long(n)); (* mov qword[rbp+n], param2 *) + OutIntByte(n); + OutInt(param2) END |IL.opGADR_SAVEC: @@ -2319,141 +2135,75 @@ BEGIN |IL.opLADR_SAVE: UnOp(reg1); - reg2 := GetVarReg(param2); - IF reg2 # -1 THEN - mov(reg2, reg1) - ELSE - movmr(rbp, param2 * 8, reg1) - END; + movmr(rbp, param2 * 8, reg1); drop |IL.opLADR_INCC: - reg1 := GetVarReg(param1); IF isLong(param2) THEN reg2 := GetAnyReg(); movrc(reg2, param2); - IF reg1 # -1 THEN - add(reg1, reg2) - ELSE - n := param1 * 8; - Rex(0, reg2); - OutByte2(01H, 45H + long(n) + (reg2 MOD 8) * 8); - OutIntByte(n) (* add qword[rbp+n], reg2 *) - END; + n := param1 * 8; + Rex(0, reg2); + OutByte2(01H, 45H + long(n) + (reg2 MOD 8) * 8); + OutIntByte(n); (* add qword[rbp+n], reg2 *) drop ELSIF ABS(param2) = 1 THEN - IF reg1 # -1 THEN - IF param2 = 1 THEN - incr(reg1) - ELSE - decr(reg1) - END - ELSE - n := param1 * 8; - OutByte3(48H, 0FFH, 45H + 8 * ORD(param2 = -1) + long(n)); (* inc/dec qword[rbp+n] *) - OutIntByte(n) - END + n := param1 * 8; + OutByte3(48H, 0FFH, 45H + 8 * ORD(param2 = -1) + long(n)); (* inc/dec qword[rbp+n] *) + OutIntByte(n) ELSE - IF reg1 # -1 THEN - addrc(reg1, param2) - ELSE - n := param1 * 8; - OutByte3(48H, 81H + short(param2), 45H + long(n)); - OutIntByte(n); - OutIntByte(param2) (* add qword[rbp+n], param2 *) - END + n := param1 * 8; + OutByte3(48H, 81H + short(param2), 45H + long(n)); + OutIntByte(n); + OutIntByte(param2) (* add qword[rbp+n], param2 *) END |IL.opLADR_INCCB, IL.opLADR_DECCB: - reg1 := GetVarReg(param1); param2 := param2 MOD 256; - IF reg1 # -1 THEN - IF opcode = IL.opLADR_DECCB THEN - subrc(reg1, param2) - ELSE - addrc(reg1, param2) - END; - andrc(reg1, 255) - ELSE - n := param1 * 8; - OutByte2(80H, 45H + long(n) + 28H * ORD(opcode = IL.opLADR_DECCB)); - OutIntByte(n); - OutByte(param2) (* add/sub byte[rbp+n], param2 *) - END + n := param1 * 8; + OutByte2(80H, 45H + long(n) + 28H * ORD(opcode = IL.opLADR_DECCB)); + OutIntByte(n); + OutByte(param2) (* add/sub byte[rbp+n], param2 *) |IL.opLADR_INC, IL.opLADR_DEC: UnOp(reg1); - reg2 := GetVarReg(param2); - IF reg2 # -1 THEN - IF opcode = IL.opLADR_DEC THEN - sub(reg2, reg1) - ELSE - add(reg2, reg1) - END - ELSE - n := param2 * 8; - Rex(0, reg1); - OutByte2(01H + 28H * ORD(opcode = IL.opLADR_DEC), 45H + long(n) + (reg1 MOD 8) * 8); - OutIntByte(n) (* add/sub qword[rbp+n], reg1 *) - END; + n := param2 * 8; + Rex(0, reg1); + OutByte2(01H + 28H * ORD(opcode = IL.opLADR_DEC), 45H + long(n) + (reg1 MOD 8) * 8); + OutIntByte(n); (* add/sub qword[rbp+n], reg1 *) drop |IL.opLADR_INCB, IL.opLADR_DECB: UnOp(reg1); - reg2 := GetVarReg(param2); - IF reg2 # -1 THEN - IF opcode = IL.opLADR_DECB THEN - sub(reg2, reg1) - ELSE - add(reg2, reg1) - END; - andrc(reg2, 255) - ELSE - n := param2 * 8; - IF reg1 >= 8 THEN - OutByte(44H) - END; - OutByte2(28H * ORD(opcode = IL.opLADR_DECB), 45H + long(n) + 8 * (reg1 MOD 8)); - OutIntByte(n) (* add/sub byte[rbp+n], reg1_8 *) + n := param2 * 8; + IF reg1 >= 8 THEN + OutByte(44H) END; + OutByte2(28H * ORD(opcode = IL.opLADR_DECB), 45H + long(n) + 8 * (reg1 MOD 8)); + OutIntByte(n); (* add/sub byte[rbp+n], reg1_8 *) drop |IL.opLADR_INCL, IL.opLADR_EXCL: UnOp(reg1); cmprc(reg1, 64); - reg2 := GetVarReg(param2); - IF reg2 # -1 THEN - OutByte2(73H, 4); (* jnb L *) - oprr2(0FH, 0ABH + 8 * ORD(opcode = IL.opLADR_EXCL), reg2, reg1) (* bts/btr reg2, reg1 *) - ELSE - n := param2 * 8; - OutByte2(73H, 5 + 3 * ORD(~X86.isByte(n))); (* jnb L *) - Rex(0, reg1); - OutByte3(0FH, 0ABH + 8 * ORD(opcode = IL.opLADR_EXCL), 45H + long(n) + 8 * (reg1 MOD 8)); - OutIntByte(n) (* bts/btr qword[rbp+n], reg1 *) - END; + n := param2 * 8; + OutByte2(73H, 5 + 3 * ORD(~X86.isByte(n))); (* jnb L *) + Rex(0, reg1); + OutByte3(0FH, 0ABH + 8 * ORD(opcode = IL.opLADR_EXCL), 45H + long(n) + 8 * (reg1 MOD 8)); + OutIntByte(n); (* bts/btr qword[rbp+n], reg1 *) (* L: *) drop |IL.opLADR_INCLC, IL.opLADR_EXCLC: - reg1 := GetVarReg(param1); - IF reg1 # -1 THEN - Rex(reg1, 0); - OutByte3(0FH, 0BAH, 0E8H); (* bts/btr reg1, param2 *) - OutByte2(reg1 MOD 8 + 8 * ORD(opcode = IL.opLADR_EXCLC), param2) - ELSE - n := param1 * 8; - OutByte3(48H, 0FH, 0BAH); (* bts/btr qword[rbp+n], param2 *) - OutByte(6DH + long(n) + 8 * ORD(opcode = IL.opLADR_EXCLC)); - OutIntByte(n); - OutByte(param2) - END + n := param1 * 8; + OutByte3(48H, 0FH, 0BAH); (* bts/btr qword[rbp+n], param2 *) + OutByte(6DH + long(n) + 8 * ORD(opcode = IL.opLADR_EXCLC)); + OutIntByte(n); + OutByte(param2) |IL.opFNAME: fname := cmd(IL.FNAMECMD).fname - |IL.opLOOP, IL.opENDLOOP: - END; cmd := cmd.next(COMMAND) @@ -2600,30 +2350,6 @@ BEGIN END epilog; -PROCEDURE rload (reg, offs, size: INTEGER); -BEGIN - offs := offs * 8; - CASE size OF - |1: movzx(reg, rbp, offs, FALSE) - |2: movzx(reg, rbp, offs, TRUE) - |4: xor(reg, reg); movrm32(reg, rbp, offs) - |8: movrm(reg, rbp, offs) - END -END rload; - - -PROCEDURE rsave (reg, offs, size: INTEGER); -BEGIN - offs := offs * 8; - CASE size OF - |1: X86.movmr8(rbp, offs, reg) - |2: X86.movmr16(rbp, offs, reg) - |4: movmr32(rbp, offs, reg) - |8: movmr(rbp, offs, reg) - END -END rsave; - - PROCEDURE CodeGen* (outname: ARRAY OF CHAR; target: INTEGER; options: PROG.OPTIONS); VAR path, modname, ext: PATHS.PATH; @@ -2647,7 +2373,7 @@ BEGIN PATHS.split(outname, path, modname, ext); S.append(modname, ext); - REG.Init(R, push, pop, mov, xchg, rload, rsave, {rax, r10, r11}, {rcx, rdx, r8, r9}); + REG.Init(R, push, pop, mov, xchg, {rax, rcx, rdx, r8, r9, r10, r11}); IL.set_bss(MAX(IL.codes.bss, MAX(IL.codes.dmin - CHL.Length(IL.codes.data), 8))); diff --git a/programs/develop/oberon07/Source/ARITH.ob07 b/programs/develop/oberon07/source/ARITH.ob07 similarity index 90% rename from programs/develop/oberon07/Source/ARITH.ob07 rename to programs/develop/oberon07/source/ARITH.ob07 index 28b766863b..d572d8b830 100644 --- a/programs/develop/oberon07/Source/ARITH.ob07 +++ b/programs/develop/oberon07/source/ARITH.ob07 @@ -1,13 +1,13 @@ (* BSD 2-Clause License - Copyright (c) 2018-2020, Anton Krotov + Copyright (c) 2018-2021, Anton Krotov All rights reserved. *) MODULE ARITH; -IMPORT AVLTREES, STRINGS, UTILS; +IMPORT STRINGS, UTILS, LISTS; CONST @@ -31,7 +31,7 @@ TYPE set: SET; bool: BOOLEAN; - string*: AVLTREES.DATA + string*: LISTS.ITEM END; @@ -158,7 +158,7 @@ BEGIN n := -1; i := 0; - WHILE (s[i] # "H") & (s[i] # "X") & (error = 0) DO + WHILE (s[i] # "H") & (s[i] # "X") & (s[i] # "h") & (s[i] # "x") & (error = 0) DO d := digit[ORD(s[i])]; IF (n = -1) & (d # 0) THEN @@ -176,13 +176,13 @@ BEGIN value := UTILS.Long(value); - IF (s[i] = "X") & (n # -1) & (i - n > 4) THEN + IF ((s[i] = "X") OR (s[i] = "x")) & (n # -1) & (i - n > 4) THEN error := 3 END; IF error = 0 THEN v.int := value; - IF s[i] = "X" THEN + IF (s[i] = "X") OR (s[i] = "x") THEN v.typ := tCHAR; IF ~check(v) THEN v.typ := tWCHAR; @@ -217,6 +217,7 @@ END opFloat2; PROCEDURE fconv* (s: ARRAY OF CHAR; VAR v: VALUE; VAR error: INTEGER); VAR value: REAL; + frac: REAL; exp10: REAL; i, n, d: INTEGER; minus: BOOLEAN; @@ -224,7 +225,8 @@ VAR BEGIN error := 0; value := 0.0; - exp10 := 10.0; + frac := 0.0; + exp10 := 1.0; minus := FALSE; n := 0; @@ -240,14 +242,19 @@ BEGIN INC(i); WHILE (error = 0) & STRINGS.digit(s[i]) DO - IF opFloat2(value, FLT(digit[ORD(s[i])]) / exp10, "+") & opFloat2(exp10, 10.0, "*") THEN + IF opFloat2(frac, 10.0, "*") & opFloat2(frac, FLT(digit[ORD(s[i])]), "+") THEN + exp10 := exp10 * 10.0; INC(i) ELSE error := 4 END END; - IF s[i] = "E" THEN + IF ~opFloat2(value, frac / exp10, "+") THEN + error := 4 + END; + + IF (s[i] = "E") OR (s[i] = "e") THEN INC(i) END; diff --git a/programs/develop/oberon07/Source/AVLTREES.ob07 b/programs/develop/oberon07/source/AVLTREES.ob07 similarity index 100% rename from programs/develop/oberon07/Source/AVLTREES.ob07 rename to programs/develop/oberon07/source/AVLTREES.ob07 diff --git a/programs/develop/oberon07/Source/BIN.ob07 b/programs/develop/oberon07/source/BIN.ob07 similarity index 100% rename from programs/develop/oberon07/Source/BIN.ob07 rename to programs/develop/oberon07/source/BIN.ob07 diff --git a/programs/develop/oberon07/Source/CHUNKLISTS.ob07 b/programs/develop/oberon07/source/CHUNKLISTS.ob07 similarity index 70% rename from programs/develop/oberon07/Source/CHUNKLISTS.ob07 rename to programs/develop/oberon07/source/CHUNKLISTS.ob07 index 548eaf1651..4137b5a00d 100644 --- a/programs/develop/oberon07/Source/CHUNKLISTS.ob07 +++ b/programs/develop/oberon07/source/CHUNKLISTS.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2018-2020, Anton Krotov + Copyright (c) 2018-2021, Anton Krotov All rights reserved. *) @@ -46,52 +46,36 @@ TYPE PROCEDURE SetByte* (list: BYTELIST; idx: INTEGER; byte: BYTE); VAR - ChunkNum: INTEGER; - chunk: BYTECHUNK; + chunk: BYTECHUNK; + item: LISTS.ITEM; BEGIN ASSERT(idx >= 0); ASSERT(list # NIL); - ChunkNum := idx DIV LENOFBYTECHUNK; - idx := idx MOD LENOFBYTECHUNK; - - chunk := list.first(BYTECHUNK); - - WHILE (chunk # NIL) & (ChunkNum > 0) DO - chunk := chunk.next(BYTECHUNK); - DEC(ChunkNum) - END; - - ASSERT(chunk # NIL); + item := LISTS.getidx(list, idx DIV LENOFBYTECHUNK); + ASSERT(item # NIL); + chunk := item(BYTECHUNK); + idx := idx MOD LENOFBYTECHUNK; ASSERT(idx < chunk.count); - chunk.data[idx] := byte END SetByte; PROCEDURE GetByte* (list: BYTELIST; idx: INTEGER): BYTE; VAR - ChunkNum: INTEGER; - chunk: BYTECHUNK; + chunk: BYTECHUNK; + item: LISTS.ITEM; BEGIN ASSERT(idx >= 0); ASSERT(list # NIL); - ChunkNum := idx DIV LENOFBYTECHUNK; - idx := idx MOD LENOFBYTECHUNK; - - chunk := list.first(BYTECHUNK); - - WHILE (chunk # NIL) & (ChunkNum > 0) DO - chunk := chunk.next(BYTECHUNK); - DEC(ChunkNum) - END; - - ASSERT(chunk # NIL); + item := LISTS.getidx(list, idx DIV LENOFBYTECHUNK); + ASSERT(item # NIL); + chunk := item(BYTECHUNK); + idx := idx MOD LENOFBYTECHUNK; ASSERT(idx < chunk.count) - RETURN chunk.data[idx] END GetByte; @@ -187,52 +171,37 @@ END CreateByteList; PROCEDURE SetInt* (list: INTLIST; idx: INTEGER; int: INTEGER); VAR - ChunkNum: INTEGER; - chunk: INTCHUNK; + chunk: INTCHUNK; + item: LISTS.ITEM; BEGIN ASSERT(idx >= 0); ASSERT(list # NIL); - ChunkNum := idx DIV LENOFINTCHUNK; - idx := idx MOD LENOFINTCHUNK; - - chunk := list.first(INTCHUNK); - - WHILE (chunk # NIL) & (ChunkNum > 0) DO - chunk := chunk.next(INTCHUNK); - DEC(ChunkNum) - END; - - ASSERT(chunk # NIL); + item := LISTS.getidx(list, idx DIV LENOFINTCHUNK); + ASSERT(item # NIL); + chunk := item(INTCHUNK); + idx := idx MOD LENOFINTCHUNK; ASSERT(idx < chunk.count); - chunk.data[idx] := int END SetInt; PROCEDURE GetInt* (list: INTLIST; idx: INTEGER): INTEGER; + VAR - ChunkNum: INTEGER; - chunk: INTCHUNK; + chunk: INTCHUNK; + item: LISTS.ITEM; BEGIN ASSERT(idx >= 0); ASSERT(list # NIL); - ChunkNum := idx DIV LENOFINTCHUNK; - idx := idx MOD LENOFINTCHUNK; - - chunk := list.first(INTCHUNK); - - WHILE (chunk # NIL) & (ChunkNum > 0) DO - chunk := chunk.next(INTCHUNK); - DEC(ChunkNum) - END; - - ASSERT(chunk # NIL); + item := LISTS.getidx(list, idx DIV LENOFINTCHUNK); + ASSERT(item # NIL); + chunk := item(INTCHUNK); + idx := idx MOD LENOFINTCHUNK; ASSERT(idx < chunk.count) - RETURN chunk.data[idx] END GetInt; diff --git a/programs/develop/oberon07/Source/COLLECTIONS.ob07 b/programs/develop/oberon07/source/COLLECTIONS.ob07 similarity index 100% rename from programs/develop/oberon07/Source/COLLECTIONS.ob07 rename to programs/develop/oberon07/source/COLLECTIONS.ob07 diff --git a/programs/develop/oberon07/Source/CONSOLE.ob07 b/programs/develop/oberon07/source/CONSOLE.ob07 similarity index 77% rename from programs/develop/oberon07/Source/CONSOLE.ob07 rename to programs/develop/oberon07/source/CONSOLE.ob07 index b5916839c7..f5091cca35 100644 --- a/programs/develop/oberon07/Source/CONSOLE.ob07 +++ b/programs/develop/oberon07/source/CONSOLE.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2018-2019, Anton Krotov + Copyright (c) 2018-2021, Anton Krotov All rights reserved. *) @@ -33,16 +33,6 @@ BEGIN END Int; -PROCEDURE Hex* (x, n: INTEGER); -VAR - s: ARRAY 24 OF CHAR; - -BEGIN - STRINGS.IntToHex(x, s, n); - String(s) -END Hex; - - PROCEDURE Int2* (x: INTEGER); BEGIN IF x < 10 THEN @@ -79,4 +69,10 @@ BEGIN END Int2Ln; +PROCEDURE Dashes*; +BEGIN + StringLn("------------------------------------------------") +END Dashes; + + END CONSOLE. \ No newline at end of file diff --git a/programs/develop/oberon07/Source/Compiler.ob07 b/programs/develop/oberon07/source/Compiler.ob07 similarity index 82% rename from programs/develop/oberon07/Source/Compiler.ob07 rename to programs/develop/oberon07/source/Compiler.ob07 index 664c03f9ae..0a30e6123d 100644 --- a/programs/develop/oberon07/Source/Compiler.ob07 +++ b/programs/develop/oberon07/source/Compiler.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2018-2020, Anton Krotov + Copyright (c) 2018-2021, Anton Krotov All rights reserved. *) @@ -11,6 +11,15 @@ IMPORT ST := STATEMENTS, PARS, UTILS, PATHS, PROG, C := CONSOLE, ERRORS, STRINGS, WRITER, MSP430, THUMB, TARGETS, SCAN; +CONST + + DEF_WINDOWS = "WINDOWS"; + DEF_LINUX = "LINUX"; + DEF_KOLIBRIOS = "KOLIBRIOS"; + DEF_CPU_X86 = "CPU_X86"; + DEF_CPU_X8664 = "CPU_X8664"; + + PROCEDURE keys (VAR options: PROG.OPTIONS; VAR out: PARS.PATH); VAR param: PARS.PATH; @@ -94,6 +103,8 @@ BEGIN EXCL(checking, ST.chkCHR); EXCL(checking, ST.chkWCHR); EXCL(checking, ST.chkBYTE) + ELSIF param[j] = "s" THEN + EXCL(checking, ST.chkSTK) ELSIF param[j] = "a" THEN checking := {} END; @@ -177,14 +188,23 @@ BEGIN options.checking := ST.chkALL; PATHS.GetCurrentDirectory(app_path); - lib_path := app_path; + + UTILS.GetArg(0, temp); + PATHS.split(temp, path, modname, ext); + IF PATHS.isRelative(path) THEN + PATHS.RelPath(app_path, path, temp); + path := temp + END; + lib_path := path; UTILS.GetArg(1, inname); + STRINGS.replace(inname, "\", UTILS.slash); + STRINGS.replace(inname, "/", UTILS.slash); C.Ln; C.String("Akron Oberon Compiler v"); C.Int(UTILS.vMajor); C.String("."); C.Int2(UTILS.vMinor); - C.String(" ("); C.Int(UTILS.bit_depth); C.StringLn("-bit)"); - C.StringLn("Copyright (c) 2018-2020, Anton Krotov"); + C.String(" ("); C.Int(UTILS.bit_depth); C.StringLn("-bit) " + UTILS.Date); + C.StringLn("Copyright (c) 2018-2021, Anton Krotov"); IF inname = "" THEN C.Ln; @@ -220,7 +240,7 @@ BEGIN UTILS.Exit(0) END; - C.StringLn("--------------------------------------------"); + C.Dashes; PATHS.split(inname, path, modname, ext); IF ext # UTILS.FILE_EXT THEN @@ -245,14 +265,14 @@ BEGIN ERRORS.Error(206) END; - IF target = TARGETS.MSP430 THEN + IF TARGETS.CPU = TARGETS.cpuMSP430 THEN options.ram := MSP430.minRAM; options.rom := MSP430.minROM END; - IF target = TARGETS.STM32CM3 THEN - options.ram := THUMB.STM32_minRAM; - options.rom := THUMB.STM32_minROM + IF (TARGETS.CPU = TARGETS.cpuTHUMB) & (TARGETS.OS = TARGETS.osNONE) THEN + options.ram := THUMB.minRAM; + options.rom := THUMB.minROM END; IF UTILS.bit_depth < TARGETS.BitDepth THEN @@ -278,10 +298,28 @@ BEGIN PARS.init(options); + CASE TARGETS.OS OF + |TARGETS.osNONE: + |TARGETS.osWIN32, + TARGETS.osWIN64: SCAN.NewDef(DEF_WINDOWS) + |TARGETS.osLINUX32, + TARGETS.osLINUX64: SCAN.NewDef(DEF_LINUX) + |TARGETS.osKOS: SCAN.NewDef(DEF_KOLIBRIOS) + END; + + CASE TARGETS.CPU OF + |TARGETS.cpuX86: SCAN.NewDef(DEF_CPU_X86) + |TARGETS.cpuAMD64: SCAN.NewDef(DEF_CPU_X8664) + |TARGETS.cpuMSP430: + |TARGETS.cpuTHUMB: + |TARGETS.cpuRVM32I: + |TARGETS.cpuRVM64I: + END; + ST.compile(path, lib_path, modname, outname, target, options); time := UTILS.GetTickCount() - UTILS.time; - C.StringLn("--------------------------------------------"); + C.Dashes; C.Int(PARS.lines); C.String(" lines, "); C.Int(time DIV 100); C.String("."); C.Int2(time MOD 100); C.String(" sec, "); C.Int(WRITER.counter); C.StringLn(" bytes"); diff --git a/programs/develop/oberon07/Source/ELF.ob07 b/programs/develop/oberon07/source/ELF.ob07 similarity index 91% rename from programs/develop/oberon07/Source/ELF.ob07 rename to programs/develop/oberon07/source/ELF.ob07 index 87c688ec65..b62c6d0a17 100644 --- a/programs/develop/oberon07/Source/ELF.ob07 +++ b/programs/develop/oberon07/source/ELF.ob07 @@ -1,13 +1,13 @@ (* BSD 2-Clause License - Copyright (c) 2019-2020, Anton Krotov + Copyright (c) 2019-2021, Anton Krotov All rights reserved. *) MODULE ELF; -IMPORT BIN, WR := WRITER, CHL := CHUNKLISTS, LISTS, PE32, UTILS; +IMPORT BIN, WR := WRITER, CHL := CHUNKLISTS, LISTS, PE32, UTILS, STRINGS; CONST @@ -155,25 +155,6 @@ BEGIN END NewSym; -PROCEDURE HashStr (name: ARRAY OF CHAR): INTEGER; -VAR - i, h: INTEGER; - g: SET; - -BEGIN - h := 0; - i := 0; - WHILE name[i] # 0X DO - h := h * 16 + ORD(name[i]); - g := BITS(h) * {28..31}; - h := ORD(BITS(h) / BITS(LSR(ORD(g), 24)) - g); - INC(i) - END - - RETURN h -END HashStr; - - PROCEDURE MakeHash (bucket, chain: CHL.INTLIST; symCount: INTEGER); VAR symi, hi, k: INTEGER; @@ -329,18 +310,18 @@ BEGIN hashtab := CHL.CreateIntList(); - CHL.PushInt(hashtab, HashStr("")); + CHL.PushInt(hashtab, STRINGS.HashStr("")); NewSym(CHL.PushStr(strtab, ""), 0, 0, 0X, 0X, 0X); - CHL.PushInt(hashtab, HashStr("dlopen")); + CHL.PushInt(hashtab, STRINGS.HashStr("dlopen")); NewSym(CHL.PushStr(strtab, "dlopen"), 0, 0, 12X, 0X, 0X); - CHL.PushInt(hashtab, HashStr("dlsym")); + CHL.PushInt(hashtab, STRINGS.HashStr("dlsym")); NewSym(CHL.PushStr(strtab, "dlsym"), 0, 0, 12X, 0X, 0X); IF so THEN item := program.exp_list.first; WHILE item # NIL DO ASSERT(CHL.GetStr(program.export, item(BIN.EXPRT).nameoffs, Name)); - CHL.PushInt(hashtab, HashStr(Name)); + CHL.PushInt(hashtab, STRINGS.HashStr(Name)); NewSym(CHL.PushStr(strtab, Name), item(BIN.EXPRT).label, 0, 12X, 0X, 0X); item := item.next END; @@ -575,7 +556,7 @@ BEGIN WR.Write32LE(00000201H) END; - + WR.Write32LE(symCount); WR.Write32LE(symCount); @@ -588,14 +569,14 @@ BEGIN END; CHL.WriteToFile(strtab); - + IF amd64 THEN WR.Write64LE(0); WR.Write64LE(0) ELSE WR.Write32LE(0); - WR.Write32LE(0) - END; + WR.Write32LE(0) + END; CHL.WriteToFile(program.code); WHILE pad > 0 DO diff --git a/programs/develop/oberon07/Source/ERRORS.ob07 b/programs/develop/oberon07/source/ERRORS.ob07 similarity index 95% rename from programs/develop/oberon07/Source/ERRORS.ob07 rename to programs/develop/oberon07/source/ERRORS.ob07 index 872b2ef297..c9056bdb2b 100644 --- a/programs/develop/oberon07/Source/ERRORS.ob07 +++ b/programs/develop/oberon07/source/ERRORS.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2018-2020, Anton Krotov + Copyright (c) 2018-2021, Anton Krotov All rights reserved. *) @@ -25,6 +25,7 @@ BEGIN CASE warning OF |0: C.StringLn("passing a string value as a fixed array") |1: C.StringLn("endless FOR loop") + |2: C.StringLn("identifier too long") END END WarningMsg; @@ -43,7 +44,7 @@ BEGIN | 3: str := "unclosed string" | 4: str := "illegal character" | 5: str := "string too long" - | 6: str := "identifier too long" + | 7: str := "number too long" | 8..12: str := "number too large" | 13: str := "real numbers not supported" diff --git a/programs/develop/oberon07/Source/FILES.ob07 b/programs/develop/oberon07/source/FILES.ob07 similarity index 87% rename from programs/develop/oberon07/Source/FILES.ob07 rename to programs/develop/oberon07/source/FILES.ob07 index 07c906bc05..d1bbde9cbf 100644 --- a/programs/develop/oberon07/Source/FILES.ob07 +++ b/programs/develop/oberon07/source/FILES.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2018-2020, Anton Krotov + Copyright (c) 2018-2021, Anton Krotov All rights reserved. *) @@ -154,27 +154,24 @@ END read; PROCEDURE write* (file: FILE; chunk: ARRAY OF BYTE; bytes: INTEGER): INTEGER; VAR - free, n, k, res, idx: INTEGER; + free, n, idx: INTEGER; BEGIN idx := 0; - res := 0; IF (file # NIL) & (file.count >= 0) THEN free := LEN(file.buffer) - file.count; WHILE bytes > 0 DO n := MIN(free, bytes); copy(chunk, idx, file.buffer, file.count, n); - INC(res, n); DEC(free, n); DEC(bytes, n); INC(idx, n); INC(file.count, n); IF free = 0 THEN - k := flush(file); - IF k # LEN(file.buffer) THEN + IF flush(file) # LEN(file.buffer) THEN bytes := 0; - DEC(res, n) + DEC(idx, n) ELSE file.count := 0; free := LEN(file.buffer) @@ -184,7 +181,7 @@ BEGIN END - RETURN res + RETURN idx END write; diff --git a/programs/develop/oberon07/Source/HEX.ob07 b/programs/develop/oberon07/source/HEX.ob07 similarity index 100% rename from programs/develop/oberon07/Source/HEX.ob07 rename to programs/develop/oberon07/source/HEX.ob07 diff --git a/programs/develop/oberon07/Source/IL.ob07 b/programs/develop/oberon07/source/IL.ob07 similarity index 91% rename from programs/develop/oberon07/Source/IL.ob07 rename to programs/develop/oberon07/source/IL.ob07 index cd1cd43bf3..e7033b37b9 100644 --- a/programs/develop/oberon07/Source/IL.ob07 +++ b/programs/develop/oberon07/source/IL.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2018-2020, Anton Krotov + Copyright (c) 2018-2021, Anton Krotov All rights reserved. *) @@ -16,6 +16,8 @@ CONST call_win64* = 1; call_sysv* = 2; + begin_loop* = 1; end_loop* = 2; + opJMP* = 0; opLABEL* = 1; opCOPYS* = 2; opGADR* = 3; opCONST* = 4; opLLOAD32* = 5; opCOPYA* = 6; opCASET* = 7; opMULC* = 8; opMUL* = 9; opDIV* = 10; opMOD* = 11; opDIVL* = 12; opMODL* = 13; opDIVR* = 14; opMODR* = 15; opUMINUS* = 16; @@ -44,7 +46,7 @@ CONST opCASEL* = 83; opCASER* = 84; opCASELR* = 85; opPOPSP* = 86; - opWIN64CALL* = 87; opWIN64CALLI* = 88; opWIN64CALLP* = 89; opLOOP* = 90; opENDLOOP* = 91; + opWIN64CALL* = 87; opWIN64CALLI* = 88; opWIN64CALLP* = 89; opAND* = 90; opOR* = 91; opLOAD8* = 92; opLOAD16* = 93; opLOAD32* = 94; opPRECALL* = 95; opRES* = 96; opRESF* = 97; opPUSHC* = 98; opSWITCH* = 99; @@ -79,7 +81,6 @@ CONST opSAVE16C* = 213; opWCHR* = 214; opHANDLER* = 215; opSYSVCALL* = 216; opSYSVCALLI* = 217; opSYSVCALLP* = 218; opFNAME* = 219; - opAND* = 220; opOR* = 221; opSADR_PARAM* = -1; opLOAD64_PARAM* = -2; opLLOAD64_PARAM* = -3; opGLOAD64_PARAM* = -4; @@ -132,21 +133,13 @@ CONST TYPE - LOCALVAR* = POINTER TO RECORD (LISTS.ITEM) - - offset*, size*, count*: INTEGER - - END; - COMMAND* = POINTER TO RECORD (LISTS.ITEM) opcode*: INTEGER; param1*: INTEGER; param2*: INTEGER; param3*: INTEGER; - float*: REAL; - variables*: LISTS.LIST; - allocReg*: BOOLEAN + float*: REAL END; @@ -166,13 +159,13 @@ TYPE EXPORT_PROC* = POINTER TO RECORD (LISTS.ITEM) label*: INTEGER; - name*: SCAN.LEXSTR + name*: SCAN.IDSTR END; IMPORT_LIB* = POINTER TO RECORD (LISTS.ITEM) - name*: SCAN.LEXSTR; + name*: SCAN.TEXTSTR; procs*: LISTS.LIST END; @@ -181,7 +174,7 @@ TYPE label*: INTEGER; lib*: IMPORT_LIB; - name*: SCAN.LEXSTR; + name*: SCAN.TEXTSTR; count: INTEGER END; @@ -215,7 +208,7 @@ VAR codes*: CODES; CPU: INTEGER; - commands, variables: C.COLLECTION; + commands: C.COLLECTION; PROCEDURE set_dmin* (value: INTEGER); @@ -247,33 +240,12 @@ BEGIN NEW(cmd) ELSE cmd := citem(COMMAND) - END; - - cmd.allocReg := FALSE + END RETURN cmd END NewCmd; -PROCEDURE NewVar* (): LOCALVAR; -VAR - lvar: LOCALVAR; - citem: C.ITEM; - -BEGIN - citem := C.pop(variables); - IF citem = NIL THEN - NEW(lvar) - ELSE - lvar := citem(LOCALVAR) - END; - - lvar.count := 0 - - RETURN lvar -END NewVar; - - PROCEDURE setlast* (cmd: COMMAND); BEGIN codes.last := cmd @@ -493,14 +465,32 @@ BEGIN set(cur, opGADR_SAVEC, param2) ELSIF (nov.opcode = opMULC) & (old_opcode = opMULC) THEN - cur.param2 := param2 * cur.param2 + cur.param2 := cur.param2 * param2 ELSIF (nov.opcode = opADDC) & (old_opcode = opADDC) THEN - cur.param2 := param2 + cur.param2 + INC(cur.param2, param2) ELSE old_opcode := -1 END + + ELSIF CPU IN {TARGETS.cpuTHUMB, TARGETS.cpuRVM32I, TARGETS.cpuRVM64I} THEN + + old_opcode := cur.opcode; + param2 := nov.param2; + + IF (old_opcode = opLADR) & (nov.opcode = opSAVE) THEN + cur.opcode := opLADR_SAVE + ELSIF (old_opcode = opLADR) & (nov.opcode = opINCC) THEN + set(cur, opLADR_INCC, param2) + ELSIF (nov.opcode = opMULC) & (old_opcode = opMULC) THEN + cur.param2 := cur.param2 * param2 + ELSIF (nov.opcode = opADDC) & (old_opcode = opADDC) THEN + INC(cur.param2, param2) + ELSE + old_opcode := -1 + END + ELSE old_opcode := -1 END; @@ -583,23 +573,8 @@ BEGIN END AddCmd0; -PROCEDURE deleteVarList (list: LISTS.LIST); -VAR - last: LISTS.ITEM; - -BEGIN - WHILE list.last # NIL DO - last := LISTS.pop(list); - C.push(variables, last) - END -END deleteVarList; - - PROCEDURE delete (cmd: COMMAND); BEGIN - IF cmd.variables # NIL THEN - deleteVarList(cmd.variables) - END; LISTS.delete(codes.commands, cmd); C.push(commands, cmd) END delete; @@ -626,7 +601,7 @@ BEGIN END delete2; -PROCEDURE AddJmpCmd* (opcode: INTEGER; label: INTEGER); +PROCEDURE Jmp* (opcode: INTEGER; label: INTEGER); VAR prev: COMMAND; not: BOOLEAN; @@ -649,7 +624,7 @@ BEGIN IF not THEN delete(prev) END -END AddJmpCmd; +END Jmp; PROCEDURE AndOrOpt* (VAR label: INTEGER); @@ -706,16 +681,16 @@ BEGIN END; IF jz THEN - AddJmpCmd(opJZ, label) + Jmp(opJZ, label) ELSE - AddJmpCmd(opJNZ, label) + Jmp(opJNZ, label) END; IF op = opOR THEN SetLabel(l) END ELSE - AddJmpCmd(opJZ, label) + Jmp(opJZ, label) END; setlast(codes.last) @@ -734,7 +709,7 @@ VAR BEGIN AddCmd(op, t); label := NewLabel(); - AddJmpCmd(opJNZ, label); + Jmp(opJNZ, label); OnError(line, error); SetLabel(label) END TypeGuard; @@ -789,7 +764,6 @@ BEGIN cmd.opcode := opENTER; cmd.param1 := label; cmd.param3 := params; - cmd.allocReg := TRUE; insert(codes.last, cmd) RETURN codes.last @@ -829,9 +803,9 @@ END LeaveC; PROCEDURE Call* (proc, callconv, fparams: INTEGER); BEGIN CASE callconv OF - |call_stack: AddJmpCmd(opCALL, proc) - |call_win64: AddJmpCmd(opWIN64CALL, proc) - |call_sysv: AddJmpCmd(opSYSVCALL, proc) + |call_stack: Jmp(opCALL, proc) + |call_win64: Jmp(opWIN64CALL, proc) + |call_sysv: Jmp(opSYSVCALL, proc) END; codes.last(COMMAND).param2 := fparams END Call; @@ -840,9 +814,9 @@ END Call; PROCEDURE CallImp* (proc: LISTS.ITEM; callconv, fparams: INTEGER); BEGIN CASE callconv OF - |call_stack: AddJmpCmd(opCALLI, proc(IMPORT_PROC).label) - |call_win64: AddJmpCmd(opWIN64CALLI, proc(IMPORT_PROC).label) - |call_sysv: AddJmpCmd(opSYSVCALLI, proc(IMPORT_PROC).label) + |call_stack: Jmp(opCALLI, proc(IMPORT_PROC).label) + |call_win64: Jmp(opWIN64CALLI, proc(IMPORT_PROC).label) + |call_sysv: Jmp(opSYSVCALLI, proc(IMPORT_PROC).label) END; codes.last(COMMAND).param2 := fparams END CallImp; @@ -860,34 +834,34 @@ END CallP; PROCEDURE AssignProc* (proc: INTEGER); BEGIN - AddJmpCmd(opSAVEP, proc) + Jmp(opSAVEP, proc) END AssignProc; PROCEDURE AssignImpProc* (proc: LISTS.ITEM); BEGIN - AddJmpCmd(opSAVEIP, proc(IMPORT_PROC).label) + Jmp(opSAVEIP, proc(IMPORT_PROC).label) END AssignImpProc; PROCEDURE PushProc* (proc: INTEGER); BEGIN - AddJmpCmd(opPUSHP, proc) + Jmp(opPUSHP, proc) END PushProc; PROCEDURE PushImpProc* (proc: LISTS.ITEM); BEGIN - AddJmpCmd(opPUSHIP, proc(IMPORT_PROC).label) + Jmp(opPUSHIP, proc(IMPORT_PROC).label) END PushImpProc; PROCEDURE ProcCmp* (proc: INTEGER; eq: BOOLEAN); BEGIN IF eq THEN - AddJmpCmd(opEQP, proc) + Jmp(opEQP, proc) ELSE - AddJmpCmd(opNEP, proc) + Jmp(opNEP, proc) END END ProcCmp; @@ -895,9 +869,9 @@ END ProcCmp; PROCEDURE ProcImpCmp* (proc: LISTS.ITEM; eq: BOOLEAN); BEGIN IF eq THEN - AddJmpCmd(opEQIP, proc(IMPORT_PROC).label) + Jmp(opEQIP, proc(IMPORT_PROC).label) ELSE - AddJmpCmd(opNEIP, proc(IMPORT_PROC).label) + Jmp(opNEIP, proc(IMPORT_PROC).label) END END ProcImpCmp; @@ -1089,7 +1063,7 @@ BEGIN END fname; -PROCEDURE AddExp* (label: INTEGER; name: SCAN.LEXSTR); +PROCEDURE AddExp* (label: INTEGER; name: SCAN.IDSTR); VAR exp: EXPORT_PROC; @@ -1101,7 +1075,7 @@ BEGIN END AddExp; -PROCEDURE AddImp* (dll, proc: SCAN.LEXSTR): IMPORT_PROC; +PROCEDURE AddImp* (dll, proc: SCAN.TEXTSTR): IMPORT_PROC; VAR lib: IMPORT_LIB; p: IMPORT_PROC; @@ -1162,7 +1136,6 @@ VAR BEGIN commands := C.create(); - variables := C.create(); CPU := pCPU; diff --git a/programs/develop/oberon07/Source/KOS.ob07 b/programs/develop/oberon07/source/KOS.ob07 similarity index 100% rename from programs/develop/oberon07/Source/KOS.ob07 rename to programs/develop/oberon07/source/KOS.ob07 diff --git a/programs/develop/oberon07/Source/LISTS.ob07 b/programs/develop/oberon07/source/LISTS.ob07 similarity index 81% rename from programs/develop/oberon07/Source/LISTS.ob07 rename to programs/develop/oberon07/source/LISTS.ob07 index 4cb60d21e0..f57e3fd6f2 100644 --- a/programs/develop/oberon07/Source/LISTS.ob07 +++ b/programs/develop/oberon07/source/LISTS.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2018-2020, Anton Krotov + Copyright (c) 2018-2021, Anton Krotov All rights reserved. *) @@ -126,20 +126,23 @@ BEGIN prev := item.prev; next := item.next; - IF (next # NIL) & (prev # NIL) THEN - prev.next := next; - next.prev := prev - ELSIF (next = NIL) & (prev = NIL) THEN - list.first := NIL; - list.last := NIL - ELSIF (next = NIL) & (prev # NIL) THEN - prev.next := NIL; - list.last := prev - ELSIF (next # NIL) & (prev = NIL) THEN - next.prev := NIL; - list.first := next + IF next # NIL THEN + IF prev # NIL THEN + prev.next := next; + next.prev := prev + ELSE + next.prev := NIL; + list.first := next + END + ELSE + IF prev # NIL THEN + prev.next := NIL; + list.last := prev + ELSE + list.first := NIL; + list.last := NIL + END END - END delete; diff --git a/programs/develop/oberon07/Source/MSCOFF.ob07 b/programs/develop/oberon07/source/MSCOFF.ob07 similarity index 100% rename from programs/develop/oberon07/Source/MSCOFF.ob07 rename to programs/develop/oberon07/source/MSCOFF.ob07 diff --git a/programs/develop/oberon07/Source/MSP430.ob07 b/programs/develop/oberon07/source/MSP430.ob07 similarity index 90% rename from programs/develop/oberon07/Source/MSP430.ob07 rename to programs/develop/oberon07/source/MSP430.ob07 index 8a37320bf2..9df92b6196 100644 --- a/programs/develop/oberon07/Source/MSP430.ob07 +++ b/programs/develop/oberon07/source/MSP430.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2019-2020, Anton Krotov + Copyright (c) 2019-2021, Anton Krotov All rights reserved. *) @@ -13,10 +13,12 @@ IMPORT IL, LISTS, REG, CHL := CHUNKLISTS, ERRORS, WR := WRITER, HEX, CONST + chkSTK* = 6; + minRAM* = 128; maxRAM* = 2048; minROM* = 2048; maxROM* = 24576; - minStackSize = 64; + StkReserve = RTL.StkReserve; IntVectorSize* = RTL.IntVectorSize; @@ -24,7 +26,7 @@ CONST R4 = 4; R5 = 5; R6 = 6; R7 = 7; - HP = 14; IR = 15; + HP = RTL.HP; ACC = R4; @@ -108,7 +110,12 @@ VAR IdxWords: RECORD src, dst: INTEGER END; - StkCnt: INTEGER; + StkCnt, MaxStkCnt: INTEGER; + + +PROCEDURE CheckProcDataSize* (VarSize, RamSize: INTEGER): BOOLEAN; + RETURN (VarSize + 1) * 2 + StkReserve + RTL.VarSize < RamSize +END CheckProcDataSize; PROCEDURE EmitLabel (L: INTEGER); @@ -163,6 +170,13 @@ BEGIN END EmitCall; +PROCEDURE IncStk; +BEGIN + INC(StkCnt); + MaxStkCnt := MAX(StkCnt, MaxStkCnt) +END IncStk; + + PROCEDURE bw (b: BOOLEAN): INTEGER; RETURN BW * ORD(b) END bw; @@ -266,7 +280,7 @@ BEGIN Op1(opPUSH, PC, sINCR); EmitWord(imm) END; - INC(StkCnt) + IncStk END PushImm; @@ -389,7 +403,7 @@ END Fixup; PROCEDURE Push (reg: INTEGER); BEGIN Op1(opPUSH, reg, sREG); - INC(StkCnt) + IncStk END Push; @@ -440,6 +454,8 @@ END Reloc; PROCEDURE CallRTL (proc, params: INTEGER); BEGIN + IncStk; + DEC(StkCnt); EmitCall(RTL.rtl[proc].label); RTL.Used(proc); IF params > 0 THEN @@ -611,7 +627,7 @@ PROCEDURE LocalSrc (offset: INTEGER): INTEGER; END LocalSrc; -PROCEDURE translate; +PROCEDURE translate (chk_stk: BOOLEAN); VAR cmd, next: COMMAND; @@ -621,6 +637,8 @@ VAR cc: INTEGER; + word: WORD; + BEGIN cmd := IL.codes.commands.first(COMMAND); @@ -636,9 +654,13 @@ BEGIN EmitJmp(opJMP, param1) |IL.opCALL: + IncStk; + DEC(StkCnt); EmitCall(param1) |IL.opCALLP: + IncStk; + DEC(StkCnt); UnOp(reg1); Op1(opCALL, reg1, sREG); drop; @@ -652,7 +674,7 @@ BEGIN |IL.opSADR_PARAM: Op1(opPUSH, PC, sINCR); - INC(StkCnt); + IncStk; EmitWord(param2); Reloc(RDATA) @@ -663,8 +685,10 @@ BEGIN PushImm(param2) |IL.opONERR: - PushImm(param2); DEC(StkCnt); + EmitWord(0C232H); (* BIC #8, SR; DINT *) + EmitWord(4303H); (* MOV R3, R3; NOP *) + PushImm(param2); EmitJmp(opJMP, param1) |IL.opLEAVEC: @@ -672,8 +696,25 @@ BEGIN |IL.opENTER: ASSERT(R.top = -1); - StkCnt := 0; EmitLabel(param1); + n := param2 MOD 65536; + param2 := param2 DIV 65536; + StkCnt := 0; + IF chk_stk THEN + L := NewLabel(); + Op2(opMOV, SP * 256, R4); + Op2(opSUB, HP * 256, R4); + Op2(opCMP, imm(StkReserve), R4); + word := CodeList.last(WORD); + jcc(jge, L); + DEC(StkCnt); + EmitWord(0C232H); (* BIC #8, SR; DINT *) + EmitWord(4303H); (* MOV R3, R3; NOP *) + PushImm(n); + EmitJmp(opJMP, cmd.param3); + EmitLabel(L) + END; + IF param2 > 8 THEN Op2(opMOV, imm(param2), R4); L := NewLabel(); @@ -681,26 +722,28 @@ BEGIN Push(CG); Op2(opSUB, imm(1), R4); jcc(jne, L) - ELSIF param2 > 0 THEN - WHILE param2 > 0 DO - Push(CG); - DEC(param2) + ELSE + FOR n := 1 TO param2 DO + Push(CG) END - END + END; + StkCnt := param2; + MaxStkCnt := StkCnt |IL.opLEAVE, IL.opLEAVER: ASSERT(param2 = 0); IF opcode = IL.opLEAVER THEN UnOp(reg1); IF reg1 # ACC THEN - GetRegA; - ASSERT(REG.Exchange(R, reg1, ACC)); - drop + mov(ACC, reg1) END; drop END; ASSERT(R.top = -1); ASSERT(StkCnt = param1); + IF chk_stk THEN + INC(word.val, MaxStkCnt * 2) + END; IF param1 > 0 THEN Op2(opADD, imm(param1 * 2), SP) END; @@ -930,9 +973,6 @@ BEGIN Test(reg1); setcc(jne, reg1) - |IL.opLOOP: - |IL.opENDLOOP: - |IL.opGET: BinOp(reg1, reg2); drop; @@ -1036,7 +1076,7 @@ BEGIN UnOp(reg1); PushAll(0); Op1(opPUSH, reg1, sIDX); - INC(StkCnt); + IncStk; EmitWord(-2); PushImm(param2); CallRTL(RTL._guardrec, 2); @@ -1144,8 +1184,12 @@ BEGIN |IL.opCASELR: Op2(opCMP, imm(param1), ACC); - jcc(jl, param2); - jcc(jg, cmd.param3) + IF param2 = cmd.param3 THEN + jcc(jne, param2) + ELSE + jcc(jl, param2); + jcc(jg, cmd.param3) + END |IL.opSBOOL: BinOp(reg2, reg1); @@ -1351,7 +1395,7 @@ BEGIN UnOp(reg1); PushAll_1; Op1(opPUSH, PC, sINCR); - INC(StkCnt); + IncStk; EmitWord(param2); Reloc(RDATA); Push(reg1); @@ -1534,12 +1578,12 @@ BEGIN END translate; -PROCEDURE prolog (ramSize: INTEGER); +PROCEDURE prolog; VAR i: INTEGER; BEGIN - RTL.Init(EmitLabel, EmitWord, EmitCall, ramSize); + RTL.Init(EmitLabel, EmitWord, EmitCall); FOR i := 0 TO LEN(RTL.rtl) - 1 DO RTL.Set(i, NewLabel()) END; @@ -1551,14 +1595,14 @@ BEGIN Op2(opMOV, incr(PC), HP); EmitWord(0); Op2(opMOV, imm(5A80H), dst_x(0120H, SR)); (* stop WDT *) - Op2(opMOV, imm(RTL.empty_proc), dst_x(RTL.int, SR)); - Op2(opMOV, imm(0), dst_x(RTL.trap, SR)) + Op2(opMOV, imm(RTL.empty_proc), dst_x(0, SP)); + Op2(opMOV, imm(RTL.empty_proc), dst_x(2, SP)); END prolog; PROCEDURE epilog; VAR - L1, i: INTEGER; + L1, i, n: INTEGER; BEGIN Op2(opBIS, imm(10H), SR); (* CPUOFF *) @@ -1575,22 +1619,24 @@ BEGIN EmitLabel(L1); - MovRR(SP, IR); - + n := 0; FOR i := 0 TO 15 DO - IF i IN R.regs + R.vregs THEN - Push(i) + IF i IN R.regs THEN + Push(i); + INC(n) END END; - Push(IR); - Op1(opPUSH, IR, sINDIR); - Op1(opCALL, SR, sIDX); - EmitWord(RTL.int); + MovRR(SP, R4); + Op2(opADD, imm(n * 2), R4); + + Push(R4); + Op1(opPUSH, R4, sINDIR); + Op1(opCALL, SR, sIDX); EmitWord(-RTL.VarSize); Reloc(RBSS); (* call int *) Op2(opADD, imm(4), SP); FOR i := 15 TO 0 BY -1 DO - IF i IN R.regs + R.vregs THEN + IF i IN R.regs THEN Pop(i) END END; @@ -1606,7 +1652,7 @@ PROCEDURE CodeGen* (outname: ARRAY OF CHAR; target: INTEGER; options: PROG.OPTIO VAR i, adr, heap, stack, TextSize, TypesSize, bits, n, val: INTEGER; - Code, Data, Bss, Free: RECORD address, size: INTEGER END; + Code, Data, Bss: RECORD address, size: INTEGER END; ram, rom: INTEGER; @@ -1625,7 +1671,7 @@ BEGIN ram := MIN(MAX(ram, minRAM), maxRAM); rom := MIN(MAX(rom, minROM), maxROM); - IF IL.codes.bss > ram - minStackSize - RTL.VarSize THEN + IF IL.codes.bss > ram - StkReserve - RTL.VarSize THEN ERRORS.Error(204) END; @@ -1634,35 +1680,40 @@ BEGIN CHL.PushInt(Labels, 0) END; - FOR i := 0 TO LEN(mem) - 1 DO - mem[i] := 0 - END; - - TypesSize := CHL.Length(IL.codes.types) * 2; CodeList := LISTS.create(NIL); RelList := LISTS.create(NIL); - REG.Init(R, Push, Pop, mov, xchg, NIL, NIL, {R4, R5, R6, R7}, {}); + REG.Init(R, Push, Pop, mov, xchg, {R4, R5, R6, R7}); - prolog(ram); - translate; + prolog; + translate(chkSTK IN options.checking); epilog; - Code.address := 10000H - rom; - Code.size := Fixup(Code.address, IntVectorSize + TypesSize); - Data.address := Code.address + Code.size; + TypesSize := CHL.Length(IL.codes.types) * 2; Data.size := CHL.Length(IL.codes.data); - Data.size := Data.size + Data.size MOD 2; - TextSize := Code.size + Data.size; + IF ODD(Data.size) THEN + CHL.PushByte(IL.codes.data, 0); + INC(Data.size) + END; + Code.size := Fixup(0, IntVectorSize + TypesSize + Data.size); + Code.address := 10000H - (IntVectorSize + TypesSize + Data.size + Code.size); + IF Code.address < 10000H - rom THEN + ERRORS.Error(203) + END; + Code.size := Fixup(Code.address, IntVectorSize + TypesSize + Data.size); + Data.address := Code.address + Code.size; + TextSize := Code.size + Data.size; - IF Code.address + TextSize + MAX(IL.codes.dmin - Data.size, IntVectorSize + TypesSize) > 10000H THEN + IF Code.address + TextSize + MAX(IL.codes.dmin - Data.size, IntVectorSize + TypesSize) > 10000H THEN ERRORS.Error(203) END; - Bss.address := RTL.ram + RTL.VarSize; - Bss.size := IL.codes.bss + IL.codes.bss MOD 2; - heap := Bss.address + Bss.size; stack := RTL.ram + ram; - ASSERT(stack - heap >= minStackSize); + Bss.size := IL.codes.bss + IL.codes.bss MOD 2; + DEC(stack, Bss.size); + Bss.address := stack; + DEC(stack, RTL.VarSize); + heap := RTL.ram; + ASSERT(stack - heap >= StkReserve); adr := Code.address + 2; PutWord(stack, adr); adr := Code.address + 6; @@ -1675,20 +1726,18 @@ BEGIN CASE reloc.section OF |RCODE: PutWord(LabelOffs(val) * 2, adr) |RDATA: PutWord(val + Data.address, adr) - |RBSS: PutWord(val + Bss.address, adr) + |RBSS: PutWord((val + Bss.address) MOD 65536, adr) END; reloc := reloc.next(RELOC) END; adr := Data.address; - FOR i := 0 TO CHL.Length(IL.codes.data) - 1 DO + FOR i := 0 TO Data.size - 1 DO mem[adr] := CHL.GetByte(IL.codes.data, i); INC(adr) END; - adr := 10000H - IntVectorSize - TypesSize; - FOR i := TypesSize DIV 2 - 1 TO 0 BY -1 DO PutWord(CHL.GetInt(IL.codes.types, i), adr) END; @@ -1705,11 +1754,6 @@ BEGIN END END; - Free.address := Code.address + TextSize; - Free.size := rom - (IntVectorSize + TypesSize + TextSize); - - PutWord(Free.address, adr); - PutWord(Free.size, adr); PutWord(4130H, adr); (* RET *) PutWord(stack, adr); PutWord(0001H, adr); (* bsl signature (adr 0FFBEH) *) @@ -1718,26 +1762,18 @@ BEGIN PutWord(LabelOffs(IV[i]) * 2, adr) END; + INC(TextSize, IntVectorSize + TypesSize + Code.address MOD 16); + INC(Bss.size, StkReserve + RTL.VarSize); + WR.Create(outname); - - HEX.Data(mem, Code.address, TextSize); - HEX.Data(mem, 10000H - IntVectorSize - TypesSize, IntVectorSize + TypesSize); + HEX.Data(mem, Code.address - Code.address MOD 16, TextSize); HEX.End; - WR.Close; - INC(TextSize, IntVectorSize + TypesSize); - INC(Bss.size, minStackSize + RTL.VarSize); - - C.StringLn("--------------------------------------------"); - C.String( " rom: "); C.Int(TextSize); C.String(" of "); C.Int(rom); C.String(" ("); C.Int(TextSize * 100 DIV rom); C.StringLn("%)"); - IF Free.size > 0 THEN - C.String( " "); C.Int(Free.size); C.String(" bytes free (0"); - C.Hex(Free.address, 4); C.String("H..0"); C.Hex(Free.address + Free.size - 1, 4); C.StringLn("H)") - END; + C.Dashes; + C.String(" rom: "); C.Int(TextSize); C.String(" of "); C.Int(rom); C.String(" ("); C.Int(TextSize * 100 DIV rom); C.StringLn("%)"); C.Ln; - C.String( " ram: "); C.Int(Bss.size); C.String(" of "); C.Int(ram); C.String(" ("); C.Int(Bss.size * 100 DIV ram); C.StringLn("%)") - + C.String(" ram: "); C.Int(Bss.size); C.String(" of "); C.Int(ram); C.String(" ("); C.Int(Bss.size * 100 DIV ram); C.StringLn("%)") END CodeGen; diff --git a/programs/develop/oberon07/Source/MSP430RTL.ob07 b/programs/develop/oberon07/source/MSP430RTL.ob07 similarity index 90% rename from programs/develop/oberon07/Source/MSP430RTL.ob07 rename to programs/develop/oberon07/source/MSP430RTL.ob07 index e2c4f6c8cd..66f0021d99 100644 --- a/programs/develop/oberon07/Source/MSP430RTL.ob07 +++ b/programs/develop/oberon07/source/MSP430RTL.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2019-2020, Anton Krotov + Copyright (c) 2019-2021, Anton Krotov All rights reserved. *) @@ -34,7 +34,7 @@ CONST _new* = 21; - HP = 14; + HP* = 15; LenIV* = 32; @@ -42,9 +42,7 @@ CONST bsl = iv - 2; sp = bsl - 2; empty_proc* = sp - 2; - free_size = empty_proc - 2; - free_adr = free_size - 2; - bits = free_adr - 272; + bits = empty_proc - 272; bits_offs = bits - 32; DataSize* = iv - bits_offs; types = bits_offs - 2; @@ -53,6 +51,10 @@ CONST VarSize* = 4; + StkReserve* = 40; + + trap = 2; + TYPE @@ -61,7 +63,7 @@ TYPE VAR - ram*, trap*, int*: INTEGER; + ram*: INTEGER; rtl*: ARRAY 22 OF RECORD @@ -187,7 +189,7 @@ BEGIN Word1(5405H); (* ADD R4, R5 *) Word2(5035H, bits); (* ADD bits, R5 *) Word1(4524H); (* MOV @R5, R4 *) - Word1(4130H); (* MOV @SP+, PC *) + Word1(4130H); (* RET *) (* L1: *) Word1(4304H); (* MOV #0, R4 *) Word1(4130H) (* RET *) @@ -202,7 +204,7 @@ BEGIN Word1(5404H); (* ADD R4, R4 *) Word2(5034H, bits); (* ADD bits, R4 *) Word1(4424H); (* MOV @R4, R4 *) - Word1(4130H); (* MOV @SP+, PC *) + Word1(4130H); (* RET *) (* L1: *) Word1(4304H); (* MOV #0, R4 *) Word1(4130H) (* RET *) @@ -234,7 +236,7 @@ BEGIN Word2(0F114H, 2); (* AND 2(SP), R4 *) Word1(2400H + 3); (* JZ L1 *) Word1(4314H); (* MOV #1, R4 *) - Word1(4130H); (* MOV @SP+, PC *) + Word1(4130H); (* RET *) (* L2: *) Word1(4304H); (* MOV #0, R4 *) (* L1: *) @@ -374,51 +376,47 @@ BEGIN (* _error (modNum, modName, err, line: INTEGER) *) IF rtl[_error].used THEN Label(rtl[_error].label); - Word1(0C232H); (* BIC #8, SR; DINT *) - Word1(4303H); (* MOV R3, R3; NOP *) - Word2(4114H, 2); (* MOV 2(SP), R4; R4 <- modNum *) - Word2(4115H, 4); (* MOV 4(SP), R5; R5 <- modName *) - Word2(4116H, 6); (* MOV 6(SP), R6; R6 <- err *) - Word2(4117H, 8); (* MOV 8(SP), R7; R7 <- line *) - Word2(4211H, sp); (* MOV sp(SR), SP *) - Word1(1207H); (* PUSH R7 *) - Word1(1206H); (* PUSH R6 *) - Word1(1205H); (* PUSH R5 *) - Word1(1204H); (* PUSH R4 *) - Word2(4214H, trap); (* MOV trap(SR), R4 *) - Word1(9304H); (* TST R4 *) - Word1(2400H + 1); (* JZ L *) - Word1(1284H); (* CALL R4 *) - (* L: *) - Word2(04032H, 0F0H) (* MOV CPUOFF+OSCOFF+SCG0+SCG1, SR *) + Word1(5321H); (* ADD #2, SP *) + Word1(4134H); (* POP R4; R4 <- modNum *) + Word1(4135H); (* POP R5; R5 <- modName *) + Word1(4136H); (* POP R6; R6 <- err *) + Word1(4137H); (* POP R7; R7 <- line *) + Word2(4211H, sp); (* MOV sp(SR), SP *) + Word1(1207H); (* PUSH R7 *) + Word1(1206H); (* PUSH R6 *) + Word1(1205H); (* PUSH R5 *) + Word1(1204H); (* PUSH R4 *) + Word2(4214H, sp); (* MOV sp(SR), R4 *) + Word2(1294H, trap); (* CALL trap(R4) *) + Word2(04032H, 0F0H) (* MOV CPUOFF+OSCOFF+SCG0+SCG1, SR *) END; (* _new (t, size: INTEGER; VAR ptr: INTEGER) *) IF rtl[_new].used THEN Label(rtl[_new].label); - Word1(1202H); (* PUSH SR *) - Word1(4302H); (* MOV #0, SR *) - Word1(4303H); (* NOP *) - Word1(4104H); (* MOV SP, R4 *) - Word2(8034H, 16); (* SUB #16, R4 *) - Word1(4005H + 100H * HP); (* MOV HP, R5 *) - Word2(5115H, 6); (* ADD 6(SP), R5 *) - Word1(9504H); (* CMP R5, R4 *) - Word2(4114H, 8); (* MOV 8(SP), R4 *) - Word1(3800H + 12); (* JL L1 *) - Word3(4190H + HP, 4, 0); (* MOV 4(SP), 0(HP) *) - Word1(5320H + HP); (* ADD #2, HP *) - Word2(4084H + 100H * HP, 0); (* MOV HP, 0(R4) *) - (* L3 *) - Word2(4380H + HP, 0); (* MOV #0, 0(HP) *) - Word1(5320H + HP); (* ADD #2, HP *) - Word1(9500H + HP); (* CMP R5, HP *) - Word1(3800H + 400H - 5); (* JL L3 *) - Word1(3C00H + 2); (* JMP L2 *) - (* L1 *) - Word2(4384H, 0); (* MOV #0, 0(R4) *) - (* L2 *) - Word1(1300H) (* RETI *) + Word1(1202H); (* PUSH SR *) + Word1(4302H); (* MOV #0, SR *) + Word1(4303H); (* NOP *) + Word1(4104H); (* MOV SP, R4 *) + Word2(8034H, StkReserve); (* SUB #StkReserve, R4 *) + Word1(4005H + 100H * HP); (* MOV HP, R5 *) + Word2(5115H, 6); (* ADD 6(SP), R5 *) + Word1(9504H); (* CMP R5, R4 *) + Word2(4114H, 8); (* MOV 8(SP), R4 *) + Word1(3800H + 12); (* JL L1 *) + Word3(4190H + HP, 4, 0); (* MOV 4(SP), 0(HP) *) + Word1(5320H + HP); (* ADD #2, HP *) + Word2(4084H + 100H * HP, 0); (* MOV HP, 0(R4) *) + (* L3 *) + Word2(4380H + HP, 0); (* MOV #0, 0(HP) *) + Word1(5320H + HP); (* ADD #2, HP *) + Word1(9500H + HP); (* CMP R5, HP *) + Word1(3800H + 400H - 5); (* JL L3 *) + Word1(3C00H + 2); (* JMP L2 *) + (* L1 *) + Word2(4384H, 0); (* MOV #0, 0(R4) *) + (* L2 *) + Word1(1300H) (* RETI *) END; (* _guardrec (t0, t1: INTEGER): INTEGER *) @@ -442,7 +440,7 @@ BEGIN Word1(9405H); (* CMP R4, R5 *) Word1(2400H + 2); (* JZ L2 *) Word1(4304H); (* MOV #0, R4 *) - Word1(4130H); (* MOV @SP+, PC *) + Word1(4130H); (* RET *) (* L2: *) Word1(4314H); (* MOV #1, R4 *) Word1(4130H) (* RET *) @@ -661,14 +659,12 @@ BEGIN END Used; -PROCEDURE Init* (pLabel, pWord, pCall: EMITPROC; ramSize: INTEGER); +PROCEDURE Init* (pLabel, pWord, pCall: EMITPROC); BEGIN Label := pLabel; Word := pWord; Call := pCall; ram := 200H; - trap := ram; - int := trap + 2 END Init; diff --git a/programs/develop/oberon07/Source/PARS.ob07 b/programs/develop/oberon07/source/PARS.ob07 similarity index 83% rename from programs/develop/oberon07/Source/PARS.ob07 rename to programs/develop/oberon07/source/PARS.ob07 index a3f2078d75..9cc5a8e7e0 100644 --- a/programs/develop/oberon07/Source/PARS.ob07 +++ b/programs/develop/oberon07/source/PARS.ob07 @@ -1,14 +1,14 @@ (* BSD 2-Clause License - Copyright (c) 2018-2020, Anton Krotov + Copyright (c) 2018-2021, Anton Krotov All rights reserved. *) MODULE PARS; IMPORT PROG, SCAN, ARITH, STRINGS, ERRORS, LISTS, IL, CONSOLE, PATHS, UTILS, - C := COLLECTIONS, TARGETS, THUMB; + C := COLLECTIONS, TARGETS, THUMB, MSP430; CONST @@ -60,7 +60,7 @@ TYPE constexp*: BOOLEAN; main*: BOOLEAN; - open*: PROCEDURE (parser: PARSER; modname: ARRAY OF CHAR): BOOLEAN; + open*: PROCEDURE (parser: PARSER; modname, FileExt: ARRAY OF CHAR): BOOLEAN; parse*: PROCEDURE (parser: PARSER); StatSeq*: STATPROC; expression*: EXPRPROC; @@ -198,10 +198,11 @@ END ExpectSym; PROCEDURE ImportList (parser: PARSER); VAR + fname, path, ext, _name: PATH; name: SCAN.IDENT; parser2: PARSER; pos: POSITION; - alias: BOOLEAN; + alias, _in: BOOLEAN; unit: PROG.UNIT; ident: PROG.IDENT; @@ -222,22 +223,69 @@ BEGIN Next(parser); + path := parser.path; + fname := ""; + ext := UTILS.FILE_EXT; + COPY(name.s, _name); + _in := FALSE; + + IF parser.sym = SCAN.lxIN THEN + _in := TRUE; + Next(parser); + IF parser.sym = SCAN.lxSTRING THEN + STRINGS.trim(parser.lex.string.s, fname) + ELSIF parser.sym = SCAN.lxCHAR THEN + fname[0] := CHR(ARITH.Int(parser.lex.value)); + fname[1] := 0X + ELSE + check1(FALSE, parser, 117) + END; + STRINGS.replace(fname, "/", UTILS.slash); + STRINGS.replace(fname, "\", UTILS.slash); + PATHS.DelSlashes(fname); + PATHS.split(fname, path, _name, ext); + IF PATHS.isRelative(path) THEN + PATHS.RelPath(parser.path, path, fname); + STRINGS.append(fname, _name); + STRINGS.append(fname, ext); + PATHS.split(fname, path, _name, ext) + END; + Next(parser) + END; + IF (parser.sym = SCAN.lxCOMMA) OR (parser.sym = SCAN.lxSEMI) THEN alias := FALSE; - unit := PROG.getUnit(name); + IF (fname = "") & ((_name = "SYSTEM") OR PROG.LowerCase & (_name = "system")) THEN + unit := PROG.program.sysunit + ELSE + IF fname # "" THEN + unit := PROG.getUnit(fname) + ELSE + fname := path; + STRINGS.append(fname, _name); + STRINGS.append(fname, UTILS.FILE_EXT); + unit := PROG.getUnit(fname); + IF unit = NIL THEN + fname := parser.lib_path; + STRINGS.append(fname, _name); + STRINGS.append(fname, UTILS.FILE_EXT); + unit := PROG.getUnit(fname) + END + END + END; IF unit # NIL THEN check(unit.closed, pos, 31) ELSE - parser2 := parser.create(parser.path, parser.lib_path, + parser2 := parser.create(path, parser.lib_path, parser.StatSeq, parser.expression, parser.designator, parser.chkreturn); - IF ~parser2.open(parser2, name.s) THEN - IF parser.path # parser.lib_path THEN + IF ~parser2.open(parser2, _name, ext) THEN + IF (path # parser.lib_path) & ~_in THEN destroy(parser2); parser2 := parser.create(parser.lib_path, parser.lib_path, parser.StatSeq, parser.expression, parser.designator, parser.chkreturn); - check(parser2.open(parser2, name.s), pos, 29) + check(parser2.open(parser2, _name, ext), pos, 29) ELSE error(pos, 29) END @@ -245,6 +293,7 @@ BEGIN parser2.parse(parser2); unit := parser2.unit; + unit.fname := parser2.fname; destroy(parser2) END; IF unit = PROG.program.sysunit THEN @@ -294,8 +343,8 @@ END QIdent; PROCEDURE strcmp* (VAR v: ARITH.VALUE; v2: ARITH.VALUE; operator: INTEGER); VAR - str: SCAN.LEXSTR; - string1, string2: SCAN.IDENT; + str: SCAN.TEXTSTR; + string1, string2: SCAN.STRING; bool: BOOLEAN; BEGIN @@ -303,20 +352,20 @@ BEGIN IF v.typ = ARITH.tCHAR THEN ASSERT(v2.typ = ARITH.tSTRING); ARITH.charToStr(v, str); - string1 := SCAN.enterid(str); - string2 := v2.string(SCAN.IDENT) + string1 := SCAN.enterStr(str); + string2 := v2.string(SCAN.STRING) END; IF v2.typ = ARITH.tCHAR THEN ASSERT(v.typ = ARITH.tSTRING); ARITH.charToStr(v2, str); - string2 := SCAN.enterid(str); - string1 := v.string(SCAN.IDENT) + string2 := SCAN.enterStr(str); + string1 := v.string(SCAN.STRING) END; IF v.typ = v2.typ THEN - string1 := v.string(SCAN.IDENT); - string2 := v2.string(SCAN.IDENT) + string1 := v.string(SCAN.STRING); + string2 := v2.string(SCAN.STRING) END; CASE operator OF @@ -482,27 +531,26 @@ VAR res, sf: INTEGER; BEGIN - IF parser.lex.s = "stdcall" THEN + checklex(parser, SCAN.lxIDENT); + IF parser.lex.ident.s = "stdcall" THEN sf := PROG.sf_stdcall - ELSIF parser.lex.s = "stdcall64" THEN - sf := PROG.sf_stdcall64 - ELSIF parser.lex.s = "ccall" THEN + ELSIF parser.lex.ident.s = "cdecl" THEN + sf := PROG.sf_cdecl + ELSIF parser.lex.ident.s = "ccall" THEN sf := PROG.sf_ccall - ELSIF parser.lex.s = "ccall16" THEN - sf := PROG.sf_ccall16 - ELSIF parser.lex.s = "win64" THEN + ELSIF parser.lex.ident.s = "win64" THEN sf := PROG.sf_win64 - ELSIF parser.lex.s = "systemv" THEN + ELSIF parser.lex.ident.s = "systemv" THEN sf := PROG.sf_systemv - ELSIF parser.lex.s = "windows" THEN + ELSIF parser.lex.ident.s = "windows" THEN sf := PROG.sf_windows - ELSIF parser.lex.s = "linux" THEN + ELSIF parser.lex.ident.s = "linux" THEN sf := PROG.sf_linux - ELSIF parser.lex.s = "code" THEN + ELSIF parser.lex.ident.s = "code" THEN sf := PROG.sf_code - ELSIF parser.lex.s = "oberon" THEN + ELSIF parser.lex.ident.s = "oberon" THEN sf := PROG.sf_oberon - ELSIF parser.lex.s = "noalign" THEN + ELSIF parser.lex.ident.s = "noalign" THEN sf := PROG.sf_noalign ELSE check1(FALSE, parser, 124) @@ -519,12 +567,16 @@ BEGIN CASE sf OF |PROG.sf_stdcall: res := PROG.stdcall - |PROG.sf_stdcall64: - res := PROG.stdcall64 + |PROG.sf_cdecl: + res := PROG.cdecl |PROG.sf_ccall: - res := PROG.ccall - |PROG.sf_ccall16: - res := PROG.ccall16 + IF TARGETS.OS IN {TARGETS.osWIN32, TARGETS.osLINUX32, TARGETS.osKOS} THEN + res := PROG.ccall + ELSIF TARGETS.OS = TARGETS.osWIN64 THEN + res := PROG.win64 + ELSIF TARGETS.OS = TARGETS.osLINUX64 THEN + res := PROG.systemv + END |PROG.sf_win64: res := PROG.win64 |PROG.sf_systemv: @@ -545,7 +597,7 @@ BEGIN END |PROG.sf_linux: IF TARGETS.OS = TARGETS.osLINUX32 THEN - res := PROG.ccall16 + res := PROG.ccall ELSIF TARGETS.OS = TARGETS.osLINUX64 THEN res := PROG.systemv END @@ -560,11 +612,11 @@ END sysflag; PROCEDURE procflag (parser: PARSER; VAR _import: IL.IMPORT_PROC; isProc: BOOLEAN): INTEGER; VAR call: INTEGER; - dll, proc: SCAN.LEXSTR; + dll, proc: SCAN.TEXTSTR; pos: POSITION; - PROCEDURE getStr (parser: PARSER; VAR name: SCAN.LEXSTR); + PROCEDURE getStr (parser: PARSER; VAR name: SCAN.TEXTSTR); VAR pos: POSITION; str: ARITH.VALUE; @@ -573,7 +625,7 @@ VAR getpos(parser, pos); ConstExpression(parser, str); IF str.typ = ARITH.tSTRING THEN - name := str.string(SCAN.IDENT).s + name := str.string(SCAN.STRING).s ELSIF str.typ = ARITH.tCHAR THEN ARITH.charToStr(str, name) ELSE @@ -614,9 +666,13 @@ BEGIN |32: IF TARGETS.CPU = TARGETS.cpuX86 THEN call := PROG.default32 ELSE - call := PROG.ccall + call := PROG.cdecl + END + |64: IF TARGETS.CPU = TARGETS.cpuAMD64 THEN + call := PROG.default64 + ELSE + call := PROG.cdecl END - |64: call := PROG.default64 END END; @@ -920,12 +976,12 @@ VAR _import: IL.IMPORT_PROC; endmod, b: BOOLEAN; fparams: SET; - variables: LISTS.LIST; int, flt: INTEGER; comma: BOOLEAN; code, iv: ARITH.VALUE; codeProc, handler: BOOLEAN; + line: INTEGER; BEGIN endmod := FALSE; @@ -938,12 +994,13 @@ VAR getpos(parser, pos); pos1 := pos; checklex(parser, SCAN.lxIDENT); + line := pos.line; IF _import # NIL THEN proc := IdentDef(parser, PROG.idIMP, name); proc._import := _import; IF _import.name = "" THEN - _import.name := name.s + COPY(name.s, _import.name) END; PROG.program.procs.last(PROG.PROC)._import := _import ELSE @@ -961,7 +1018,7 @@ VAR IF parser.sym = SCAN.lxLSQUARE THEN getpos(parser, pos2); - check(TARGETS.target = TARGETS.STM32CM3, pos2, 24); + check((TARGETS.CPU = TARGETS.cpuTHUMB) & (TARGETS.OS = TARGETS.osNONE), pos2, 24); Next(parser); getpos(parser, pos2); ConstExpression(parser, iv); @@ -1075,8 +1132,10 @@ VAR proc.proc.leave := IL.LeaveC() END; - IF TARGETS.CPU = TARGETS.cpuMSP430 THEN - check((enter.param2 * ORD(~codeProc) + proc._type.parSize) * 2 + 16 < PROG.program.options.ram, pos1, 63) + IF (TARGETS.CPU = TARGETS.cpuMSP430) & ~codeProc THEN + check(MSP430.CheckProcDataSize(enter.param2 + proc._type.parSize, PROG.program.options.ram), pos1, 63); + enter.param2 := enter.param2 * 65536 + line; + enter.param3 := IL.codes.errlabels[10] END END; @@ -1086,15 +1145,15 @@ VAR getpos(parser, pos); endname := parser.lex.ident; IF ~codeProc & (_import = NIL) THEN - check(endname = name, pos, 60); + check(PROG.IdEq(endname, name), pos, 60); ExpectSym(parser, SCAN.lxSEMI); Next(parser) ELSE - IF endname = parser.unit.name THEN + IF PROG.IdEq(endname, parser.unit.name) THEN ExpectSym(parser, SCAN.lxPOINT); Next(parser); endmod := TRUE - ELSIF endname = name THEN + ELSIF PROG.IdEq(endname, name) THEN ExpectSym(parser, SCAN.lxSEMI); Next(parser) ELSE @@ -1108,17 +1167,7 @@ VAR END END; - IF ~codeProc & (_import = NIL) THEN - variables := LISTS.create(NIL); - ELSE - variables := NIL - END; - - PROG.closeScope(unit, variables); - - IF ~codeProc & (_import = NIL) THEN - enter.variables := variables - END + PROG.closeScope(unit); RETURN endmod END ProcDeclaration; @@ -1185,11 +1234,11 @@ BEGIN ExpectSym(parser, SCAN.lxIDENT); IF ~parser.main THEN - check1(parser.lex.s = parser.modname, parser, 23) + check1(parser.lex.ident.s = parser.modname, parser, 23) END; unit := PROG.newUnit(parser.lex.ident); - + unit.fname := parser.fname; parser.unit := unit; ExpectSym(parser, SCAN.lxSEMI); @@ -1214,7 +1263,7 @@ BEGIN END; label := IL.NewLabel(); - IL.AddJmpCmd(IL.opJMP, label); + IL.Jmp(IL.opJMP, label); name := IL.putstr(unit.name.s); @@ -1228,7 +1277,7 @@ BEGIN FOR errno := 1 TO LEN(IL.codes.errlabels) - 1 DO IL.SetErrLabel(errno); IL.AddCmd(IL.opPUSHC, errno); - IL.AddJmpCmd(IL.opJMP, errlabel) + IL.Jmp(IL.opJMP, errlabel) END; endmod := DeclarationSequence(parser); @@ -1245,7 +1294,7 @@ BEGIN checklex(parser, SCAN.lxEND); ExpectSym(parser, SCAN.lxIDENT); - check1(parser.lex.s = unit.name.s, parser, 25); + check1(parser.lex.ident.s = unit.name.s, parser, 25); ExpectSym(parser, SCAN.lxPOINT) END; @@ -1254,12 +1303,12 @@ BEGIN END parse; -PROCEDURE open (parser: PARSER; modname: ARRAY OF CHAR): BOOLEAN; +PROCEDURE open (parser: PARSER; modname, FileExt: ARRAY OF CHAR): BOOLEAN; BEGIN ASSERT(parser # NIL); STRINGS.append(parser.fname, modname); - STRINGS.append(parser.fname, parser.ext); + STRINGS.append(parser.fname, FileExt); STRINGS.append(parser.modname, modname); parser.scanner := SCAN.open(parser.fname) diff --git a/programs/develop/oberon07/Source/PATHS.ob07 b/programs/develop/oberon07/source/PATHS.ob07 similarity index 65% rename from programs/develop/oberon07/Source/PATHS.ob07 rename to programs/develop/oberon07/source/PATHS.ob07 index 5532b6ca1d..f75c64a004 100644 --- a/programs/develop/oberon07/Source/PATHS.ob07 +++ b/programs/develop/oberon07/source/PATHS.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2018-2019, Anton Krotov + Copyright (c) 2018-2021, Anton Krotov All rights reserved. *) @@ -29,7 +29,7 @@ VAR BEGIN len := LENGTH(fname); pos1 := len - 1; - pos2 := len - 1; + pos2 := pos1; STRINGS.search(fname, pos1, slash, FALSE); STRINGS.search(fname, pos2, ".", FALSE); @@ -45,8 +45,7 @@ BEGIN STRINGS.copy(fname, name, pos1, 0, pos2 - pos1); name[pos2 - pos1] := 0X; STRINGS.copy(fname, ext, pos2, 0, len - pos2); - ext[len - pos2] := 0X; - + ext[len - pos2] := 0X END split; @@ -67,6 +66,12 @@ BEGIN error := FALSE; j := 0; + WHILE (relative[j] = ".") & (relative[j + 1] = slash) DO + INC(j, 2) + ELSIF relative[j] = slash DO + INC(j) + END; + WHILE ~error & (relative[j] # 0X) DO IF (relative[j] = ".") & (relative[j + 1] = ".") & (relative[j + 2] = slash) & (i > 0) & (res[i - 1] = slash) THEN DEC(i, 2); @@ -95,6 +100,43 @@ BEGIN END RelPath; +PROCEDURE DelSlashes* (VAR path: ARRAY OF CHAR); +VAR + i, j, k: INTEGER; + c: CHAR; + +BEGIN + i := 0; + j := 0; + k := 0; + REPEAT + c := path[j]; + INC(j); + IF c = slash THEN + INC(k) + ELSE + k := 0 + END; + IF k <= 1 THEN + path[i] := c; + INC(i) + END + UNTIL c = 0X; + + i := 0; + j := 0; + REPEAT + c := path[j]; + INC(j); + path[i] := c; + INC(i); + IF (c = slash) & (path[j] = ".") & (path[j + 1] = slash) THEN + INC(j, 2) + END + UNTIL c = 0X +END DelSlashes; + + PROCEDURE isRelative* (path: ARRAY OF CHAR): BOOLEAN; RETURN UTILS.isRelative(path) END isRelative; diff --git a/programs/develop/oberon07/Source/PE32.ob07 b/programs/develop/oberon07/source/PE32.ob07 similarity index 100% rename from programs/develop/oberon07/Source/PE32.ob07 rename to programs/develop/oberon07/source/PE32.ob07 diff --git a/programs/develop/oberon07/Source/PROG.ob07 b/programs/develop/oberon07/source/PROG.ob07 similarity index 80% rename from programs/develop/oberon07/Source/PROG.ob07 rename to programs/develop/oberon07/source/PROG.ob07 index 87cde889fa..f2e3b6c46d 100644 --- a/programs/develop/oberon07/Source/PROG.ob07 +++ b/programs/develop/oberon07/source/PROG.ob07 @@ -1,13 +1,13 @@ (* BSD 2-Clause License - Copyright (c) 2018-2020, Anton Krotov + Copyright (c) 2018-2021, Anton Krotov All rights reserved. *) MODULE PROG; -IMPORT SCAN, LISTS, ARITH, ERRORS, C := COLLECTIONS, IL, UTILS, TARGETS, STRINGS; +IMPORT SCAN, LISTS, ARITH, ERRORS, C := COLLECTIONS, IL, UTILS, TARGETS, STRINGS, PATHS; CONST @@ -44,25 +44,24 @@ CONST default32* = 2; _default32* = default32 + 1; stdcall* = 4; _stdcall* = stdcall + 1; - ccall* = 6; _ccall* = ccall + 1; - ccall16* = 8; _ccall16* = ccall16 + 1; + cdecl* = 6; _cdecl* = cdecl + 1; + ccall* = 8; _ccall* = ccall + 1; win64* = 10; _win64* = win64 + 1; - stdcall64* = 12; _stdcall64* = stdcall64 + 1; - default64* = 14; _default64* = default64 + 1; - systemv* = 16; _systemv* = systemv + 1; - default16* = 18; - code* = 20; _code* = code + 1; + default64* = 12; _default64* = default64 + 1; + systemv* = 14; _systemv* = systemv + 1; + default16* = 16; _default16* = default16 + 1; + code* = 18; _code* = code + 1; noalign* = 22; - callee_clean_up* = {default32, stdcall, _stdcall, default64, stdcall64, _stdcall64}; + callee_clean_up* = {default32, _default32, stdcall, _stdcall, default64, _default64}; - sf_stdcall* = 0; sf_stdcall64* = 1; sf_ccall* = 2; sf_ccall16* = 3; - sf_win64* = 4; sf_systemv* = 5; sf_windows* = 6; sf_linux* = 7; - sf_code* = 8; sf_oberon* = 9; - sf_noalign* = 10; + sf_stdcall* = 0; sf_oberon* = 1; sf_cdecl* = 2; sf_ccall* = 3; + sf_win64* = 4; sf_systemv* = 5; sf_windows* = 6; sf_linux* = 7; + sf_code* = 8; + sf_noalign* = 9; - proc_flags* = {sf_stdcall, sf_stdcall64, sf_ccall, sf_ccall16, sf_win64, sf_systemv, sf_windows, sf_linux, sf_code, sf_oberon}; + proc_flags* = {sf_stdcall, sf_cdecl, sf_ccall, sf_win64, sf_systemv, sf_windows, sf_linux, sf_code, sf_oberon}; rec_flags* = {sf_noalign}; STACK_FRAME = 2; @@ -115,6 +114,7 @@ TYPE rUNIT = RECORD (LISTS.ITEM) + fname*: PATHS.PATH; name*: SCAN.IDENT; idents*: LISTS.LIST; frwPointers: LISTS.LIST; @@ -214,7 +214,7 @@ TYPE VAR - LowerCase: BOOLEAN; + LowerCase*: BOOLEAN; idents: C.COLLECTION; program*: PROGRAM; @@ -300,15 +300,18 @@ BEGIN END closeUnit; +PROCEDURE IdEq* (a, b: SCAN.IDENT): BOOLEAN; + RETURN (a.hash = b.hash) & (a.s = b.s) +END IdEq; + + PROCEDURE unique (unit: UNIT; ident: SCAN.IDENT): BOOLEAN; VAR item: IDENT; BEGIN - ASSERT(ident # NIL); - item := unit.idents.last(IDENT); - WHILE (item.typ # idGUARD) & (item.name # ident) DO + WHILE (item.typ # idGUARD) & ~IdEq(item.name, ident) DO item := item.prev(IDENT) END @@ -324,7 +327,6 @@ VAR BEGIN ASSERT(unit # NIL); - ASSERT(ident # NIL); res := unique(unit, ident); @@ -410,21 +412,19 @@ VAR item: IDENT; BEGIN - ASSERT(ident # NIL); - item := unit.idents.last(IDENT); IF item # NIL THEN IF currentScope THEN - WHILE (item.name # ident) & (item.typ # idGUARD) DO + WHILE (item.typ # idGUARD) & ~IdEq(item.name, ident) DO item := item.prev(IDENT) END; - IF item.name # ident THEN + IF item.typ = idGUARD THEN item := NIL END ELSE - WHILE (item # NIL) & (item.name # ident) DO + WHILE (item # NIL) & ~IdEq(item.name, ident) DO item := item.prev(IDENT) END END @@ -452,7 +452,8 @@ BEGIN NEW(item); item := NewIdent(); - item.name := NIL; + item.name.s := ""; + item.name.hash := 0; item.typ := idGUARD; LISTS.push(unit.idents, item) @@ -462,11 +463,10 @@ BEGIN END openScope; -PROCEDURE closeScope* (unit: UNIT; variables: LISTS.LIST); +PROCEDURE closeScope* (unit: UNIT); VAR item: IDENT; del: IDENT; - lvar: IL.LOCALVAR; BEGIN item := unit.idents.last(IDENT); @@ -477,17 +477,6 @@ BEGIN IF (del.typ = idVAR) & (del.offset = -1) THEN ERRORS.HintMsg(del.name.s, del.pos.line, del.pos.col, 0) END; - IF (variables # NIL) & (del.typ IN {idVAR, idPARAM}) & (del.offset # -1) THEN - IF del._type.typ IN BASICTYPES - {tREAL} + {tPOINTER, tPROCEDURE} THEN - lvar := IL.NewVar(); - lvar.offset := del.offset; - lvar.size := del._type.size; - IF del.typ = idVAR THEN - lvar.offset := -lvar.offset - END; - LISTS.push(variables, lvar) - END - END; LISTS.delete(unit.idents, del); C.push(idents, del) END; @@ -508,7 +497,6 @@ VAR BEGIN ASSERT(unit # NIL); ASSERT(_type # NIL); - ASSERT(baseIdent # NIL); NEW(newptr); @@ -626,20 +614,18 @@ PROCEDURE arrcomp* (src, dst: _TYPE): BOOLEAN; END arrcomp; -PROCEDURE getUnit* (name: SCAN.IDENT): UNIT; +PROCEDURE getUnit* (name: PATHS.PATH): UNIT; VAR item: UNIT; BEGIN - ASSERT(name # NIL); - item := program.units.first(UNIT); - WHILE (item # NIL) & (item.name # name) DO + WHILE (item # NIL) & (item.fname # name) DO item := item.next(UNIT) END; - IF (item = NIL) & ((name.s = "SYSTEM") OR LowerCase & (name.s = "system")) THEN + IF (item = NIL) & ((name = "SYSTEM") OR LowerCase & (name = "system")) THEN item := program.sysunit END @@ -650,19 +636,22 @@ END getUnit; PROCEDURE enterStTypes (unit: UNIT); - PROCEDURE enter (unit: UNIT; name: SCAN.LEXSTR; _type: _TYPE); + PROCEDURE enter (unit: UNIT; nameStr: SCAN.IDSTR; _type: _TYPE); VAR ident: IDENT; - upper: SCAN.LEXSTR; + upper: SCAN.IDSTR; + name: SCAN.IDENT; BEGIN IF LowerCase THEN - ident := addIdent(unit, SCAN.enterid(name), idTYPE); + SCAN.setIdent(name, nameStr); + ident := addIdent(unit, name, idTYPE); ident._type := _type END; - upper := name; + upper := nameStr; STRINGS.UpCase(upper); - ident := addIdent(unit, SCAN.enterid(upper), idTYPE); + SCAN.setIdent(name, upper); + ident := addIdent(unit, name, idTYPE); ident._type := _type END enter; @@ -687,80 +676,64 @@ END enterStTypes; PROCEDURE enterStProcs (unit: UNIT); - PROCEDURE EnterProc (unit: UNIT; name: SCAN.LEXSTR; proc: INTEGER); + PROCEDURE Enter (unit: UNIT; nameStr: SCAN.IDSTR; nfunc, tfunc: INTEGER); VAR ident: IDENT; - upper: SCAN.LEXSTR; + upper: SCAN.IDSTR; + name: SCAN.IDENT; BEGIN IF LowerCase THEN - ident := addIdent(unit, SCAN.enterid(name), idSTPROC); - ident.stproc := proc; + SCAN.setIdent(name, nameStr); + ident := addIdent(unit, name, tfunc); + ident.stproc := nfunc; ident._type := program.stTypes.tNONE END; - upper := name; + upper := nameStr; STRINGS.UpCase(upper); - ident := addIdent(unit, SCAN.enterid(upper), idSTPROC); - ident.stproc := proc; + SCAN.setIdent(name, upper); + ident := addIdent(unit, name, tfunc); + ident.stproc := nfunc; ident._type := program.stTypes.tNONE - END EnterProc; - - - PROCEDURE EnterFunc (unit: UNIT; name: SCAN.LEXSTR; func: INTEGER); - VAR - ident: IDENT; - upper: SCAN.LEXSTR; - - BEGIN - IF LowerCase THEN - ident := addIdent(unit, SCAN.enterid(name), idSTFUNC); - ident.stproc := func; - ident._type := program.stTypes.tNONE - END; - upper := name; - STRINGS.UpCase(upper); - ident := addIdent(unit, SCAN.enterid(upper), idSTFUNC); - ident.stproc := func; - ident._type := program.stTypes.tNONE - END EnterFunc; + END Enter; BEGIN - EnterProc(unit, "assert", stASSERT); - EnterProc(unit, "dec", stDEC); - EnterProc(unit, "excl", stEXCL); - EnterProc(unit, "inc", stINC); - EnterProc(unit, "incl", stINCL); - EnterProc(unit, "new", stNEW); - EnterProc(unit, "copy", stCOPY); + Enter(unit, "assert", stASSERT, idSTPROC); + Enter(unit, "dec", stDEC, idSTPROC); + Enter(unit, "excl", stEXCL, idSTPROC); + Enter(unit, "inc", stINC, idSTPROC); + Enter(unit, "incl", stINCL, idSTPROC); + Enter(unit, "new", stNEW, idSTPROC); + Enter(unit, "copy", stCOPY, idSTPROC); - EnterFunc(unit, "abs", stABS); - EnterFunc(unit, "asr", stASR); - EnterFunc(unit, "chr", stCHR); - EnterFunc(unit, "len", stLEN); - EnterFunc(unit, "lsl", stLSL); - EnterFunc(unit, "odd", stODD); - EnterFunc(unit, "ord", stORD); - EnterFunc(unit, "ror", stROR); - EnterFunc(unit, "bits", stBITS); - EnterFunc(unit, "lsr", stLSR); - EnterFunc(unit, "length", stLENGTH); - EnterFunc(unit, "min", stMIN); - EnterFunc(unit, "max", stMAX); + Enter(unit, "abs", stABS, idSTFUNC); + Enter(unit, "asr", stASR, idSTFUNC); + Enter(unit, "chr", stCHR, idSTFUNC); + Enter(unit, "len", stLEN, idSTFUNC); + Enter(unit, "lsl", stLSL, idSTFUNC); + Enter(unit, "odd", stODD, idSTFUNC); + Enter(unit, "ord", stORD, idSTFUNC); + Enter(unit, "ror", stROR, idSTFUNC); + Enter(unit, "bits", stBITS, idSTFUNC); + Enter(unit, "lsr", stLSR, idSTFUNC); + Enter(unit, "length", stLENGTH, idSTFUNC); + Enter(unit, "min", stMIN, idSTFUNC); + Enter(unit, "max", stMAX, idSTFUNC); IF TARGETS.RealSize # 0 THEN - EnterProc(unit, "pack", stPACK); - EnterProc(unit, "unpk", stUNPK); - EnterFunc(unit, "floor", stFLOOR); - EnterFunc(unit, "flt", stFLT) + Enter(unit, "pack", stPACK, idSTPROC); + Enter(unit, "unpk", stUNPK, idSTPROC); + Enter(unit, "floor", stFLOOR, idSTFUNC); + Enter(unit, "flt", stFLT, idSTFUNC) END; IF TARGETS.BitDepth >= 32 THEN - EnterFunc(unit, "wchr", stWCHR) + Enter(unit, "wchr", stWCHR, idSTFUNC) END; IF TARGETS.Dispose THEN - EnterProc(unit, "dispose", stDISPOSE) + Enter(unit, "dispose", stDISPOSE, idSTPROC) END END enterStProcs; @@ -771,8 +744,6 @@ VAR unit: UNIT; BEGIN - ASSERT(name # NIL); - NEW(unit); unit.name := name; @@ -810,7 +781,6 @@ VAR BEGIN ASSERT(self # NIL); - ASSERT(name # NIL); ASSERT(unit # NIL); field := NIL; @@ -818,7 +788,7 @@ BEGIN field := self.fields.first(FIELD); - WHILE (field # NIL) & (field.name # name) DO + WHILE (field # NIL) & ~IdEq(field.name, name) DO field := field.next(FIELD) END; @@ -842,8 +812,6 @@ VAR res: BOOLEAN; BEGIN - ASSERT(name # NIL); - res := getField(self, name, self.unit) = NIL; IF res THEN @@ -901,11 +869,9 @@ VAR item: PARAM; BEGIN - ASSERT(name # NIL); - item := self.params.first(PARAM); - WHILE (item # NIL) & (item.name # name) DO + WHILE (item # NIL) & ~IdEq(item.name, name) DO item := item.next(PARAM) END @@ -919,8 +885,6 @@ VAR res: BOOLEAN; BEGIN - ASSERT(name # NIL); - res := getParam(self, name) = NIL; IF res THEN @@ -1101,23 +1065,27 @@ PROCEDURE createSysUnit; VAR ident: IDENT; unit: UNIT; + name: SCAN.IDENT; - PROCEDURE EnterProc (sys: UNIT; name: SCAN.LEXSTR; idtyp, proc: INTEGER); + PROCEDURE EnterProc (sys: UNIT; nameStr: SCAN.IDSTR; idtyp, proc: INTEGER); VAR ident: IDENT; - upper: SCAN.LEXSTR; + upper: SCAN.IDSTR; + name: SCAN.IDENT; BEGIN IF LowerCase THEN - ident := addIdent(sys, SCAN.enterid(name), idtyp); + SCAN.setIdent(name, nameStr); + ident := addIdent(sys, name, idtyp); ident.stproc := proc; ident._type := program.stTypes.tNONE; ident.export := TRUE END; - upper := name; + upper := nameStr; STRINGS.UpCase(upper); - ident := addIdent(sys, SCAN.enterid(upper), idtyp); + SCAN.setIdent(name, upper); + ident := addIdent(sys, name, idtyp); ident.stproc := proc; ident._type := program.stTypes.tNONE; ident.export := TRUE @@ -1125,7 +1093,9 @@ VAR BEGIN - unit := newUnit(SCAN.enterid("$SYSTEM")); + SCAN.setIdent(name, "$SYSTEM"); + unit := newUnit(name); + unit.fname := "SYSTEM"; EnterProc(unit, "adr", idSYSFUNC, sysADR); EnterProc(unit, "size", idSYSFUNC, sysSIZE); @@ -1161,11 +1131,13 @@ BEGIN EnterProc(unit, "get32", idSYSPROC, sysGET32); IF LowerCase THEN - ident := addIdent(unit, SCAN.enterid("card32"), idTYPE); + SCAN.setIdent(name, "card32"); + ident := addIdent(unit, name, idTYPE); ident._type := program.stTypes.tCARD32; ident.export := TRUE END; - ident := addIdent(unit, SCAN.enterid("CARD32"), idTYPE); + SCAN.setIdent(name, "CARD32"); + ident := addIdent(unit, name, idTYPE); ident._type := program.stTypes.tCARD32; ident.export := TRUE; END; @@ -1247,11 +1219,11 @@ BEGIN program.options := options; CASE TARGETS.OS OF - |TARGETS.osWIN32: program.sysflags := {sf_oberon, sf_windows, sf_stdcall, sf_ccall, sf_ccall16, sf_noalign} - |TARGETS.osLINUX32: program.sysflags := {sf_oberon, sf_linux, sf_stdcall, sf_ccall, sf_ccall16, sf_noalign} - |TARGETS.osKOS: program.sysflags := {sf_oberon, sf_stdcall, sf_ccall, sf_ccall16, sf_noalign} - |TARGETS.osWIN64: program.sysflags := {sf_oberon, sf_windows, sf_stdcall64, sf_win64, sf_systemv, sf_noalign} - |TARGETS.osLINUX64: program.sysflags := {sf_oberon, sf_linux, sf_stdcall64, sf_win64, sf_systemv, sf_noalign} + |TARGETS.osWIN32: program.sysflags := {sf_oberon, sf_windows, sf_stdcall, sf_cdecl, sf_ccall, sf_noalign} + |TARGETS.osLINUX32: program.sysflags := {sf_oberon, sf_linux, sf_stdcall, sf_cdecl, sf_ccall, sf_noalign} + |TARGETS.osKOS: program.sysflags := {sf_oberon, sf_stdcall, sf_cdecl, sf_ccall, sf_noalign} + |TARGETS.osWIN64: program.sysflags := {sf_oberon, sf_windows, sf_win64, sf_systemv, sf_ccall, sf_noalign} + |TARGETS.osLINUX64: program.sysflags := {sf_oberon, sf_linux, sf_win64, sf_systemv, sf_ccall, sf_noalign} |TARGETS.osNONE: program.sysflags := {sf_code} END; diff --git a/programs/develop/oberon07/Source/REG.ob07 b/programs/develop/oberon07/source/REG.ob07 similarity index 58% rename from programs/develop/oberon07/Source/REG.ob07 rename to programs/develop/oberon07/source/REG.ob07 index 32dbbf60d8..06aab4fe11 100644 --- a/programs/develop/oberon07/Source/REG.ob07 +++ b/programs/develop/oberon07/source/REG.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2018-2020, Anton Krotov + Copyright (c) 2018-2021, Anton Krotov All rights reserved. *) @@ -17,14 +17,11 @@ CONST R8* = 8; R9* = 9; R10* = 10; R11* = 11; R12* = 12; R13* = 13; R14* = 14; R15* = 15; - NVR = 32; - TYPE OP1 = PROCEDURE (arg: INTEGER); OP2 = PROCEDURE (arg1, arg2: INTEGER); - OP3 = PROCEDURE (arg1, arg2, arg3: INTEGER); REGS* = RECORD @@ -33,13 +30,8 @@ TYPE top*: INTEGER; pushed*: INTEGER; - vregs*: SET; - offs: ARRAY NVR OF INTEGER; - size: ARRAY NVR OF INTEGER; - push, pop: OP1; - mov, xch: OP2; - load, save: OP3 + mov, xch: OP2 END; @@ -78,17 +70,12 @@ END pop; PROCEDURE InStk (R: REGS; reg: INTEGER): INTEGER; VAR - i, n: INTEGER; + i: INTEGER; BEGIN - i := 0; - n := R.top; - WHILE (i <= n) & (R.stk[i] # reg) DO - INC(i) - END; - - IF i > n THEN - i := -1 + i := R.top; + WHILE (i >= 0) & (R.stk[i] # reg) DO + DEC(i) END RETURN i @@ -206,7 +193,7 @@ VAR res: BOOLEAN; BEGIN - res := FALSE; + res := TRUE; IF reg1 # reg2 THEN n1 := InStk(R, reg1); @@ -215,23 +202,20 @@ BEGIN IF (n1 # -1) & (n2 # -1) THEN R.stk[n1] := reg2; R.stk[n2] := reg1; - R.xch(reg2, reg1); - res := TRUE + R.xch(reg2, reg1) ELSIF (n1 # -1) & (reg2 IN R.regs) THEN R.stk[n1] := reg2; INCL(R.regs, reg1); EXCL(R.regs, reg2); - R.mov(reg2, reg1); - res := TRUE + R.mov(reg2, reg1) ELSIF (n2 # -1) & (reg1 IN R.regs) THEN R.stk[n2] := reg1; EXCL(R.regs, reg1); INCL(R.regs, reg2); - R.mov(reg1, reg2); - res := TRUE + R.mov(reg1, reg2) + ELSE + res := FALSE END - ELSE - res := TRUE END RETURN res @@ -252,8 +236,8 @@ BEGIN reg2 := R.stk[R.top] ELSIF R.top = 0 THEN reg1 := PopAnyReg(R); - reg2 := R.stk[R.top] - ELSIF R.top < 0 THEN + reg2 := R.stk[1] + ELSE (* R.top = -1 *) reg2 := PopAnyReg(R); reg1 := PopAnyReg(R) END @@ -286,130 +270,7 @@ BEGIN END PushAll_1; -PROCEDURE Lock* (VAR R: REGS; reg, offs, size: INTEGER); -BEGIN - ASSERT(reg IN R.vregs); - ASSERT(offs # 0); - ASSERT(size IN {1, 2, 4, 8}); - R.offs[reg] := offs; - R.size[reg] := size -END Lock; - - -PROCEDURE Release* (VAR R: REGS; reg: INTEGER); -BEGIN - ASSERT(reg IN R.vregs); - R.offs[reg] := 0 -END Release; - - -PROCEDURE Load* (R: REGS; reg: INTEGER); -VAR - offs: INTEGER; - -BEGIN - ASSERT(reg IN R.vregs); - offs := R.offs[reg]; - IF offs # 0 THEN - R.load(reg, offs, R.size[reg]) - END -END Load; - - -PROCEDURE Save* (R: REGS; reg: INTEGER); -VAR - offs: INTEGER; - -BEGIN - ASSERT(reg IN R.vregs); - offs := R.offs[reg]; - IF offs # 0 THEN - R.save(reg, offs, R.size[reg]) - END -END Save; - - -PROCEDURE Store* (R: REGS); -VAR - i: INTEGER; - -BEGIN - FOR i := 0 TO NVR - 1 DO - IF i IN R.vregs THEN - Save(R, i) - END - END -END Store; - - -PROCEDURE Restore* (R: REGS); -VAR - i: INTEGER; - -BEGIN - FOR i := 0 TO NVR - 1 DO - IF i IN R.vregs THEN - Load(R, i) - END - END -END Restore; - - -PROCEDURE Reset* (VAR R: REGS); -VAR - i: INTEGER; - -BEGIN - FOR i := 0 TO NVR - 1 DO - IF i IN R.vregs THEN - R.offs[i] := 0 - END - END -END Reset; - - -PROCEDURE GetVarReg* (R: REGS; offs: INTEGER): INTEGER; -VAR - i, res: INTEGER; - -BEGIN - res := -1; - i := 0; - WHILE i < NVR DO - IF (i IN R.vregs) & (R.offs[i] = offs) THEN - res := i; - i := NVR - END; - INC(i) - END - - RETURN res -END GetVarReg; - - -PROCEDURE GetAnyVarReg* (R: REGS): INTEGER; -VAR - i, res: INTEGER; - -BEGIN - res := -1; - i := 0; - WHILE i < NVR DO - IF (i IN R.vregs) & (R.offs[i] = 0) THEN - res := i; - i := NVR - END; - INC(i) - END - - RETURN res -END GetAnyVarReg; - - -PROCEDURE Init* (VAR R: REGS; push, pop: OP1; mov, xch: OP2; load, save: OP3; regs, vregs: SET); -VAR - i: INTEGER; - +PROCEDURE Init* (VAR R: REGS; push, pop: OP1; mov, xch: OP2; regs: SET); BEGIN R.regs := regs; R.pushed := 0; @@ -419,16 +280,6 @@ BEGIN R.pop := pop; R.mov := mov; R.xch := xch; - R.load := load; - R.save := save; - - R.vregs := vregs; - - FOR i := 0 TO NVR - 1 DO - R.offs[i] := 0; - R.size[i] := 0 - END - END Init; diff --git a/programs/develop/oberon07/Source/RVM32I.ob07 b/programs/develop/oberon07/source/RVM32I.ob07 similarity index 100% rename from programs/develop/oberon07/Source/RVM32I.ob07 rename to programs/develop/oberon07/source/RVM32I.ob07 diff --git a/programs/develop/oberon07/source/RVMxI.ob07 b/programs/develop/oberon07/source/RVMxI.ob07 new file mode 100644 index 0000000000..d9630221c8 --- /dev/null +++ b/programs/develop/oberon07/source/RVMxI.ob07 @@ -0,0 +1,1428 @@ +(* + BSD 2-Clause License + + Copyright (c) 2020-2021, Anton Krotov + All rights reserved. +*) + +MODULE RVMxI; + +IMPORT + + PROG, WR := WRITER, IL, CHL := CHUNKLISTS, REG, UTILS, STRINGS, ERRORS, TARGETS; + + +CONST + + LTypes = 0; + LStrings = 1; + LGlobal = 2; + LHeap = 3; + LStack = 4; + + numGPRs = 3; + + R0 = 0; R1 = 1; + BP = 3; SP = 4; + + ACC = R0; + + GPRs = {0 .. 2} + {5 .. numGPRs + 1}; + + opSTOP = 0; opRET = 1; opENTER = 2; opNEG = 3; opNOT = 4; opNOP = 5; + opXCHG = 6; opLDB = 7; opLDH = 8; opLDW = 9; opPUSH = 10; opPUSHC = 11; + opPOP = 12; opLABEL = 13; opLEA = 14; opLLA = 15; + opLDD = 16; (* 17, 18 *) + opJMP = 19; opCALL = 20; opCALLI = 21; + + opMOV = 22; opMUL = 24; opADD = 26; opSUB = 28; opDIV = 30; opMOD = 32; + opSTB = 34; opSTH = 36; opSTW = 38; opSTD = 40; (* 42, 44 *) + opAND = 46; opOR = 48; opXOR = 50; opASR = 52; opLSR = 54; + opLSL = 56; opROR = 58; (* 60, 62 *) opCMP = 64; + + opMOVC = 23; opMULC = 25; opADDC = 27; opSUBC = 29; opDIVC = 31; opMODC = 33; + opSTBC = 35; opSTHC = 37; opSTWC = 39; opSTDC = 41; (* 43, 45 *) + opANDC = 47; opORC = 49; opXORC = 51; opASRC = 53; opLSRC = 55; + opLSLC = 57; opRORC = 59; (* 61, 63 *) opCMPC = 65; + + opBIT = 66; opSYSCALL = 67; opJBT = 68; opADDRC = 69; + + opJEQ = 70; opJNE = 71; opJLT = 72; opJGE = 73; opJGT = 74; opJLE = 75; + opSEQ = 76; opSNE = 77; opSLT = 78; opSGE = 79; opSGT = 80; opSLE = 81; + + +VAR + + R: REG.REGS; count, szWord: INTEGER; + + ldr, str: PROCEDURE (r1, r2: INTEGER); + + +PROCEDURE OutByte (n: BYTE); +BEGIN + WR.WriteByte(n); + INC(count) +END OutByte; + + +PROCEDURE OutInt (n: INTEGER); +BEGIN + IF szWord = 8 THEN + WR.Write64LE(n); + INC(count, 8) + ELSE (* szWord = 4 *) + WR.Write32LE(n); + INC(count, 4) + END +END OutInt; + + +PROCEDURE Emit (op, par1, par2: INTEGER); +BEGIN + OutInt(op); + OutInt(par1); + OutInt(par2) +END Emit; + + +PROCEDURE drop; +BEGIN + REG.Drop(R) +END drop; + + +PROCEDURE GetAnyReg (): INTEGER; + RETURN REG.GetAnyReg(R) +END GetAnyReg; + + +PROCEDURE GetAcc; +BEGIN + ASSERT(REG.GetReg(R, ACC)) +END GetAcc; + + +PROCEDURE UnOp (VAR r: INTEGER); +BEGIN + REG.UnOp(R, r) +END UnOp; + + +PROCEDURE BinOp (VAR r1, r2: INTEGER); +BEGIN + REG.BinOp(R, r1, r2) +END BinOp; + + +PROCEDURE PushAll (NumberOfParameters: INTEGER); +BEGIN + REG.PushAll(R); + DEC(R.pushed, NumberOfParameters) +END PushAll; + + +PROCEDURE push (r: INTEGER); +BEGIN + Emit(opPUSH, r, 0) +END push; + + +PROCEDURE pop (r: INTEGER); +BEGIN + Emit(opPOP, r, 0) +END pop; + + +PROCEDURE mov (r1, r2: INTEGER); +BEGIN + Emit(opMOV, r1, r2) +END mov; + + +PROCEDURE xchg (r1, r2: INTEGER); +BEGIN + Emit(opXCHG, r1, r2) +END xchg; + + +PROCEDURE addrc (r, c: INTEGER); +BEGIN + Emit(opADDC, r, c) +END addrc; + + +PROCEDURE subrc (r, c: INTEGER); +BEGIN + Emit(opSUBC, r, c) +END subrc; + + +PROCEDURE movrc (r, c: INTEGER); +BEGIN + Emit(opMOVC, r, c) +END movrc; + + +PROCEDURE pushc (c: INTEGER); +BEGIN + Emit(opPUSHC, c, 0) +END pushc; + + +PROCEDURE add (r1, r2: INTEGER); +BEGIN + Emit(opADD, r1, r2) +END add; + + +PROCEDURE sub (r1, r2: INTEGER); +BEGIN + Emit(opSUB, r1, r2) +END sub; + + +PROCEDURE ldr64 (r1, r2: INTEGER); +BEGIN + Emit(opLDD, r2 * 256 + r1, 0) +END ldr64; + + +PROCEDURE ldr32 (r1, r2: INTEGER); +BEGIN + Emit(opLDW, r2 * 256 + r1, 0) +END ldr32; + + +PROCEDURE ldr16 (r1, r2: INTEGER); +BEGIN + Emit(opLDH, r2 * 256 + r1, 0) +END ldr16; + + +PROCEDURE ldr8 (r1, r2: INTEGER); +BEGIN + Emit(opLDB, r2 * 256 + r1, 0) +END ldr8; + + +PROCEDURE str64 (r1, r2: INTEGER); +BEGIN + Emit(opSTD, r1 * 256 + r2, 0) +END str64; + + +PROCEDURE str32 (r1, r2: INTEGER); +BEGIN + Emit(opSTW, r1 * 256 + r2, 0) +END str32; + + +PROCEDURE str16 (r1, r2: INTEGER); +BEGIN + Emit(opSTH, r1 * 256 + r2, 0) +END str16; + + +PROCEDURE str8 (r1, r2: INTEGER); +BEGIN + Emit(opSTB, r1 * 256 + r2, 0) +END str8; + + +PROCEDURE GlobalAdr (r, offset: INTEGER); +BEGIN + Emit(opLEA, r + 256 * LGlobal, offset) +END GlobalAdr; + + +PROCEDURE StrAdr (r, offset: INTEGER); +BEGIN + Emit(opLEA, r + 256 * LStrings, offset) +END StrAdr; + + +PROCEDURE ProcAdr (r, label: INTEGER); +BEGIN + Emit(opLLA, r, label) +END ProcAdr; + + +PROCEDURE jnz (r, label: INTEGER); +BEGIN + Emit(opCMPC, r, 0); + Emit(opJNE, label, 0) +END jnz; + + +PROCEDURE CallRTL (proc, par: INTEGER); +BEGIN + Emit(opCALL, IL.codes.rtl[proc], 0); + addrc(SP, par * szWord) +END CallRTL; + + +PROCEDURE jcc (cc: INTEGER): INTEGER; +BEGIN + CASE cc OF + |IL.opEQ, IL.opEQC: cc := opJEQ + |IL.opNE, IL.opNEC: cc := opJNE + |IL.opLT, IL.opLTC: cc := opJLT + |IL.opLE, IL.opLEC: cc := opJLE + |IL.opGT, IL.opGTC: cc := opJGT + |IL.opGE, IL.opGEC: cc := opJGE + END + RETURN cc +END jcc; + + +PROCEDURE shift1 (op, param: INTEGER); +VAR + r1, r2: INTEGER; + +BEGIN + r2 := GetAnyReg(); + Emit(opMOVC, r2, param); + BinOp(r1, r2); + Emit(op, r2, r1); + mov(r1, r2); + drop +END shift1; + + +PROCEDURE shift (op: INTEGER); +VAR + r1, r2: INTEGER; + +BEGIN + BinOp(r1, r2); + Emit(op, r1, r2); + drop +END shift; + + +PROCEDURE translate (szWord: INTEGER); +VAR + cmd, next: IL.COMMAND; + + opcode, param1, param2, r1, r2, r3, + a, b, label, opLD, opST, opSTC: INTEGER; + +BEGIN + IF szWord = 8 THEN + opLD := opLDD; + opST := opSTD; + opSTC := opSTDC + ELSE + opLD := opLDW; + opST := opSTW; + opSTC := opSTWC + END; + + cmd := IL.codes.commands.first(IL.COMMAND); + + WHILE cmd # NIL DO + + param1 := cmd.param1; + param2 := cmd.param2; + opcode := cmd.opcode; + + CASE opcode OF + + |IL.opJMP: + Emit(opJMP, param1, 0) + + |IL.opLABEL: + Emit(opLABEL, param1, 0) + + |IL.opCALL: + Emit(opCALL, param1, 0) + + |IL.opCALLP: + UnOp(r1); + Emit(opCALLI, r1, 0); + drop; + ASSERT(R.top = -1) + + |IL.opPUSHC: + pushc(param2) + + |IL.opCLEANUP: + IF param2 # 0 THEN + addrc(SP, param2 * szWord) + END + + |IL.opNOP, IL.opAND, IL.opOR: + + |IL.opSADR: + StrAdr(GetAnyReg(), param2) + + |IL.opGADR: + GlobalAdr(GetAnyReg(), param2) + + |IL.opLADR: + param2 := param2 * szWord; + next := cmd.next(IL.COMMAND); + IF ((next.opcode = IL.opSAVE) OR (next.opcode = IL.opSAVEF)) & (szWord = 8) OR (next.opcode = IL.opSAVE64) THEN + UnOp(r1); + Emit(opSTD, BP * 256 + r1, param2); + drop; + cmd := next + ELSIF ((next.opcode = IL.opSAVE) OR (next.opcode = IL.opSAVEF)) & (szWord = 4) OR (next.opcode = IL.opSAVE32) THEN + UnOp(r1); + Emit(opSTW, BP * 256 + r1, param2); + drop; + cmd := next + ELSIF next.opcode = IL.opSAVE16 THEN + UnOp(r1); + Emit(opSTH, BP * 256 + r1, param2); + drop; + cmd := next + ELSIF next.opcode = IL.opSAVE8 THEN + UnOp(r1); + Emit(opSTB, BP * 256 + r1, param2); + drop; + cmd := next + ELSE + Emit(opADDRC, BP * 256 + GetAnyReg(), param2) + END + + |IL.opPARAM: + IF param2 = 1 THEN + UnOp(r1); + push(r1); + drop + ELSE + ASSERT(R.top + 1 <= param2); + PushAll(param2) + END + + |IL.opONERR: + pushc(param2); + Emit(opJMP, param1, 0) + + |IL.opPRECALL: + PushAll(0) + + |IL.opRES, IL.opRESF: + ASSERT(R.top = -1); + GetAcc + + |IL.opENTER: + ASSERT(R.top = -1); + Emit(opLABEL, param1, 0); + Emit(opENTER, param2, 0) + + |IL.opLEAVE, IL.opLEAVER, IL.opLEAVEF: + IF opcode # IL.opLEAVE THEN + UnOp(r1); + IF r1 # ACC THEN + mov(ACC, r1) + END; + drop + END; + + ASSERT(R.top = -1); + + IF param1 > 0 THEN + mov(SP, BP) + END; + + pop(BP); + + Emit(opRET, 0, 0) + + |IL.opLEAVEC: + Emit(opRET, 0, 0) + + |IL.opCONST: + next := cmd.next(IL.COMMAND); + IF (next.opcode = IL.opPARAM) & (next.param2 = 1) THEN + pushc(param2); + cmd := next + ELSE + movrc(GetAnyReg(), param2) + END + + |IL.opDROP: + UnOp(r1); + drop + + |IL.opSAVEC: + UnOp(r1); + Emit(opSTC, r1, param2); + drop + + |IL.opSAVE8C: + UnOp(r1); + Emit(opSTBC, r1, param2 MOD 256); + drop + + |IL.opSAVE16C: + UnOp(r1); + Emit(opSTHC, r1, param2 MOD 65536); + drop + + |IL.opSAVE, IL.opSAVEF: + BinOp(r2, r1); + str(r1, r2); + drop; + drop + + |IL.opSAVE32: + BinOp(r2, r1); + str32(r1, r2); + drop; + drop + + |IL.opSAVE64: + BinOp(r2, r1); + str64(r1, r2); + drop; + drop + + |IL.opSAVEFI: + BinOp(r2, r1); + str(r2, r1); + drop; + drop + + |IL.opSAVE8: + BinOp(r2, r1); + str8(r1, r2); + drop; + drop + + |IL.opSAVE16: + BinOp(r2, r1); + str16(r1, r2); + drop; + drop + + |IL.opGLOAD32: + r1 := GetAnyReg(); + GlobalAdr(r1, param2); + ldr32(r1, r1) + + |IL.opGLOAD64: + r1 := GetAnyReg(); + GlobalAdr(r1, param2); + ldr64(r1, r1) + + |IL.opVADR: + Emit(opLD, BP * 256 + GetAnyReg(), param2 * szWord) + + |IL.opLLOAD32: + Emit(opLDW, BP * 256 + GetAnyReg(), param2 * szWord) + + |IL.opLLOAD64: + Emit(opLDD, BP * 256 + GetAnyReg(), param2 * szWord) + + |IL.opVLOAD32: + r1 := GetAnyReg(); + Emit(opLD, BP * 256 + r1, param2 * szWord); + ldr32(r1, r1) + + |IL.opVLOAD64: + r1 := GetAnyReg(); + Emit(opLDD, BP * 256 + r1, param2 * szWord); + ldr64(r1, r1) + + |IL.opGLOAD16: + r1 := GetAnyReg(); + GlobalAdr(r1, param2); + ldr16(r1, r1) + + |IL.opLLOAD16: + Emit(opLDH, BP * 256 + GetAnyReg(), param2 * szWord) + + |IL.opVLOAD16: + r1 := GetAnyReg(); + Emit(opLD, BP * 256 + r1, param2 * szWord); + ldr16(r1, r1) + + |IL.opGLOAD8: + r1 := GetAnyReg(); + GlobalAdr(r1, param2); + ldr8(r1, r1) + + |IL.opLLOAD8: + Emit(opLDB, BP * 256 + GetAnyReg(), param2 * szWord) + + |IL.opVLOAD8: + r1 := GetAnyReg(); + Emit(opLD, BP * 256 + r1, param2 * szWord); + ldr8(r1, r1) + + |IL.opLOAD8: + UnOp(r1); + ldr8(r1, r1) + + |IL.opLOAD16: + UnOp(r1); + ldr16(r1, r1) + + |IL.opLOAD32: + UnOp(r1); + ldr32(r1, r1) + + |IL.opLOAD64: + UnOp(r1); + ldr64(r1, r1) + + |IL.opLOADF: + UnOp(r1); + ldr(r1, r1) + + |IL.opUMINUS: + UnOp(r1); + Emit(opNEG, r1, 0) + + |IL.opADD: + BinOp(r1, r2); + add(r1, r2); + drop + + |IL.opSUB: + BinOp(r1, r2); + sub(r1, r2); + drop + + |IL.opADDC: + UnOp(r1); + next := cmd.next(IL.COMMAND); + CASE next.opcode OF + |IL.opLOADF: + Emit(opLD, r1 * 256 + r1, param2); + cmd := next + |IL.opLOAD64: + Emit(opLDD, r1 * 256 + r1, param2); + cmd := next + |IL.opLOAD32: + Emit(opLDW, r1 * 256 + r1, param2); + cmd := next + |IL.opLOAD16: + Emit(opLDH, r1 * 256 + r1, param2); + cmd := next + |IL.opLOAD8: + Emit(opLDB, r1 * 256 + r1, param2); + cmd := next + ELSE + addrc(r1, param2) + END + + |IL.opSUBR: + UnOp(r1); + subrc(r1, param2) + + |IL.opSUBL: + UnOp(r1); + subrc(r1, param2); + Emit(opNEG, r1, 0) + + |IL.opMULC: + UnOp(r1); + Emit(opMULC, r1, param2) + + |IL.opMUL: + BinOp(r1, r2); + Emit(opMUL, r1, r2); + drop + + |IL.opDIV: + BinOp(r1, r2); + Emit(opDIV, r1, r2); + drop + + |IL.opMOD: + BinOp(r1, r2); + Emit(opMOD, r1, r2); + drop + + |IL.opDIVR: + UnOp(r1); + Emit(opDIVC, r1, param2) + + |IL.opMODR: + UnOp(r1); + Emit(opMODC, r1, param2) + + |IL.opDIVL: + UnOp(r1); + r2 := GetAnyReg(); + movrc(r2, param2); + Emit(opDIV, r2, r1); + mov(r1, r2); + drop + + |IL.opMODL: + UnOp(r1); + r2 := GetAnyReg(); + movrc(r2, param2); + Emit(opMOD, r2, r1); + mov(r1, r2); + drop + + |IL.opEQ .. IL.opGE, IL.opEQC .. IL.opGEC: + IF (IL.opEQ <= opcode) & (opcode <= IL.opGE) THEN + BinOp(r1, r2); + Emit(opCMP, r1, r2); + drop + ELSE + UnOp(r1); + Emit(opCMPC, r1, param2) + END; + next := cmd.next(IL.COMMAND); + IF next.opcode = IL.opJZ THEN + Emit(ORD(BITS(jcc(opcode)) / {0}), next.param1, 0); + cmd := next; + drop + ELSIF next.opcode = IL.opJNZ THEN + Emit(jcc(opcode), next.param1, 0); + cmd := next; + drop + ELSE + Emit(jcc(opcode) + 6, r1, 0) + END + + |IL.opJNZ1: + UnOp(r1); + jnz(r1, param1) + + |IL.opJG: + UnOp(r1); + Emit(opCMPC, r1, 0); + Emit(opJGT, param1, 0) + + |IL.opJNZ: + UnOp(r1); + jnz(r1, param1); + drop + + |IL.opJZ: + UnOp(r1); + Emit(opCMPC, r1, 0); + Emit(opJEQ, param1, 0); + drop + + |IL.opMULS: + BinOp(r1, r2); + Emit(opAND, r1, r2); + drop + + |IL.opMULSC: + UnOp(r1); + Emit(opANDC, r1, param2) + + |IL.opDIVS: + BinOp(r1, r2); + Emit(opXOR, r1, r2); + drop + + |IL.opDIVSC: + UnOp(r1); + Emit(opXORC, r1, param2) + + |IL.opADDS: + BinOp(r1, r2); + Emit(opOR, r1, r2); + drop + + |IL.opSUBS: + BinOp(r1, r2); + Emit(opNOT, r2, 0); + Emit(opAND, r1, r2); + drop + + |IL.opADDSC: + UnOp(r1); + Emit(opORC, r1, param2) + + |IL.opSUBSL: + UnOp(r1); + Emit(opNOT, r1, 0); + Emit(opANDC, r1, param2) + + |IL.opSUBSR: + UnOp(r1); + Emit(opANDC, r1, ORD(-BITS(param2))) + + |IL.opUMINS: + UnOp(r1); + Emit(opNOT, r1, 0) + + |IL.opASR: + shift(opASR) + + |IL.opLSL: + shift(opLSL) + + |IL.opROR: + shift(opROR) + + |IL.opLSR: + shift(opLSR) + + |IL.opASR1: + shift1(opASR, param2) + + |IL.opLSL1: + shift1(opLSL, param2) + + |IL.opROR1: + shift1(opROR, param2) + + |IL.opLSR1: + shift1(opLSR, param2) + + |IL.opASR2: + UnOp(r1); + Emit(opASRC, r1, param2 MOD (szWord * 8)) + + |IL.opLSL2: + UnOp(r1); + Emit(opLSLC, r1, param2 MOD (szWord * 8)) + + |IL.opROR2: + UnOp(r1); + Emit(opRORC, r1, param2 MOD (szWord * 8)) + + |IL.opLSR2: + UnOp(r1); + Emit(opLSRC, r1, param2 MOD (szWord * 8)) + + |IL.opCHR: + UnOp(r1); + Emit(opANDC, r1, 255) + + |IL.opWCHR: + UnOp(r1); + Emit(opANDC, r1, 65535) + + |IL.opABS: + UnOp(r1); + Emit(opCMPC, r1, 0); + label := IL.NewLabel(); + Emit(opJGE, label, 0); + Emit(opNEG, r1, 0); + Emit(opLABEL, label, 0) + + |IL.opLEN: + UnOp(r1); + drop; + EXCL(R.regs, r1); + + WHILE param2 > 0 DO + UnOp(r2); + drop; + DEC(param2) + END; + + INCL(R.regs, r1); + ASSERT(REG.GetReg(R, r1)) + + |IL.opSWITCH: + UnOp(r1); + IF param2 = 0 THEN + r2 := ACC + ELSE + r2 := R1 + END; + IF r1 # r2 THEN + ASSERT(REG.GetReg(R, r2)); + ASSERT(REG.Exchange(R, r1, r2)); + drop + END; + drop + + |IL.opENDSW: + + |IL.opCASEL: + Emit(opCMPC, ACC, param1); + Emit(opJLT, param2, 0) + + |IL.opCASER: + Emit(opCMPC, ACC, param1); + Emit(opJGT, param2, 0) + + |IL.opCASELR: + Emit(opCMPC, ACC, param1); + IF param2 = cmd.param3 THEN + Emit(opJNE, param2, 0) + ELSE + Emit(opJLT, param2, 0); + Emit(opJGT, cmd.param3, 0) + END + + |IL.opSBOOL: + BinOp(r2, r1); + Emit(opCMPC, r2, 0); + Emit(opSNE, r2, 0); + str8(r1, r2); + drop; + drop + + |IL.opSBOOLC: + UnOp(r1); + Emit(opSTBC, r1, ORD(param2 # 0)); + drop + + |IL.opINCC: + UnOp(r1); + r2 := GetAnyReg(); + ldr(r2, r1); + addrc(r2, param2); + str(r1, r2); + drop; + drop + + |IL.opINCCB, IL.opDECCB: + IF opcode = IL.opDECCB THEN + param2 := -param2 + END; + UnOp(r1); + r2 := GetAnyReg(); + ldr8(r2, r1); + addrc(r2, param2); + str8(r1, r2); + drop; + drop + + |IL.opINCB, IL.opDECB: + BinOp(r2, r1); + r3 := GetAnyReg(); + ldr8(r3, r1); + IF opcode = IL.opINCB THEN + add(r3, r2) + ELSE + sub(r3, r2) + END; + str8(r1, r3); + drop; + drop; + drop + + |IL.opINC, IL.opDEC: + BinOp(r2, r1); + r3 := GetAnyReg(); + ldr(r3, r1); + IF opcode = IL.opINC THEN + add(r3, r2) + ELSE + sub(r3, r2) + END; + str(r1, r3); + drop; + drop; + drop + + |IL.opINCL, IL.opEXCL: + BinOp(r2, r1); + Emit(opBIT, r2, r2); + r3 := GetAnyReg(); + ldr(r3, r1); + IF opcode = IL.opINCL THEN + Emit(opOR, r3, r2) + ELSE + Emit(opNOT, r2, 0); + Emit(opAND, r3, r2) + END; + str(r1, r3); + drop; + drop; + drop + + |IL.opINCLC, IL.opEXCLC: + UnOp(r1); + r2 := GetAnyReg(); + ldr(r2, r1); + IF opcode = IL.opINCLC THEN + Emit(opORC, r2, ORD({param2})) + ELSE + Emit(opANDC, r2, ORD(-{param2})) + END; + str(r1, r2); + drop; + drop + + |IL.opEQB, IL.opNEB: + BinOp(r1, r2); + Emit(opCMPC, r1, 0); + Emit(opSNE, r1, 0); + Emit(opCMPC, r2, 0); + Emit(opSNE, r2, 0); + Emit(opCMP, r1, r2); + IF opcode = IL.opEQB THEN + Emit(opSEQ, r1, 0) + ELSE + Emit(opSNE, r1, 0) + END; + drop + + |IL.opCHKBYTE: + BinOp(r1, r2); + Emit(opCMPC, r1, 256); + Emit(opJBT, param1, 0) + + |IL.opCHKIDX: + UnOp(r1); + Emit(opCMPC, r1, param2); + Emit(opJBT, param1, 0) + + |IL.opCHKIDX2: + BinOp(r1, r2); + IF param2 # -1 THEN + Emit(opCMP, r2, r1); + Emit(opJBT, param1, 0) + END; + INCL(R.regs, r1); + DEC(R.top); + R.stk[R.top] := r2 + + |IL.opEQP, IL.opNEP: + ProcAdr(GetAnyReg(), param1); + BinOp(r1, r2); + Emit(opCMP, r1, r2); + IF opcode = IL.opEQP THEN + Emit(opSEQ, r1, 0) + ELSE + Emit(opSNE, r1, 0) + END; + drop + + |IL.opSAVEP: + UnOp(r1); + r2 := GetAnyReg(); + ProcAdr(r2, param2); + str(r1, r2); + drop; + drop + + |IL.opPUSHP: + ProcAdr(GetAnyReg(), param2) + + |IL.opPUSHT: + UnOp(r1); + Emit(opLD, r1 * 256 + GetAnyReg(), -szWord) + + |IL.opGET, IL.opGETC: + IF opcode = IL.opGET THEN + BinOp(r1, r2) + ELSIF opcode = IL.opGETC THEN + UnOp(r2); + r1 := GetAnyReg(); + movrc(r1, param1) + END; + drop; + drop; + + CASE param2 OF + |1: ldr8(r1, r1); str8(r2, r1) + |2: ldr16(r1, r1); str16(r2, r1) + |4: ldr32(r1, r1); str32(r2, r1) + |8: ldr64(r1, r1); str64(r2, r1) + END + + |IL.opNOT: + UnOp(r1); + Emit(opCMPC, r1, 0); + Emit(opSEQ, r1, 0) + + |IL.opORD: + UnOp(r1); + Emit(opCMPC, r1, 0); + Emit(opSNE, r1, 0) + + |IL.opMIN, IL.opMAX: + BinOp(r1, r2); + Emit(opCMP, r1, r2); + label := IL.NewLabel(); + IF opcode = IL.opMIN THEN + Emit(opJLE, label, 0) + ELSE + Emit(opJGE, label, 0) + END; + Emit(opMOV, r1, r2); + Emit(opLABEL, label, 0); + drop + + |IL.opMINC, IL.opMAXC: + UnOp(r1); + Emit(opCMPC, r1, param2); + label := IL.NewLabel(); + IF opcode = IL.opMINC THEN + Emit(opJLE, label, 0) + ELSE + Emit(opJGE, label, 0) + END; + Emit(opMOVC, r1, param2); + Emit(opLABEL, label, 0) + + |IL.opIN: + BinOp(r1, r2); + Emit(opBIT, r1, r1); + Emit(opAND, r1, r2); + Emit(opCMPC, r1, 0); + Emit(opSNE, r1, 0); + drop + + |IL.opINL: + UnOp(r1); + Emit(opANDC, r1, ORD({param2})); + Emit(opCMPC, r1, 0); + Emit(opSNE, r1, 0) + + |IL.opINR: + UnOp(r1); + Emit(opBIT, r1, r1); + Emit(opANDC, r1, param2); + Emit(opCMPC, r1, 0); + Emit(opSNE, r1, 0) + + |IL.opERR: + CallRTL(IL._error, 4) + + |IL.opEQS .. IL.opGES: + PushAll(4); + pushc(opcode - IL.opEQS); + CallRTL(IL._strcmp, 5); + GetAcc + + |IL.opEQSW .. IL.opGESW: + PushAll(4); + pushc(opcode - IL.opEQSW); + CallRTL(IL._strcmpw, 5); + GetAcc + + |IL.opCOPY: + PushAll(2); + pushc(param2); + CallRTL(IL._move, 3) + + |IL.opMOVE: + PushAll(3); + CallRTL(IL._move, 3) + + |IL.opCOPYA: + PushAll(4); + pushc(param2); + CallRTL(IL._arrcpy, 5); + GetAcc + + |IL.opCOPYS: + PushAll(4); + pushc(param2); + CallRTL(IL._strcpy, 5) + + |IL.opROT: + PushAll(0); + mov(ACC, SP); + push(ACC); + pushc(param2); + CallRTL(IL._rot, 2) + + |IL.opLENGTH: + PushAll(2); + CallRTL(IL._length, 2); + GetAcc + + |IL.opLENGTHW: + PushAll(2); + CallRTL(IL._lengthw, 2); + GetAcc + + |IL.opSAVES: + UnOp(r2); + REG.PushAll_1(R); + r1 := GetAnyReg(); + StrAdr(r1, param2); + push(r1); + drop; + push(r2); + drop; + pushc(param1); + CallRTL(IL._move, 3) + + |IL.opRSET: + PushAll(2); + CallRTL(IL._set, 2); + GetAcc + + |IL.opRSETR: + PushAll(1); + pushc(param2); + CallRTL(IL._set, 2); + GetAcc + + |IL.opRSETL: + UnOp(r1); + REG.PushAll_1(R); + pushc(param2); + push(r1); + drop; + CallRTL(IL._set, 2); + GetAcc + + |IL.opRSET1: + PushAll(1); + CallRTL(IL._set1, 1); + GetAcc + + |IL.opNEW: + PushAll(1); + INC(param2, szWord); + ASSERT(UTILS.Align(param2, szWord)); + pushc(param2); + pushc(param1); + CallRTL(IL._new, 3) + + |IL.opTYPEGP: + UnOp(r1); + PushAll(0); + push(r1); + pushc(param2); + CallRTL(IL._guard, 2); + GetAcc + + |IL.opIS: + PushAll(1); + pushc(param2); + CallRTL(IL._is, 2); + GetAcc + + |IL.opISREC: + PushAll(2); + pushc(param2); + CallRTL(IL._guardrec, 3); + GetAcc + + |IL.opTYPEGR: + PushAll(1); + pushc(param2); + CallRTL(IL._guardrec, 2); + GetAcc + + |IL.opTYPEGD: + UnOp(r1); + PushAll(0); + subrc(r1, szWord); + ldr(r1, r1); + push(r1); + pushc(param2); + CallRTL(IL._guardrec, 2); + GetAcc + + |IL.opCASET: + push(R1); + push(R1); + pushc(param2); + CallRTL(IL._guardrec, 2); + pop(R1); + jnz(ACC, param1) + + |IL.opCONSTF: + IF szWord = 8 THEN + movrc(GetAnyReg(), UTILS.splitf(cmd.float, a, b)) + ELSE (* szWord = 4 *) + movrc(GetAnyReg(), UTILS.d2s(cmd.float)) + END + + |IL.opMULF: + PushAll(2); + CallRTL(IL._fmul, 2); + GetAcc + + |IL.opDIVF: + PushAll(2); + CallRTL(IL._fdiv, 2); + GetAcc + + |IL.opDIVFI: + PushAll(2); + CallRTL(IL._fdivi, 2); + GetAcc + + |IL.opADDF: + PushAll(2); + CallRTL(IL._fadd, 2); + GetAcc + + |IL.opSUBFI: + PushAll(2); + CallRTL(IL._fsubi, 2); + GetAcc + + |IL.opSUBF: + PushAll(2); + CallRTL(IL._fsub, 2); + GetAcc + + |IL.opEQF..IL.opGEF: + PushAll(2); + pushc(opcode - IL.opEQF); + CallRTL(IL._fcmp, 3); + GetAcc + + |IL.opFLOOR: + PushAll(1); + CallRTL(IL._floor, 1); + GetAcc + + |IL.opFLT: + PushAll(1); + CallRTL(IL._flt, 1); + GetAcc + + |IL.opUMINF: + UnOp(r1); + Emit(opRORC, r1, -1); + Emit(opXORC, r1, 1); + Emit(opRORC, r1, 1) + + |IL.opFABS: + UnOp(r1); + Emit(opLSLC, r1, 1); + Emit(opLSRC, r1, 1) + + |IL.opINF: + r1 := GetAnyReg(); + Emit(opMOVC, r1, 1); + Emit(opRORC, r1, 1); + Emit(opASRC, r1, 7 + 3 * ORD(szWord = 8)); + Emit(opLSRC, r1, 1) + + |IL.opPUSHF: + UnOp(r1); + push(r1); + drop + + |IL.opPACK: + PushAll(2); + CallRTL(IL._pack, 2) + + |IL.opPACKC: + PushAll(1); + pushc(param2); + CallRTL(IL._pack, 2) + + |IL.opUNPK: + PushAll(2); + CallRTL(IL._unpk, 2) + + |IL.opCODE: + OutInt(param2) + + |IL.opLADR_SAVE: + UnOp(r1); + Emit(opST, BP * 256 + r1, param2 * szWord); + drop + + |IL.opLADR_INCC: + r1 := GetAnyReg(); + Emit(opLD, BP * 256 + r1, param1 * szWord); + Emit(opADDC, r1, param2); + Emit(opST, BP * 256 + r1, param1 * szWord); + drop + + END; + + cmd := cmd.next(IL.COMMAND) + END; + + ASSERT(R.pushed = 0); + ASSERT(R.top = -1) +END translate; + + +PROCEDURE prolog; +BEGIN + Emit(opLEA, SP + LStack * 256, 0); + Emit(opLEA, ACC + LTypes * 256, 0); + push(ACC); + Emit(opLEA, ACC + LHeap * 256, 0); + push(ACC); + pushc(CHL.Length(IL.codes.types)); + CallRTL(IL._init, 3) +END prolog; + + +PROCEDURE epilog (ram, szWord: INTEGER); +VAR + tcount, dcount, i, offTypes, offStrings, + szData, szGlobal, szHeapStack: INTEGER; + +BEGIN + Emit(opSTOP, 0, 0); + + offTypes := count; + + tcount := CHL.Length(IL.codes.types); + FOR i := 0 TO tcount - 1 DO + OutInt(CHL.GetInt(IL.codes.types, i)) + END; + + offStrings := count; + dcount := CHL.Length(IL.codes.data); + FOR i := 0 TO dcount - 1 DO + OutByte(CHL.GetByte(IL.codes.data, i)) + END; + + IF dcount MOD szWord # 0 THEN + i := szWord - dcount MOD szWord; + WHILE i > 0 DO + OutByte(0); + DEC(i) + END + END; + + szData := count - offTypes; + szGlobal := (IL.codes.bss DIV szWord + 1) * szWord; + szHeapStack := ram - szData - szGlobal; + + OutInt(offTypes); + OutInt(offStrings); + OutInt(szGlobal DIV szWord); + OutInt(szHeapStack DIV szWord); + FOR i := 1 TO 8 DO + OutInt(0) + END +END epilog; + + +PROCEDURE CodeGen* (outname: ARRAY OF CHAR; target: INTEGER; options: PROG.OPTIONS); +CONST + minRAM = 32*1024; + maxRAM = 256*1024; + +VAR + szData, szRAM: INTEGER; + +BEGIN + szWord := TARGETS.WordSize; + IF szWord = 8 THEN + ldr := ldr64; + str := str64 + ELSE + ldr := ldr32; + str := str32 + END; + szData := (CHL.Length(IL.codes.types) + CHL.Length(IL.codes.data) DIV szWord + IL.codes.bss DIV szWord + 2) * szWord; + szRAM := MIN(MAX(options.ram, minRAM), maxRAM) * 1024; + + IF szRAM - szData < 1024*1024 THEN + ERRORS.Error(208) + END; + + count := 0; + WR.Create(outname); + + REG.Init(R, push, pop, mov, xchg, GPRs); + + prolog; + translate(szWord); + epilog(szRAM, szWord); + + WR.Close +END CodeGen; + + +END RVMxI. \ No newline at end of file diff --git a/programs/develop/oberon07/Source/SCAN.ob07 b/programs/develop/oberon07/source/SCAN.ob07 similarity index 65% rename from programs/develop/oberon07/Source/SCAN.ob07 rename to programs/develop/oberon07/source/SCAN.ob07 index c1c95571ff..f32cf45f4c 100644 --- a/programs/develop/oberon07/Source/SCAN.ob07 +++ b/programs/develop/oberon07/source/SCAN.ob07 @@ -1,18 +1,20 @@ (* BSD 2-Clause License - Copyright (c) 2018-2020, Anton Krotov + Copyright (c) 2018-2021, Anton Krotov All rights reserved. *) MODULE SCAN; -IMPORT TXT := TEXTDRV, AVL := AVLTREES, ARITH, S := STRINGS, ERRORS, LISTS; +IMPORT TXT := TEXTDRV, ARITH, S := STRINGS, ERRORS, LISTS; CONST - LEXLEN = 1024; + NUMLEN = 256; + IDLEN = 256; + TEXTLEN = 512; lxUNDEF* = 0; lxIDENT* = 1; lxINTEGER* = 2; lxHEX* = 3; lxCHAR* = 4; lxFLOAT* = 5; lxSTRING* = 6; lxCOMMENT* = 7; @@ -39,26 +41,33 @@ CONST lxWHILE* = 83; lxERROR01* = -1; lxERROR02* = -2; lxERROR03* = -3; lxERROR04* = -4; - lxERROR05* = -5; lxERROR06* = -6; lxERROR07* = -7; lxERROR08* = -8; + lxERROR05* = -5; (*lxERROR06* = -6;*) lxERROR07* = -7; lxERROR08* = -8; lxERROR09* = -9; lxERROR10* = -10; lxERROR11* = -11; lxERROR12* = -12; lxERROR13* = -13; TYPE - LEXSTR* = ARRAY LEXLEN OF CHAR; + TEXTSTR* = ARRAY TEXTLEN OF CHAR; + IDSTR* = ARRAY IDLEN OF CHAR; DEF = POINTER TO RECORD (LISTS.ITEM) - ident: LEXSTR + ident: IDSTR END; - IDENT* = POINTER TO RECORD (AVL.DATA) + STRING* = POINTER TO RECORD (LISTS.ITEM) - s*: LEXSTR; - offset*, offsetW*: INTEGER; - key: INTEGER + s*: TEXTSTR; + offset*, offsetW*, hash: INTEGER + + END; + + IDENT* = RECORD + + s*: IDSTR; + hash*: INTEGER END; @@ -70,70 +79,89 @@ TYPE LEX* = RECORD - s*: LEXSTR; - length*: INTEGER; sym*: INTEGER; pos*: POSITION; ident*: IDENT; - string*: IDENT; + string*: STRING; value*: ARITH.VALUE; - error*: INTEGER; - - over: BOOLEAN + error*: INTEGER END; SCANNER* = TXT.TEXT; + KEYWORD = ARRAY 10 OF CHAR; + VAR - idents: AVL.NODE; - delimiters: ARRAY 256 OF BOOLEAN; - NewIdent: IDENT; - upto, LowerCase, _if: BOOLEAN; - def: LISTS.LIST; + strings, def: LISTS.LIST; + + KW: ARRAY 33 OF RECORD upper, lower: KEYWORD; uhash, lhash: INTEGER END; -PROCEDURE nodecmp (a, b: AVL.DATA): INTEGER; - RETURN ORD(a(IDENT).s > b(IDENT).s) - ORD(a(IDENT).s < b(IDENT).s) -END nodecmp; +PROCEDURE enterKW (s: KEYWORD; idx: INTEGER); +BEGIN + KW[idx].lower := s; + KW[idx].upper := s; + S.UpCase(KW[idx].upper); + KW[idx].uhash := S.HashStr(KW[idx].upper); + KW[idx].lhash := S.HashStr(KW[idx].lower); +END enterKW; -PROCEDURE enterid* (s: LEXSTR): IDENT; +PROCEDURE checkKW (ident: IDENT): INTEGER; VAR - newnode: BOOLEAN; - node: AVL.NODE; + i, res: INTEGER; BEGIN - NewIdent.s := s; - idents := AVL.insert(idents, NewIdent, nodecmp, newnode, node); - - IF newnode THEN - NEW(NewIdent); - NewIdent.offset := -1; - NewIdent.offsetW := -1; - NewIdent.key := 0 + res := lxIDENT; + i := 0; + WHILE i < LEN(KW) DO + IF (KW[i].uhash = ident.hash) & (KW[i].upper = ident.s) + OR LowerCase & (KW[i].lhash = ident.hash) & (KW[i].lower = ident.s) THEN + res := i + lxKW; + i := LEN(KW) + END; + INC(i) END - RETURN node.data(IDENT) -END enterid; + RETURN res +END checkKW; -PROCEDURE putchar (VAR lex: LEX; c: CHAR); +PROCEDURE enterStr* (s: TEXTSTR): STRING; +VAR + str, res: STRING; + hash: INTEGER; + BEGIN - IF lex.length < LEXLEN - 1 THEN - lex.s[lex.length] := c; - INC(lex.length); - lex.s[lex.length] := 0X - ELSE - lex.over := TRUE + hash := S.HashStr(s); + str := strings.first(STRING); + res := NIL; + WHILE str # NIL DO + IF (str.hash = hash) & (str.s = s) THEN + res := str; + str := NIL + ELSE + str := str.next(STRING) + END + END; + IF res = NIL THEN + NEW(res); + res.s := s; + res.offset := -1; + res.offsetW := -1; + res.hash := hash; + LISTS.push(strings, res) END -END putchar; + + RETURN res +END enterStr; PROCEDURE nextc (text: TXT.TEXT): CHAR; @@ -143,66 +171,92 @@ BEGIN END nextc; +PROCEDURE setIdent* (VAR ident: IDENT; s: IDSTR); +BEGIN + ident.s := s; + ident.hash := S.HashStr(s) +END setIdent; + + PROCEDURE ident (text: TXT.TEXT; VAR lex: LEX); VAR c: CHAR; + i: INTEGER; BEGIN c := text.peak; ASSERT(S.letter(c)); - WHILE S.letter(c) OR S.digit(c) DO - putchar(lex, c); + i := 0; + WHILE (i < IDLEN - 1) & (S.letter(c) OR S.digit(c)) DO + lex.ident.s[i] := c; + INC(i); c := nextc(text) END; - IF lex.over THEN - lex.sym := lxERROR06 - ELSE - lex.ident := enterid(lex.s); - IF lex.ident.key # 0 THEN - lex.sym := lex.ident.key - ELSE - lex.sym := lxIDENT + lex.ident.s[i] := 0X; + lex.ident.hash := S.HashStr(lex.ident.s); + lex.sym := checkKW(lex.ident); + + IF S.letter(c) OR S.digit(c) THEN + ERRORS.WarningMsg(lex.pos.line, lex.pos.col, 2); + WHILE S.letter(c) OR S.digit(c) DO + c := nextc(text) END END - END ident; PROCEDURE number (text: TXT.TEXT; VAR lex: LEX); +TYPE + NUMSTR = ARRAY NUMLEN OF CHAR; + VAR c: CHAR; hex: BOOLEAN; - error, sym: INTEGER; + error, sym, i: INTEGER; + num: NUMSTR; + + + PROCEDURE push (VAR num: NUMSTR; VAR i: INTEGER; c: CHAR); + BEGIN + IF i < NUMLEN - 1 THEN + num[i] := c; + INC(i) + END + END push; + BEGIN c := text.peak; ASSERT(S.digit(c)); + i := 0; + error := 0; sym := lxINTEGER; hex := FALSE; WHILE S.digit(c) DO - putchar(lex, c); + push(num, i, c); c := nextc(text) END; - WHILE S.hexdigit(c) DO - putchar(lex, c); + WHILE S.hexdigit(c) OR LowerCase & ("a" <= c) & (c <= "f") DO + S.cap(c); + push(num, i, c); c := nextc(text); hex := TRUE END; - IF c = "H" THEN - putchar(lex, c); + IF (c = "H") OR LowerCase & (c = "h") THEN + push(num, i, c); TXT.next(text); sym := lxHEX - ELSIF c = "X" THEN - putchar(lex, c); + ELSIF (c = "X") OR LowerCase & (c = "x") THEN + push(num, i, c); TXT.next(text); sym := lxCHAR @@ -215,7 +269,7 @@ BEGIN c := nextc(text); IF c # "." THEN - putchar(lex, "."); + push(num, i, "."); sym := lxFLOAT ELSE sym := lxINTEGER; @@ -224,22 +278,22 @@ BEGIN END; WHILE S.digit(c) DO - putchar(lex, c); + push(num, i, c); c := nextc(text) END; - IF c = "E" THEN + IF (c = "E") OR LowerCase & (c = "e") THEN - putchar(lex, c); + push(num, i, c); c := nextc(text); IF (c = "+") OR (c = "-") THEN - putchar(lex, c); + push(num, i, c); c := nextc(text) END; IF S.digit(c) THEN WHILE S.digit(c) DO - putchar(lex, c); + push(num, i, c); c := nextc(text) END ELSE @@ -255,16 +309,18 @@ BEGIN END; - IF lex.over & (sym >= 0) THEN + IF (i = NUMLEN - 1) & (sym >= 0) THEN sym := lxERROR07 END; + num[i] := 0X; + IF sym = lxINTEGER THEN - ARITH.iconv(lex.s, lex.value, error) + ARITH.iconv(num, lex.value, error) ELSIF (sym = lxHEX) OR (sym = lxCHAR) THEN - ARITH.hconv(lex.s, lex.value, error) + ARITH.hconv(num, lex.value, error) ELSIF sym = lxFLOAT THEN - ARITH.fconv(lex.s, lex.value, error) + ARITH.fconv(num, lex.value, error) END; CASE error OF @@ -283,36 +339,39 @@ END number; PROCEDURE string (text: TXT.TEXT; VAR lex: LEX; quot: CHAR); VAR c: CHAR; - n: INTEGER; + i: INTEGER; + str: TEXTSTR; BEGIN c := nextc(text); - n := 0; - WHILE (c # quot) & (c # 0X) & ~text.eol & ~text.eof DO - putchar(lex, c); + i := 0; + WHILE (i < LEN(str) - 1) & (c # quot) & (c # 0X) & ~text.eol & ~text.eof DO + str[i] := c; c := nextc(text); - INC(n) + INC(i) + END; + + str[i] := 0X; + + IF (i = LEN(str) - 1) & (c # quot) & (c # 0X) & ~text.eol & ~text.eof THEN + lex.sym := lxERROR05 END; IF c = quot THEN TXT.next(text); - IF lex.over THEN - lex.sym := lxERROR05 + IF i # 1 THEN + lex.sym := lxSTRING ELSE - IF n # 1 THEN - lex.sym := lxSTRING - ELSE - lex.sym := lxCHAR; - ARITH.setChar(lex.value, ORD(lex.s[0])) - END + lex.sym := lxCHAR; + ARITH.setChar(lex.value, ORD(str[0])) END - ELSE + ELSIF lex.sym # lxERROR05 THEN lex.sym := lxERROR03 END; IF lex.sym = lxSTRING THEN - lex.string := enterid(lex.s); + lex.string := enterStr(str); lex.value.typ := ARITH.tSTRING; lex.value.string := lex.string END @@ -357,15 +416,16 @@ BEGIN END comment; -PROCEDURE delimiter (text: TXT.TEXT; VAR lex: LEX; c: CHAR); +PROCEDURE delimiter (text: TXT.TEXT; c: CHAR): INTEGER; VAR sym: INTEGER; + c0: CHAR; BEGIN - putchar(lex, c); + c0 := c; c := nextc(text); - CASE lex.s[0] OF + CASE c0 OF |"+": sym := lxPLUS @@ -396,7 +456,6 @@ BEGIN IF c = "." THEN sym := lxRANGE; - putchar(lex, c); TXT.next(text) END @@ -438,7 +497,6 @@ BEGIN IF c = "=" THEN sym := lxLE; - putchar(lex, c); TXT.next(text) END @@ -447,7 +505,6 @@ BEGIN IF c = "=" THEN sym := lxGE; - putchar(lex, c); TXT.next(text) END @@ -456,7 +513,6 @@ BEGIN IF c = "=" THEN sym := lxASSIGN; - putchar(lex, c); TXT.next(text) END @@ -469,10 +525,9 @@ BEGIN |"}": sym := lxRCURLY - END; - - lex.sym := sym + END + RETURN sym END delimiter; @@ -538,7 +593,7 @@ VAR check(lex.sym = lxIDENT, text, lex, 22); REPEAT - IF IsDef(lex.s) THEN + IF IsDef(lex.ident.s) THEN skip := FALSE END; @@ -590,12 +645,8 @@ BEGIN c := nextc(text) END; - lex.s[0] := 0X; - lex.length := 0; lex.pos.line := text.line; lex.pos.col := text.col; - lex.ident := NIL; - lex.over := FALSE; IF S.letter(c) THEN ident(text, lex) @@ -604,7 +655,7 @@ BEGIN ELSIF (c = '"') OR (c = "'") THEN string(text, lex, c) ELSIF delimiters[ORD(c)] THEN - delimiter(text, lex, c) + lex.sym := delimiter(text, c) ELSIF c = "$" THEN IF S.letter(nextc(text)) THEN ident(text, lex); @@ -631,12 +682,9 @@ BEGIN ELSIF (c = 7FX) & upto THEN upto := FALSE; lex.sym := lxRANGE; - putchar(lex, "."); - putchar(lex, "."); DEC(lex.pos.col); TXT.next(text) ELSE - putchar(lex, c); TXT.next(text); lex.sym := lxERROR04 END; @@ -668,24 +716,6 @@ VAR i: INTEGER; delim: ARRAY 23 OF CHAR; - - PROCEDURE enterkw (key: INTEGER; kw: LEXSTR); - VAR - id: IDENT; - upper: LEXSTR; - - BEGIN - IF LowerCase THEN - id := enterid(kw); - id.key := key - END; - upper := kw; - S.UpCase(upper); - id := enterid(upper); - id.key := key - END enterkw; - - BEGIN upto := FALSE; LowerCase := lower; @@ -700,48 +730,39 @@ BEGIN delimiters[ORD(delim[i])] := TRUE END; - NEW(NewIdent); - NewIdent.s := ""; - NewIdent.offset := -1; - NewIdent.offsetW := -1; - NewIdent.key := 0; - - idents := NIL; - - enterkw(lxARRAY, "array"); - enterkw(lxBEGIN, "begin"); - enterkw(lxBY, "by"); - enterkw(lxCASE, "case"); - enterkw(lxCONST, "const"); - enterkw(lxDIV, "div"); - enterkw(lxDO, "do"); - enterkw(lxELSE, "else"); - enterkw(lxELSIF, "elsif"); - enterkw(lxEND, "end"); - enterkw(lxFALSE, "false"); - enterkw(lxFOR, "for"); - enterkw(lxIF, "if"); - enterkw(lxIMPORT, "import"); - enterkw(lxIN, "in"); - enterkw(lxIS, "is"); - enterkw(lxMOD, "mod"); - enterkw(lxMODULE, "module"); - enterkw(lxNIL, "nil"); - enterkw(lxOF, "of"); - enterkw(lxOR, "or"); - enterkw(lxPOINTER, "pointer"); - enterkw(lxPROCEDURE, "procedure"); - enterkw(lxRECORD, "record"); - enterkw(lxREPEAT, "repeat"); - enterkw(lxRETURN, "return"); - enterkw(lxTHEN, "then"); - enterkw(lxTO, "to"); - enterkw(lxTRUE, "true"); - enterkw(lxTYPE, "type"); - enterkw(lxUNTIL, "until"); - enterkw(lxVAR, "var"); - enterkw(lxWHILE, "while") - + enterKW("array", 0); + enterKW("begin", 1); + enterKW("by", 2); + enterKW("case", 3); + enterKW("const", 4); + enterKW("div", 5); + enterKW("do", 6); + enterKW("else", 7); + enterKW("elsif", 8); + enterKW("end", 9); + enterKW("false", 10); + enterKW("for", 11); + enterKW("if", 12); + enterKW("import", 13); + enterKW("in", 14); + enterKW("is", 15); + enterKW("mod", 16); + enterKW("module", 17); + enterKW("nil", 18); + enterKW("of", 19); + enterKW("or", 20); + enterKW("pointer", 21); + enterKW("procedure", 22); + enterKW("record", 23); + enterKW("repeat", 24); + enterKW("return", 25); + enterKW("then", 26); + enterKW("to", 27); + enterKW("true", 28); + enterKW("type", 29); + enterKW("until", 30); + enterKW("var", 31); + enterKW("while", 32) END init; @@ -757,5 +778,6 @@ END NewDef; BEGIN - def := LISTS.create(NIL) + def := LISTS.create(NIL); + strings := LISTS.create(NIL) END SCAN. \ No newline at end of file diff --git a/programs/develop/oberon07/Source/STATEMENTS.ob07 b/programs/develop/oberon07/source/STATEMENTS.ob07 similarity index 93% rename from programs/develop/oberon07/Source/STATEMENTS.ob07 rename to programs/develop/oberon07/source/STATEMENTS.ob07 index a873af1b42..cb6cfa4ffa 100644 --- a/programs/develop/oberon07/Source/STATEMENTS.ob07 +++ b/programs/develop/oberon07/source/STATEMENTS.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2018-2020, Anton Krotov + Copyright (c) 2018-2021, Anton Krotov All rights reserved. *) @@ -9,7 +9,7 @@ MODULE STATEMENTS; IMPORT - PARS, PROG, SCAN, ARITH, STRINGS, LISTS, IL, X86, AMD64, MSP430, THUMB, RVM32I, + PARS, PROG, SCAN, ARITH, STRINGS, LISTS, IL, X86, AMD64, MSP430, THUMB, RVMxI, ERRORS, UTILS, AVL := AVLTREES, CONSOLE, C := COLLECTIONS, TARGETS; @@ -26,8 +26,9 @@ CONST errCHR = 9; errWCHR = 10; errBYTE = 11; chkIDX* = 0; chkGUARD* = 1; chkPTR* = 2; chkCHR* = 3; chkWCHR* = 4; chkBYTE* = 5; + chkSTK* = MSP430.chkSTK; (* 6 *) - chkALL* = {chkIDX, chkGUARD, chkPTR, chkCHR, chkWCHR, chkBYTE}; + chkALL* = {chkIDX, chkGUARD, chkPTR, chkCHR, chkWCHR, chkBYTE, chkSTK}; TYPE @@ -207,7 +208,7 @@ BEGIN IF e._type = tCHAR THEN res := 1 ELSE - res := LENGTH(e.value.string(SCAN.IDENT).s) + res := LENGTH(e.value.string(SCAN.STRING).s) END RETURN res END strlen; @@ -240,7 +241,7 @@ BEGIN IF e._type.typ IN {PROG.tCHAR, PROG.tWCHAR} THEN res := 1 ELSE - res := _length(e.value.string(SCAN.IDENT).s) + res := _length(e.value.string(SCAN.STRING).s) END RETURN res END utf8strlen; @@ -301,11 +302,11 @@ END assigncomp; PROCEDURE String (e: PARS.EXPR): INTEGER; VAR offset: INTEGER; - string: SCAN.IDENT; + string: SCAN.STRING; BEGIN IF strlen(e) # 1 THEN - string := e.value.string(SCAN.IDENT); + string := e.value.string(SCAN.STRING); IF string.offset = -1 THEN string.offset := IL.putstr(string.s); END; @@ -321,11 +322,11 @@ END String; PROCEDURE StringW (e: PARS.EXPR): INTEGER; VAR offset: INTEGER; - string: SCAN.IDENT; + string: SCAN.STRING; BEGIN IF utf8strlen(e) # 1 THEN - string := e.value.string(SCAN.IDENT); + string := e.value.string(SCAN.STRING); IF string.offsetW = -1 THEN string.offsetW := IL.putstrW(string.s); END; @@ -334,7 +335,7 @@ BEGIN IF e._type.typ IN {PROG.tWCHAR, PROG.tCHAR} THEN offset := IL.putstrW1(ARITH.Int(e.value)) ELSE (* e._type.typ = PROG.tSTRING *) - string := e.value.string(SCAN.IDENT); + string := e.value.string(SCAN.STRING); IF string.offsetW = -1 THEN string.offsetW := IL.putstrW(string.s); END; @@ -383,7 +384,7 @@ BEGIN END; IL.AddCmd(IL.opCOPYA, VarType.base.size); label := IL.NewLabel(); - IL.AddJmpCmd(IL.opJNZ, label); + IL.Jmp(IL.opJNZ, label); IL.OnError(line, errCOPY); IL.SetLabel(label) @@ -436,7 +437,7 @@ BEGIN ELSIF (e.obj = eCONST) & isChar(e) & (VarType = tWCHAR) THEN IL.AddCmd(IL.opSAVE16C, ARITH.Int(e.value)) ELSIF isStringW1(e) & (VarType = tWCHAR) THEN - IL.AddCmd(IL.opSAVE16C, StrToWChar(e.value.string(SCAN.IDENT).s)) + IL.AddCmd(IL.opSAVE16C, StrToWChar(e.value.string(SCAN.STRING).s)) ELSIF isCharW(e) & (VarType = tWCHAR) THEN IF e.obj = eCONST THEN IL.AddCmd(IL.opSAVE16C, ARITH.Int(e.value)) @@ -608,7 +609,7 @@ BEGIN IL.Const(0); IL.Param1 ELSIF isStringW1(e) & (p._type = tWCHAR) THEN - IL.Const(StrToWChar(e.value.string(SCAN.IDENT).s)); + IL.Const(StrToWChar(e.value.string(SCAN.STRING).s)); IL.Param1 ELSIF (e._type.typ = PROG.tSTRING) OR (e._type.typ IN {PROG.tCHAR, PROG.tWCHAR}) & (p._type.typ = PROG.tARRAY) & (p._type.base.typ IN {PROG.tCHAR, PROG.tWCHAR}) THEN @@ -709,12 +710,6 @@ BEGIN getpos(parser, pos); - IF e.obj IN {eSYSPROC, eSYSFUNC} THEN - IF parser.unit.scopeLvl > 0 THEN - parser.unit.scopes[parser.unit.scopeLvl].enter(IL.COMMAND).allocReg := FALSE - END - END; - IF e.obj IN {eSTPROC, eSYSPROC} THEN CASE proc OF @@ -1146,11 +1141,12 @@ BEGIN END |PROG.stORD: + IL.AddCmd(IL.opPRECALL, 0); PExpression(parser, e); PARS.check(isChar(e) OR isBoolean(e) OR isSet(e) OR isCharW(e) OR isStringW1(e), pos, 66); IF e.obj = eCONST THEN IF isStringW1(e) THEN - ASSERT(ARITH.setInt(e.value, StrToWChar(e.value.string(SCAN.IDENT).s))) + ASSERT(ARITH.setInt(e.value, StrToWChar(e.value.string(SCAN.STRING).s))) ELSE ARITH.ord(e.value) END @@ -1382,7 +1378,7 @@ BEGIN IF chkPTR IN Options.checking THEN label := IL.NewLabel(); - IL.AddJmpCmd(IL.opJNZ1, label); + IL.Jmp(IL.opJNZ1, label); IL.OnError(pos.line, error); IL.SetLabel(label) END @@ -1551,7 +1547,9 @@ BEGIN PARS.checklex(parser, SCAN.lxRSQUARE); PARS.Next(parser); - e.ident := NIL + IF ~(isArr(e) & (e._type.length = 0) & (parser.sym = SCAN.lxLSQUARE)) THEN + e.ident := NIL + END ELSIF parser.sym = SCAN.lxCARET DO getpos(parser, pos); @@ -1628,7 +1626,7 @@ BEGIN IL.setlast(begcall); IL.AddCmd(IL.opPRECALL, ORD(isfloat)); - IF cconv IN {PROG._ccall16, PROG.ccall16} THEN + IF cconv IN {PROG._ccall, PROG.ccall} THEN IL.AddCmd(IL.opALIGN16, parSize) ELSIF cconv IN {PROG._win64, PROG.win64} THEN IL.AddCmd(IL.opWIN64ALIGN16, parSize) @@ -1646,7 +1644,7 @@ BEGIN IL.CallP(callconv, fparSize) END; - IF cconv IN {PROG._ccall16, PROG.ccall16} THEN + IF cconv IN {PROG._ccall, PROG.ccall} THEN IL.AddCmd(IL.opCLEANUP, parSize); IL.AddCmd0(IL.opPOPSP) ELSIF cconv IN {PROG._win64, PROG.win64} THEN @@ -1655,7 +1653,7 @@ BEGIN ELSIF cconv IN {PROG._systemv, PROG.systemv} THEN IL.AddCmd(IL.opCLEANUP, parSize + stk_par); IL.AddCmd0(IL.opPOPSP) - ELSIF cconv IN {PROG._ccall, PROG.ccall, PROG.default16, PROG.code, PROG._code} THEN + ELSIF cconv IN {PROG._cdecl, PROG.cdecl, PROG.default16, PROG.code, PROG._code} THEN IL.AddCmd(IL.opCLEANUP, parSize) END; @@ -1912,10 +1910,10 @@ VAR label := IL.NewLabel() END; - IF e.obj = eCONST THEN + IF (e.obj = eCONST) & isBoolean(e) THEN IL.Const(ORD(ARITH.getBool(e.value))) END; - IL.AndOrOpt(label) + IL.Jmp(IL.opJZ, label) END END; @@ -2011,7 +2009,7 @@ VAR ELSE IF e1.obj # eCONST THEN label1 := IL.NewLabel(); - IL.AddJmpCmd(IL.opJG, label1) + IL.Jmp(IL.opJG, label1) END; IF e.obj = eCONST THEN IL.OnError(pos.line, errDIV); @@ -2030,7 +2028,7 @@ VAR |SCAN.lxAND: PARS.check(isBoolean(e) & isBoolean(e1), pos, 37); - IF (e.obj = eCONST) & (e1.obj = eCONST) THEN + IF (e.obj = eCONST) & (e1.obj = eCONST) & parser.constexp THEN ARITH.opBoolean(e.value, e1.value, "&") ELSE e.obj := eEXPR; @@ -2044,12 +2042,12 @@ VAR IF label # -1 THEN label1 := IL.NewLabel(); - IL.AddJmpCmd(IL.opJNZ, label1); + IL.Jmp(IL.opJNZ, label1); IL.SetLabel(label); IL.Const(0); IL.drop; label := IL.NewLabel(); - IL.AddJmpCmd(IL.opJMP, label); + IL.Jmp(IL.opJMP, label); IL.SetLabel(label1); IL.Const(1); IL.SetLabel(label); @@ -2063,7 +2061,7 @@ VAR pos: PARS.POSITION; op: INTEGER; e1: PARS.EXPR; - s, s1: SCAN.LEXSTR; + s, s1: SCAN.TEXTSTR; plus, minus: BOOLEAN; @@ -2117,11 +2115,10 @@ VAR label := IL.NewLabel() END; - IF e.obj = eCONST THEN + IF (e.obj = eCONST) & isBoolean(e) THEN IL.Const(ORD(ARITH.getBool(e.value))) END; - IL.not; - IL.AndOrOpt(label) + IL.Jmp(IL.opJNZ, label) END END; @@ -2155,15 +2152,15 @@ VAR IF e.value.typ = ARITH.tCHAR THEN ARITH.charToStr(e.value, s) ELSE - s := e.value.string(SCAN.IDENT).s + s := e.value.string(SCAN.STRING).s END; IF e1.value.typ = ARITH.tCHAR THEN ARITH.charToStr(e1.value, s1) ELSE - s1 := e1.value.string(SCAN.IDENT).s + s1 := e1.value.string(SCAN.STRING).s END; PARS.check(ARITH.concat(s, s1), pos, 5); - e.value.string := SCAN.enterid(s); + e.value.string := SCAN.enterStr(s); e.value.typ := ARITH.tSTRING; e._type := PROG.program.stTypes.tSTRING END @@ -2202,7 +2199,7 @@ VAR |SCAN.lxOR: PARS.check(isBoolean(e) & isBoolean(e1), pos, 37); - IF (e.obj = eCONST) & (e1.obj = eCONST) THEN + IF (e.obj = eCONST) & (e1.obj = eCONST) & parser.constexp THEN ARITH.opBoolean(e.value, e1.value, "|") ELSE e.obj := eEXPR; @@ -2216,12 +2213,12 @@ VAR IF label # -1 THEN label1 := IL.NewLabel(); - IL.AddJmpCmd(IL.opJZ, label1); + IL.Jmp(IL.opJZ, label1); IL.SetLabel(label); IL.Const(1); IL.drop; label := IL.NewLabel(); - IL.AddJmpCmd(IL.opJMP, label); + IL.Jmp(IL.opJMP, label); IL.SetLabel(label1); IL.Const(0); IL.SetLabel(label); @@ -2371,10 +2368,10 @@ BEGIN END ELSIF isStringW1(e) & isCharW(e1) THEN - IL.AddCmd(IL.opEQC + cmp, StrToWChar(e.value.string(SCAN.IDENT).s)) + IL.AddCmd(IL.opEQC + cmp, StrToWChar(e.value.string(SCAN.STRING).s)) ELSIF isStringW1(e1) & isCharW(e) THEN - IL.AddCmd(IL.opEQC + cmp, StrToWChar(e1.value.string(SCAN.IDENT).s)) + IL.AddCmd(IL.opEQC + cmp, StrToWChar(e1.value.string(SCAN.STRING).s)) ELSIF isBoolean(e) & isBoolean(e1) THEN IF constant THEN @@ -2488,10 +2485,10 @@ BEGIN END ELSIF isStringW1(e) & isCharW(e1) THEN - IL.AddCmd(IL.opEQC + invcmpcode(op), StrToWChar(e.value.string(SCAN.IDENT).s)) + IL.AddCmd(IL.opEQC + invcmpcode(op), StrToWChar(e.value.string(SCAN.STRING).s)) ELSIF isStringW1(e1) & isCharW(e) THEN - IL.AddCmd(IL.opEQC + cmp, StrToWChar(e1.value.string(SCAN.IDENT).s)) + IL.AddCmd(IL.opEQC + cmp, StrToWChar(e1.value.string(SCAN.STRING).s)) ELSIF isReal(e) & isReal(e1) THEN IF constant THEN @@ -2641,7 +2638,7 @@ BEGIN L := IL.NewLabel(); IF ~_if THEN - IL.AddCmd0(IL.opLOOP); + IL.AddCmd(IL.opNOP, IL.begin_loop); IL.SetLabel(L) END; @@ -2655,7 +2652,7 @@ BEGIN IF e.obj = eCONST THEN IF ~ARITH.getBool(e.value) THEN - IL.AddJmpCmd(IL.opJMP, label) + IL.Jmp(IL.opJMP, label) END ELSE IL.AndOrOpt(label) @@ -2671,7 +2668,7 @@ BEGIN parser.StatSeq(parser); IF ~_if OR (parser.sym # SCAN.lxEND) THEN - IL.AddJmpCmd(IL.opJMP, L) + IL.Jmp(IL.opJMP, L) END; IL.SetLabel(label) @@ -2684,7 +2681,7 @@ BEGIN END; IL.SetLabel(L) ELSE - IL.AddCmd0(IL.opENDLOOP) + IL.AddCmd(IL.opNOP, IL.end_loop) END; PARS.checklex(parser, SCAN.lxEND); @@ -2701,7 +2698,7 @@ VAR L: IL.COMMAND; BEGIN - IL.AddCmd0(IL.opLOOP); + IL.AddCmd(IL.opNOP, IL.begin_loop); label := IL.NewLabel(); IL.SetLabel(label); @@ -2716,14 +2713,14 @@ BEGIN IF e.obj = eCONST THEN IF ~ARITH.getBool(e.value) THEN - IL.AddJmpCmd(IL.opJMP, label) + IL.Jmp(IL.opJMP, label) END ELSE IL.AndOrOpt(label); L.param1 := label END; - IL.AddCmd0(IL.opENDLOOP) + IL.AddCmd(IL.opNOP, IL.end_loop) END RepeatStatement; @@ -2797,8 +2794,8 @@ VAR a := ARITH.getInt(value) ELSIF isCharW(caseExpr) THEN PARS.ConstExpression(parser, value); - IF (value.typ = ARITH.tSTRING) & (_length(value.string(SCAN.IDENT).s) = 1) & (LENGTH(value.string(SCAN.IDENT).s) > 1) THEN - ASSERT(ARITH.setInt(value, StrToWChar(value.string(SCAN.IDENT).s))) + IF (value.typ = ARITH.tSTRING) & (_length(value.string(SCAN.STRING).s) = 1) & (LENGTH(value.string(SCAN.STRING).s) > 1) THEN + ASSERT(ARITH.setInt(value, StrToWChar(value.string(SCAN.STRING).s))) ELSE PARS.check(value.typ IN {ARITH.tWCHAR, ARITH.tCHAR}, pos, 99) END; @@ -2927,7 +2924,7 @@ VAR END; parser.StatSeq(parser); - IL.AddJmpCmd(IL.opJMP, _end); + IL.Jmp(IL.opJMP, _end); IF isRecPtr(caseExpr) THEN caseExpr.ident._type := t @@ -2976,7 +2973,7 @@ VAR IL.SetLabel(node.data(CASE_LABEL).self); IL._case(range.a, range.b, L, R); IF v.processed THEN - IL.AddJmpCmd(IL.opJMP, node.data(CASE_LABEL).variant) + IL.Jmp(IL.opJMP, node.data(CASE_LABEL).variant) END; v.processed := TRUE; @@ -3010,7 +3007,7 @@ VAR _else := IL.NewLabel(); table := IL.NewLabel(); IL.AddCmd(IL.opSWITCH, ORD(isRecPtr(e))); - IL.AddJmpCmd(IL.opJMP, table); + IL.Jmp(IL.opJMP, table); tree := NIL; @@ -3024,7 +3021,7 @@ VAR IF parser.sym = SCAN.lxELSE THEN PARS.Next(parser); parser.StatSeq(parser); - IL.AddJmpCmd(IL.opJMP, _end) + IL.Jmp(IL.opJMP, _end) ELSE IL.OnError(pos.line, errCASE) END; @@ -3035,7 +3032,7 @@ VAR IF isRecPtr(e) THEN IL.SetLabel(table); TableT(tree); - IL.AddJmpCmd(IL.opJMP, _else) + IL.Jmp(IL.opJMP, _else) ELSE tree.data(CASE_LABEL).self := table; Table(tree, _else) @@ -3094,7 +3091,7 @@ VAR L1, L2: INTEGER; BEGIN - IL.AddCmd0(IL.opLOOP); + IL.AddCmd(IL.opNOP, IL.begin_loop); L1 := IL.NewLabel(); L2 := IL.NewLabel(); @@ -3167,7 +3164,7 @@ BEGIN END END; - IL.AddJmpCmd(IL.opJZ, L2); + IL.Jmp(IL.opJZ, L2); PARS.checklex(parser, SCAN.lxDO); PARS.Next(parser); @@ -3181,15 +3178,14 @@ BEGIN IL.AddCmd(IL.opINCC, st); - IL.AddJmpCmd(IL.opJMP, L1); + IL.Jmp(IL.opJMP, L1); PARS.checklex(parser, SCAN.lxEND); PARS.Next(parser); IL.SetLabel(L2); - IL.AddCmd0(IL.opENDLOOP) - + IL.AddCmd(IL.opNOP, IL.end_loop) END ForStatement; @@ -3260,12 +3256,14 @@ VAR rtl: PROG.UNIT; - PROCEDURE getproc (rtl: PROG.UNIT; name: SCAN.LEXSTR; idx: INTEGER); + PROCEDURE getproc (rtl: PROG.UNIT; name: SCAN.IDSTR; idx: INTEGER); VAR id: PROG.IDENT; + ident: SCAN.IDENT; BEGIN - id := PROG.getIdent(rtl, SCAN.enterid(name), FALSE); + SCAN.setIdent(ident, name); + id := PROG.getIdent(rtl, ident, FALSE); IF (id # NIL) & (id._import # NIL) THEN IL.set_rtl(idx, -id._import(IL.IMPORT_PROC).label); @@ -3307,7 +3305,7 @@ BEGIN getproc(rtl, "_isrec", IL._isrec); getproc(rtl, "_dllentry", IL._dllentry); getproc(rtl, "_sofinit", IL._sofinit) - ELSIF CPU IN {TARGETS.cpuTHUMB, TARGETS.cpuRVM32I} THEN + ELSIF CPU IN {TARGETS.cpuTHUMB, TARGETS.cpuRVM32I, TARGETS.cpuRVM64I} THEN getproc(rtl, "_fmul", IL._fmul); getproc(rtl, "_fdiv", IL._fdiv); getproc(rtl, "_fdivi", IL._fdivi); @@ -3319,7 +3317,7 @@ BEGIN getproc(rtl, "_flt", IL._flt); getproc(rtl, "_pack", IL._pack); getproc(rtl, "_unpk", IL._unpk); - IF CPU = TARGETS.cpuRVM32I THEN + IF CPU IN {TARGETS.cpuRVM32I, TARGETS.cpuRVM64I} THEN getproc(rtl, "_error", IL._error) END END @@ -3355,13 +3353,13 @@ BEGIN IF TARGETS.RTL THEN parser := PARS.create(path, lib_path, StatSeq, expression, designator, chkreturn); - IF parser.open(parser, UTILS.RTL_NAME) THEN + IF parser.open(parser, UTILS.RTL_NAME, UTILS.FILE_EXT) THEN parser.parse(parser); PARS.destroy(parser) ELSE PARS.destroy(parser); parser := PARS.create(lib_path, lib_path, StatSeq, expression, designator, chkreturn); - IF parser.open(parser, UTILS.RTL_NAME) THEN + IF parser.open(parser, UTILS.RTL_NAME, UTILS.FILE_EXT) THEN parser.parse(parser); PARS.destroy(parser) ELSE @@ -3373,7 +3371,7 @@ BEGIN parser := PARS.create(path, lib_path, StatSeq, expression, designator, chkreturn); parser.main := TRUE; - IF parser.open(parser, modname) THEN + IF parser.open(parser, modname, UTILS.FILE_EXT) THEN parser.parse(parser) ELSE ERRORS.FileNotFound(path, modname, UTILS.FILE_EXT) @@ -3398,7 +3396,8 @@ BEGIN |TARGETS.cpuX86: X86.CodeGen(outname, target, options) |TARGETS.cpuMSP430: MSP430.CodeGen(outname, target, options) |TARGETS.cpuTHUMB: THUMB.CodeGen(outname, target, options) - |TARGETS.cpuRVM32I: RVM32I.CodeGen(outname, target, options) + |TARGETS.cpuRVM32I, + TARGETS.cpuRVM64I: RVMxI.CodeGen(outname, target, options) END END compile; diff --git a/programs/develop/oberon07/Source/STRINGS.ob07 b/programs/develop/oberon07/source/STRINGS.ob07 similarity index 77% rename from programs/develop/oberon07/Source/STRINGS.ob07 rename to programs/develop/oberon07/source/STRINGS.ob07 index 8dfcb66d05..4109447699 100644 --- a/programs/develop/oberon07/Source/STRINGS.ob07 +++ b/programs/develop/oberon07/source/STRINGS.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2018-2020, Anton Krotov + Copyright (c) 2018-2021, Anton Krotov All rights reserved. *) @@ -73,17 +73,6 @@ BEGIN END IntToStr; -PROCEDURE IntToHex* (x: INTEGER; VAR str: ARRAY OF CHAR; n: INTEGER); -BEGIN - str[n] := 0X; - WHILE n > 0 DO - str[n - 1] := CHR(UTILS.hexdgt(x MOD 16)); - x := x DIV 16; - DEC(n) - END -END IntToHex; - - PROCEDURE search* (s: ARRAY OF CHAR; VAR pos: INTEGER; c: CHAR; forward: BOOLEAN); VAR length: INTEGER; @@ -110,6 +99,47 @@ BEGIN END search; +PROCEDURE replace* (VAR s: ARRAY OF CHAR; find, repl: CHAR); +VAR + i, strlen: INTEGER; + +BEGIN + strlen := LENGTH(s) - 1; + FOR i := 0 TO strlen DO + IF s[i] = find THEN + s[i] := repl + END + END +END replace; + + +PROCEDURE trim* (source: ARRAY OF CHAR; VAR result: ARRAY OF CHAR); +VAR + LenS, start, _end, i, j: INTEGER; + +BEGIN + LenS := LENGTH(source) - 1; + j := 0; + IF LenS >= 0 THEN + start := 0; + WHILE (start <= LenS) & (source[start] <= 20X) DO + INC(start) + END; + + _end := LenS; + WHILE (_end >= 0) & (source[_end] <= 20X) DO + DEC(_end) + END; + + FOR i := start TO _end DO + result[j] := source[i]; + INC(j) + END + END; + result[j] := 0X +END trim; + + PROCEDURE letter* (c: CHAR): BOOLEAN; RETURN ("a" <= c) & (c <= "z") OR ("A" <= c) & (c <= "Z") OR (c = "_") END letter; @@ -130,7 +160,7 @@ PROCEDURE space* (c: CHAR): BOOLEAN; END space; -PROCEDURE cap (VAR c: CHAR); +PROCEDURE cap* (VAR c: CHAR); BEGIN IF ("a" <= c) & (c <= "z") THEN c := CHR(ORD(c) - 32) @@ -290,4 +320,23 @@ BEGIN END Utf8To16; +PROCEDURE HashStr* (name: ARRAY OF CHAR): INTEGER; +VAR + i, h: INTEGER; + g: SET; + +BEGIN + h := 0; + i := 0; + WHILE name[i] # 0X DO + h := h * 16 + ORD(name[i]); + g := BITS(h) * {28..31}; + h := ORD(BITS(h) / BITS(LSR(ORD(g), 24)) - g); + INC(i) + END + + RETURN h +END HashStr; + + END STRINGS. \ No newline at end of file diff --git a/programs/develop/oberon07/Source/TARGETS.ob07 b/programs/develop/oberon07/source/TARGETS.ob07 similarity index 81% rename from programs/develop/oberon07/Source/TARGETS.ob07 rename to programs/develop/oberon07/source/TARGETS.ob07 index 58d7e01830..0b87e5838d 100644 --- a/programs/develop/oberon07/Source/TARGETS.ob07 +++ b/programs/develop/oberon07/source/TARGETS.ob07 @@ -1,12 +1,14 @@ (* BSD 2-Clause License - Copyright (c) 2019-2020, Anton Krotov + Copyright (c) 2019-2021, Anton Krotov All rights reserved. *) MODULE TARGETS; +IMPORT UTILS; + CONST @@ -25,17 +27,21 @@ CONST Linux64SO* = 12; STM32CM3* = 13; RVM32I* = 14; + RVM64I* = 15; cpuX86* = 0; cpuAMD64* = 1; cpuMSP430* = 2; cpuTHUMB* = 3; - cpuRVM32I* = 4; + cpuRVM32I* = 4; cpuRVM64I* = 5; osNONE* = 0; osWIN32* = 1; osWIN64* = 2; osLINUX32* = 3; osLINUX64* = 4; osKOS* = 5; - noDISPOSE = {MSP430, STM32CM3, RVM32I}; + noDISPOSE = {MSP430, STM32CM3, RVM32I, RVM64I}; noRTL = {MSP430}; + libRVM32I = "RVMxI" + UTILS.slash + "32"; + libRVM64I = "RVMxI" + UTILS.slash + "64"; + TYPE @@ -51,9 +57,9 @@ TYPE VAR - Targets*: ARRAY 15 OF TARGET; + Targets*: ARRAY 16 OF TARGET; - CPUs: ARRAY 5 OF + CPUs: ARRAY 6 OF RECORD BitDepth, InstrSize: INTEGER; LittleEndian: BOOLEAN @@ -126,20 +132,22 @@ BEGIN EnterCPU(cpuMSP430, 16, 2, TRUE); EnterCPU(cpuTHUMB, 32, 2, TRUE); EnterCPU(cpuRVM32I, 32, 4, TRUE); + EnterCPU(cpuRVM64I, 64, 8, TRUE); - Enter( MSP430, cpuMSP430, 0, osNONE, "msp430", "MSP430", ".hex"); - Enter( Win32C, cpuX86, 8, osWIN32, "win32con", "Windows32", ".exe"); - Enter( Win32GUI, cpuX86, 8, osWIN32, "win32gui", "Windows32", ".exe"); - Enter( Win32DLL, cpuX86, 8, osWIN32, "win32dll", "Windows32", ".dll"); - Enter( KolibriOS, cpuX86, 8, osKOS, "kosexe", "KolibriOS", ""); - Enter( KolibriOSDLL, cpuX86, 8, osKOS, "kosdll", "KolibriOS", ".obj"); - Enter( Win64C, cpuAMD64, 8, osWIN64, "win64con", "Windows64", ".exe"); - Enter( Win64GUI, cpuAMD64, 8, osWIN64, "win64gui", "Windows64", ".exe"); - Enter( Win64DLL, cpuAMD64, 8, osWIN64, "win64dll", "Windows64", ".dll"); - Enter( Linux32, cpuX86, 8, osLINUX32, "linux32exe", "Linux32", ""); - Enter( Linux32SO, cpuX86, 8, osLINUX32, "linux32so", "Linux32", ".so"); - Enter( Linux64, cpuAMD64, 8, osLINUX64, "linux64exe", "Linux64", ""); - Enter( Linux64SO, cpuAMD64, 8, osLINUX64, "linux64so", "Linux64", ".so"); - Enter( STM32CM3, cpuTHUMB, 4, osNONE, "stm32cm3", "STM32CM3", ".hex"); - Enter( RVM32I, cpuRVM32I, 4, osNONE, "rvm32i", "RVM32I", ".bin"); + Enter( MSP430, cpuMSP430, 0, osNONE, "msp430", "MSP430", ".hex"); + Enter( Win32C, cpuX86, 8, osWIN32, "win32con", "Windows", ".exe"); + Enter( Win32GUI, cpuX86, 8, osWIN32, "win32gui", "Windows", ".exe"); + Enter( Win32DLL, cpuX86, 8, osWIN32, "win32dll", "Windows", ".dll"); + Enter( KolibriOS, cpuX86, 8, osKOS, "kosexe", "KolibriOS", ""); + Enter( KolibriOSDLL, cpuX86, 8, osKOS, "kosdll", "KolibriOS", ".obj"); + Enter( Win64C, cpuAMD64, 8, osWIN64, "win64con", "Windows", ".exe"); + Enter( Win64GUI, cpuAMD64, 8, osWIN64, "win64gui", "Windows", ".exe"); + Enter( Win64DLL, cpuAMD64, 8, osWIN64, "win64dll", "Windows", ".dll"); + Enter( Linux32, cpuX86, 8, osLINUX32, "linux32exe", "Linux", ""); + Enter( Linux32SO, cpuX86, 8, osLINUX32, "linux32so", "Linux", ".so"); + Enter( Linux64, cpuAMD64, 8, osLINUX64, "linux64exe", "Linux", ""); + Enter( Linux64SO, cpuAMD64, 8, osLINUX64, "linux64so", "Linux", ".so"); + Enter( STM32CM3, cpuTHUMB, 4, osNONE, "stm32cm3", "STM32CM3", ".hex"); + Enter( RVM32I, cpuRVM32I, 4, osNONE, "rvm32i", libRVM32I, ".bin"); + Enter( RVM64I, cpuRVM64I, 8, osNONE, "rvm64i", libRVM64I, ".bin"); END TARGETS. \ No newline at end of file diff --git a/programs/develop/oberon07/Source/TEXTDRV.ob07 b/programs/develop/oberon07/source/TEXTDRV.ob07 similarity index 100% rename from programs/develop/oberon07/Source/TEXTDRV.ob07 rename to programs/develop/oberon07/source/TEXTDRV.ob07 diff --git a/programs/develop/oberon07/Source/THUMB.ob07 b/programs/develop/oberon07/source/THUMB.ob07 similarity index 88% rename from programs/develop/oberon07/Source/THUMB.ob07 rename to programs/develop/oberon07/source/THUMB.ob07 index cfc3a52f68..f53cd57c84 100644 --- a/programs/develop/oberon07/Source/THUMB.ob07 +++ b/programs/develop/oberon07/source/THUMB.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2019-2020, Anton Krotov + Copyright (c) 2019-2021, Anton Krotov All rights reserved. *) @@ -23,11 +23,18 @@ CONST inf = 7F800000H; - STM32_minROM* = 16; STM32_maxROM* = 65536; - STM32_minRAM* = 4; STM32_maxRAM* = 65536; + minROM* = 16; maxROM* = 65536; + minRAM* = 4; maxRAM* = 65536; maxIVT* = 1023; + _THUMB2 = 0; _IT = 1; _SDIV = 2; _CBXZ = 3; + + CortexM0 = {}; + CortexM1 = {}; + CortexM3 = {_THUMB2, _IT, _SDIV, _CBXZ}; + CortexM23 = {_SDIV, _CBXZ}; + TYPE @@ -103,7 +110,8 @@ VAR IVTLen, MinStack, Reserved: INTEGER; - InstrSet: RECORD thumb2, it, cbxz, sdiv: BOOLEAN END + InstrSet: SET; + isNXP: BOOLEAN END; IVT: ARRAY maxIVT + 1 OF INTEGER; @@ -475,7 +483,7 @@ END Cmp; PROCEDURE Tst (r: INTEGER); BEGIN - gen3(1, r, 0) (* cmp r, #0 *) + gen3(1, r, 0) (* cmp r, 0 *) END Tst; @@ -533,8 +541,6 @@ VAR shorted: BOOLEAN; jump: JUMP; - first, second: INTEGER; - reloc, i, diff, len: INTEGER; RelocCode: RELOCCODE; @@ -555,14 +561,6 @@ VAR END genjmp; - PROCEDURE genlongjmp (offset: INTEGER; VAR first, second: INTEGER); - BEGIN - ASSERT(srange(offset, 22)); - first := 0F000H + ASR(offset, 11) MOD 2048; - second := 0F800H + offset MOD 2048 - END genlongjmp; - - PROCEDURE movwt (r, imm16, t: INTEGER; VAR code: RELOCCODE); VAR imm1, imm3, imm4, imm8: INTEGER; @@ -576,17 +574,17 @@ VAR PROCEDURE genmovimm32 (r, value: INTEGER; VAR code: RELOCCODE); BEGIN - IF Target.InstrSet.thumb2 THEN + IF _THUMB2 IN Target.InstrSet THEN movwt(r, low(value), 0, code); movwt(r, high(value), 1, code) ELSE - code[0] := 2000H + r * 256 + UTILS.Byte(value, 3); (* mov r, #imm8 *) - code[1] := 0200H + r * 9; (* lsl r, r, #8 *) - code[2] := 3000H + r * 256 + UTILS.Byte(value, 2); (* add r, #imm8 *) - code[3] := code[1]; (* lsl r, r, #8 *) - code[4] := 3000H + r * 256 + UTILS.Byte(value, 1); (* add r, #imm8 *) - code[5] := code[1]; (* lsl r, r, #8 *) - code[6] := 3000H + r * 256 + UTILS.Byte(value, 0) (* add r, #imm8 *) + code[0] := 2000H + r * 256 + UTILS.Byte(value, 3); (* movs r, imm8 *) + code[1] := 0200H + r * 9; (* lsls r, 8 *) + code[2] := 3000H + r * 256 + UTILS.Byte(value, 2); (* adds r, imm8 *) + code[3] := code[1]; (* lsls r, 8 *) + code[4] := 3000H + r * 256 + UTILS.Byte(value, 1); (* adds r, imm8 *) + code[5] := code[1]; (* lsls r, 8 *) + code[6] := 3000H + r * 256 + UTILS.Byte(value, 0) (* adds r, imm8 *) END END genmovimm32; @@ -597,19 +595,22 @@ VAR END PutCode; - PROCEDURE genbc (code: JUMP); - VAR - first, second: INTEGER; + PROCEDURE genlongjmp (offset: INTEGER); + BEGIN + ASSERT(srange(offset, 22)); + PutCode(0F000H + ASR(offset, 11) MOD 2048); + PutCode(0F800H + offset MOD 2048) + END genlongjmp; + + PROCEDURE genbc (code: JUMP); BEGIN CASE code.len OF |1: PutCode(genjcc(code.cond, code.diff)) |2: PutCode(genjcc(inv0(code.cond), 0)); PutCode(genjmp(code.diff)) |3: PutCode(genjcc(inv0(code.cond), 1)); - genlongjmp(code.diff, first, second); - PutCode(first); - PutCode(second) + genlongjmp(code.diff) END END genbc; @@ -647,7 +648,7 @@ BEGIN |CODE: INC(count) |LABEL: BIN.SetLabel(program, code.label, count) |JUMP: INC(count, code.len); code.offset := count + ORD(code.short) - |RELOC: INC(count, 7 - ORD(Target.InstrSet.thumb2) * 3 + code.rel MOD 2) + |RELOC: INC(count, 7 - ORD(_THUMB2 IN Target.InstrSet) * 3 + code.rel MOD 2) END; code := code.next(ANYCODE) @@ -714,27 +715,22 @@ BEGIN IF code.len = 1 THEN PutCode(genjmp(code.diff)) ELSE - genlongjmp(code.diff, first, second); - PutCode(first); - PutCode(second) + genlongjmp(code.diff) END |JCC: genbc(code) |CBXZ: IF code.len > 1 THEN - PutCode(2800H + code.reg * 256); (* cmp code.reg, #0 *) + PutCode(2800H + code.reg * 256); (* cmp code.reg, 0 *) DEC(code.len); genbc(code) ELSE (* cb(n)z code.reg, L *) - PutCode(0B100H + 800H * ORD(code.cond = jne) + 200H * ORD(code.diff >= 32) + (code.diff MOD 32) * 8 + code.reg) + PutCode(0B100H + 800H * ORD(code.cond = jne) + 200H * (code.diff DIV 32) + (code.diff MOD 32) * 8 + code.reg) END - |CALL: - genlongjmp(code.diff, first, second); - PutCode(first); - PutCode(second) + |CALL: genlongjmp(code.diff) |RELOC: CASE code.rel OF @@ -743,14 +739,14 @@ BEGIN |BIN.RBSS, BIN.PICBSS: reloc := code.value + BssAdr END; IF code.rel IN {BIN.PICCODE, BIN.PICDATA, BIN.PICBSS} THEN - DEC(reloc, CodeAdr + 2 * (code.offset - 3 * ORD(Target.InstrSet.thumb2) + 9)) + DEC(reloc, CodeAdr + 2 * (code.offset - 3 * ORD(_THUMB2 IN Target.InstrSet) + 9)) END; genmovimm32(code.reg, reloc, RelocCode); - FOR i := 0 TO 6 - 3 * ORD(Target.InstrSet.thumb2) DO + FOR i := 0 TO 6 - 3 * ORD(_THUMB2 IN Target.InstrSet) DO PutCode(RelocCode[i]) END; IF code.rel IN {BIN.PICCODE, BIN.PICDATA, BIN.PICBSS} THEN - PutCode(4478H + code.reg) (* add code.reg, PC *) + PutCode(4478H + code.reg) (* add code.reg, pc *) END END; @@ -858,7 +854,7 @@ BEGIN MovImm8(r, 1); LslImm(r, 31) ELSE - IF Target.InstrSet.thumb2 THEN + IF _THUMB2 IN Target.InstrSet THEN movwt(r, low(c), 0); IF (c < 0) OR (c > 65535) THEN movwt(r, high(c), 1) @@ -897,7 +893,7 @@ VAR L1, L2: INTEGER; BEGIN - IF Target.InstrSet.it THEN + IF _IT IN Target.InstrSet THEN Code(0BF00H + cc * 16 + ((cc + 1) MOD 2) * 8 + 4); (* ite cc *) MovConst(r, 1); MovConst(r, 0) @@ -938,12 +934,8 @@ BEGIN ELSE SubImm8(r, -n) END - ELSIF Target.InstrSet.thumb2 & (-4095 <= n) & (n <= 4095) THEN - IF n > 0 THEN - AddSubImm12(r, n, FALSE) - ELSE - AddSubImm12(r, -n, TRUE) - END + ELSIF (_THUMB2 IN Target.InstrSet) & (-4095 <= n) & (n <= 4095) THEN + AddSubImm12(r, ABS(n), n < 0) ELSE r2 := GetAnyReg(); ASSERT(r2 # r); @@ -971,7 +963,7 @@ PROCEDURE AddSP (n: INTEGER); BEGIN IF n > 0 THEN IF n < 127 THEN - Code(0B000H + n) (* add sp, n*4 *) + Code(0B000H + n) (* add sp, n*4 *) ELSE ASSERT(R2 IN R.regs); MovConst(R2, n * 4); @@ -982,25 +974,26 @@ BEGIN END AddSP; -PROCEDURE cbz (r, label: INTEGER); +PROCEDURE cbxz2 (c, r, label: INTEGER); BEGIN - IF Target.InstrSet.cbxz THEN - cbxz(je, r, label) + IF _CBXZ IN Target.InstrSet THEN + cbxz(c, r, label) ELSE Tst(r); - jcc(je, label) + jcc(c, label) END +END cbxz2; + + +PROCEDURE cbz (r, label: INTEGER); +BEGIN + cbxz2(je, r, label) END cbz; PROCEDURE cbnz (r, label: INTEGER); BEGIN - IF Target.InstrSet.cbxz THEN - cbxz(jne, r, label) - ELSE - Tst(r); - jcc(jne, label) - END + cbxz2(jne, r, label) END cbnz; @@ -1053,6 +1046,18 @@ BEGIN END divmod; +PROCEDURE cpsid_i; +BEGIN + Code(0B672H) (* cpsid i *) +END cpsid_i; + + +PROCEDURE cpsie_i; +BEGIN + Code(0B662H) (* cpsie i *) +END cpsie_i; + + PROCEDURE translate (pic, stroffs: INTEGER); VAR cmd, next: COMMAND; @@ -1103,7 +1108,7 @@ BEGIN Label(param1); - gen14(FALSE, TRUE, {}); (* push LR *) + gen14(FALSE, TRUE, {}); (* push {lr} *) n := param2; IF n >= 5 THEN @@ -1128,9 +1133,7 @@ BEGIN IF opcode # IL.opLEAVE THEN UnOp(r1); IF r1 # ACC THEN - GetRegA; - ASSERT(REG.Exchange(R, r1, ACC)); - drop + mov(ACC, r1) END; drop END; @@ -1139,10 +1142,10 @@ BEGIN ASSERT(StkCount = param1); AddSP(param1); - gen14(TRUE, TRUE, {}) (* pop PC *) + gen14(TRUE, TRUE, {}) (* pop {pc} *) |IL.opLEAVEC: - gen5(3, FALSE, TRUE, 6, 0) (* bx LR *) + gen5(3, FALSE, TRUE, 6, 0) (* bx lr *) |IL.opPRECALL: PushAll(0) @@ -1169,6 +1172,7 @@ BEGIN PushConst(param2) |IL.opONERR: + cpsid_i; MovConst(R0, param2); push(R0); DEC(StkCount); @@ -1203,6 +1207,38 @@ BEGIN reloc(r1, BIN.RBSS + pic, param2); Ldr8(r1, r1) + |IL.opLADR_SAVE: + UnOp(r1); + n := LocalOffset(param2); + IF n <= 255 THEN + gen11(FALSE, r1, n) (* str r1, [sp, n*4] *) + ELSE + LocAdr(param2); + BinOp(r1, r2); + Str32(r1, r2); + drop + END; + drop + + |IL.opLADR_INCC: + n := LocalOffset(param1); + IF n <= 255 THEN + r1 := GetAnyReg(); + LdrSp(r1, n); + AddConst(r1, param2); + gen11(FALSE, r1, n) (* str r1, [sp, n*4] *) + ELSE + LocAdr(param1); + r1 := GetAnyReg(); + BinOp(r2, r1); + Ldr32(r1, r2); + AddConst(r1, param2); + BinOp(r2, r1); + Str32(r1, r2); + drop + END; + drop + |IL.opLLOAD32, IL.opVADR, IL.opVLOAD32: r1 := GetAnyReg(); n := LocalOffset(param2); @@ -1402,8 +1438,12 @@ BEGIN |IL.opCASELR: GetRegA; CmpConst(ACC, param1); - jcc(jl, param2); - jcc(jg, cmd.param3); + IF param2 = cmd.param3 THEN + jcc(jne, param2) + ELSE + jcc(jl, param2); + jcc(jg, cmd.param3) + END; drop |IL.opCODE: @@ -1549,11 +1589,11 @@ BEGIN |IL.opCHR: UnOp(r1); - Code(0B2C0H + r1 * 9) (* uxtb r1 *) + Code(0B2C0H + r1 * 9) (* uxtb r1, r1 *) |IL.opWCHR: UnOp(r1); - Code(0B280H + r1 * 9) (* uxth r1 *) + Code(0B280H + r1 * 9) (* uxth r1, r1 *) |IL.opASR, IL.opROR, IL.opLSL, IL.opLSR: BinOp(r1, r2); @@ -1615,8 +1655,6 @@ BEGIN INCL(R.regs, r1); ASSERT(REG.GetReg(R, r1)) - |IL.opLOOP, IL.opENDLOOP: - |IL.opINF: MovConst(GetAnyReg(), inf) @@ -1720,46 +1758,46 @@ BEGIN |IL.opMULS: BinOp(r1, r2); - gen4(0, r2, r1); (* and r1, r2 *) + gen4(0, r2, r1); (* ands r1, r2 *) drop |IL.opMULSC: MovConst(GetAnyReg(), param2); BinOp(r1, r2); - gen4(0, r2, r1); (* and r1, r2 *) + gen4(0, r2, r1); (* ands r1, r2 *) drop |IL.opDIVS: BinOp(r1, r2); - gen4(1, r2, r1); (* eor r1, r2 *) + gen4(1, r2, r1); (* eors r1, r2 *) drop |IL.opDIVSC: MovConst(GetAnyReg(), param2); BinOp(r1, r2); - gen4(1, r2, r1); (* eor r1, r2 *) + gen4(1, r2, r1); (* eors r1, r2 *) drop |IL.opADDS: BinOp(r1, r2); - gen4(12, r2, r1); (* orr r1, r2 *) + gen4(12, r2, r1); (* orrs r1, r2 *) drop |IL.opSUBS: BinOp(r1, r2); - gen4(14, r2, r1); (* bic r1, r2 *) + gen4(14, r2, r1); (* bics r1, r2 *) drop |IL.opADDSC: MovConst(GetAnyReg(), param2); BinOp(r1, r2); - gen4(12, r2, r1); (* orr r1, r2 *) + gen4(12, r2, r1); (* orrs r1, r2 *) drop |IL.opSUBSL: MovConst(GetAnyReg(), param2); BinOp(r1, r2); - gen4(14, r1, r2); (* bic r2, r1 *) + gen4(14, r1, r2); (* bics r2, r1 *) INCL(R.regs, r1); DEC(R.top); R.stk[R.top] := r2 @@ -1767,12 +1805,12 @@ BEGIN |IL.opSUBSR: MovConst(GetAnyReg(), param2); BinOp(r1, r2); - gen4(14, r2, r1); (* bic r1, r2 *) + gen4(14, r2, r1); (* bics r1, r2 *) drop |IL.opUMINS: UnOp(r1); - gen4(15, r1, r1) (* mvn r1, r1 *) + gen4(15, r1, r1) (* mvns r1, r1 *) |IL.opINCL, IL.opEXCL: BinOp(r1, r2); @@ -1781,12 +1819,12 @@ BEGIN CmpConst(r1, 32); L := NewLabel(); jcc(jnb, L); - gen4(2, r1, r3); (* lsl r3, r1 *) + gen4(2, r1, r3); (* lsls r3, r1 *) Ldr32(r1, r2); IF opcode = IL.opINCL THEN - gen4(12, r3, r1) (* orr r1, r3 *) + gen4(12, r3, r1) (* orrs r1, r3 *) ELSE - gen4(14, r3, r1) (* bic r1, r3 *) + gen4(14, r3, r1) (* bics r1, r3 *) END; Str32(r1, r2); Label(L); @@ -1802,9 +1840,9 @@ BEGIN LslImm(r3, param2); Ldr32(r1, r2); IF opcode = IL.opINCLC THEN - gen4(12, r3, r1) (* orr r1, r3 *) + gen4(12, r3, r1) (* orrs r1, r3 *) ELSE - gen4(14, r3, r1) (* bic r1, r3 *) + gen4(14, r3, r1) (* bics r1, r3 *) END; Str32(r1, r2); drop; @@ -1902,9 +1940,9 @@ BEGIN IF n > 0 THEN UnOp(r1); IF n = 8 THEN - Code(0B2C0H + r1 * 9) (* uxtb r1 *) + Code(0B2C0H + r1 * 9) (* uxtb r1, r1 *) ELSIF n = 16 THEN - Code(0B280H + r1 * 9) (* uxth r1 *) + Code(0B280H + r1 * 9) (* uxth r1, r1 *) ELSE LslImm(r1, 32 - n); LsrImm(r1, 32 - n) @@ -1946,7 +1984,7 @@ BEGIN Label(L); MovConst(r3, 1); Shift(IL.opLSL, r3, r1); - gen4(0, r3, r2); (* and r2, r3 *) + gen4(0, r3, r2); (* ands r2, r3 *) SetCC(jne, r1); Label(L2); drop; @@ -1956,7 +1994,7 @@ BEGIN UnOp(r1); r2 := GetAnyReg(); MovConst(r2, LSL(1, param2)); - gen4(0, r2, r1); (* and r1, r2 *) + gen4(0, r2, r1); (* ands r1, r2 *) SetCC(jne, r1); drop @@ -2039,7 +2077,7 @@ BEGIN r2 := GetAnyReg(); MovConst(r2, 1); LslImm(r2, 31); - gen4(1, r2, r1); (* eor r1, r2 *) + gen4(1, r2, r1); (* eors r1, r2 *) drop |IL.opFABS: @@ -2047,16 +2085,18 @@ BEGIN r2 := GetAnyReg(); MovConst(r2, 1); LslImm(r2, 31); - gen4(14, r2, r1); (* bic r1, r2 *) + gen4(14, r2, r1); (* bics r1, r2 *) drop |IL.opNEW: + cpsid_i; PushAll(1); - n := param2 + 8; - ASSERT(UTILS.Align(n, 32)); + n := param2 + 4; + ASSERT(UTILS.Align(n, 4)); PushConst(n); PushConst(param1); - CallRTL(IL._new, 3) + CallRTL(IL._new, 3); + cpsie_i |IL.opTYPEGP: UnOp(r1); @@ -2132,7 +2172,7 @@ BEGIN END translate; -PROCEDURE prolog (GlobSize, tcount, pic, FlashAdr, sp, ivt_len: INTEGER); +PROCEDURE prolog (GlobSize, tcount, pic, sp, ivt_len: INTEGER); VAR r1, r2, i, dcount: INTEGER; @@ -2158,6 +2198,7 @@ BEGIN END; Label(entry); + cpsie_i; r1 := GetAnyReg(); r2 := GetAnyReg(); @@ -2201,14 +2242,14 @@ VAR L1, L2, L3, L4: INTEGER; BEGIN - Code(0BF30H); (* L2: wfi *) - Code(0E7FDH); (* b L2 *) + (* L2: *) + Code(0E7FEH); (* b L2 *) Label(genInt); - Code(0F3EFH); Code(08105H); (* mrs r1, ipsr *) - gen14(FALSE, TRUE, {R1}); (* push {LR, R1} *) + Code(0F3EFH); Code(08005H); (* mrs r0, ipsr *) + gen14(FALSE, TRUE, {R0}); (* push {lr, r0} *) call(int0); - gen14(TRUE, TRUE, {R1}); (* pop {PC, R1} *) + gen14(TRUE, TRUE, {R0}); (* pop {pc, r0} *) Label(emptyProc); Code(04770H); (* bx lr *) @@ -2218,20 +2259,20 @@ BEGIN call(entry); Label(sdivProc); - IF Target.InstrSet.sdiv THEN - Code(09800H); (* ldr r0, [sp + #0] *) - Code(09901H); (* ldr r1, [sp + #4] *) - Code(0FB91H); (* sdiv r2, r1, r0 *) + IF _SDIV IN Target.InstrSet THEN + Code(09800H); (* ldr r0, [sp] *) + Code(09901H); (* ldr r1, [sp, 4] *) + Code(0FB91H); (* sdiv r2, r1, r0 *) Code(0F2F0H); - Code(00013H); (* mov r3, r2 *) - Code(04343H); (* mul r3, r0 *) - Code(01AC9H); (* sub r1, r3 *) - Code(0DA01H); (* bge L *) - Code(04401H); (* add r1, r0 *) - Code(03A01H); (* sub r2, #1 *) - (* L: *) - Code(00010H); (* mov r0, r2 *) - Code(04770H); (* bx lr *) + Code(00013H); (* movs r3, r2 *) + Code(04343H); (* muls r3, r0, r3 *) + Code(01AC9H); (* subs r1, r1, r3 *) + Code(0DA01H); (* bge L *) + Code(01809H); (* adds r1, r1, r0 *) + Code(03A01H); (* subs r2, 1 *) + (* L: *) + Code(00010H); (* movs r0, r2 *) + Code(04770H); (* bx lr *) ELSE (* a / b; a >= 0 *) L1 := NewLabel(); @@ -2303,35 +2344,34 @@ BEGIN END epilog; -PROCEDURE CortexM3; +PROCEDURE SetTarget (FlashStart, SRAMStart: INTEGER; InstrSet: SET; isNXP: BOOLEAN); BEGIN - Target.FlashAdr := 08000000H; - Target.SRAMAdr := 20000000H; - Target.IVTLen := 256; + Target.FlashAdr := FlashStart; + Target.SRAMAdr := SRAMStart; + Target.InstrSet := InstrSet; + Target.isNXP := isNXP; + + Target.IVTLen := 256; (* >= 192 *) Target.Reserved := 0; Target.MinStack := 512; - Target.InstrSet.thumb2 := TRUE; - Target.InstrSet.it := TRUE; - Target.InstrSet.sdiv := TRUE; - Target.InstrSet.cbxz := TRUE -END CortexM3; +END SetTarget; PROCEDURE CodeGen* (outname: ARRAY OF CHAR; target: INTEGER; options: PROG.OPTIONS); VAR opt: PROG.OPTIONS; - ram, rom: INTEGER; + ram, rom, i, j: INTEGER; DataAdr, BssAdr, DataSize, BssSize, CodeSize: INTEGER; BEGIN - IF target = TARGETS.STM32CM3 THEN - CortexM3 - END; + ram := MIN(MAX(options.ram, minRAM), maxRAM) * 1024; + rom := MIN(MAX(options.rom, minROM), maxROM) * 1024; - ram := MIN(MAX(options.ram, STM32_minRAM), STM32_maxRAM) * 1024; - rom := MIN(MAX(options.rom, STM32_minROM), STM32_maxROM) * 1024; + IF target = TARGETS.STM32CM3 THEN + SetTarget(08000000H, 20000000H, CortexM3, FALSE) + END; tcount := CHL.Length(IL.codes.types); @@ -2340,7 +2380,7 @@ BEGIN program := BIN.create(IL.codes.lcount); - REG.Init(R, push, pop, mov, xchg, NIL, NIL, {R0, R1, R2, R3}, {}); + REG.Init(R, push, pop, mov, xchg, {R0, R1, R2, R3}); StkCount := 0; @@ -2357,7 +2397,7 @@ BEGIN BssSize := IL.codes.bss; ASSERT(UTILS.Align(BssSize, 4)); - prolog(BssSize, tcount, ORD(opt.pic), Target.FlashAdr, Target.SRAMAdr + ram, Target.IVTLen); + prolog(BssSize, tcount, ORD(opt.pic), Target.SRAMAdr + ram, Target.IVTLen); translate(ORD(opt.pic), tcount * 4); epilog; @@ -2374,6 +2414,16 @@ BEGIN ERRORS.Error(204) END; + IF Target.isNXP THEN + BIN.put32le(program.code, 2FCH, 0H); (* code read protection (CRP) *) + (* NXP checksum *) + j := 0; + FOR i := 0 TO 6 DO + INC(j, BIN.get32le(program.code, i * 4)) + END; + BIN.put32le(program.code, 1CH, -j) + END; + WR.Create(outname); HEX.Data2(program.code, 0, CodeSize, high(Target.FlashAdr)); @@ -2381,11 +2431,10 @@ BEGIN WR.Close; - C.StringLn("--------------------------------------------"); + C.Dashes; C.String( " rom: "); C.Int(CodeSize); C.String(" of "); C.Int(rom); C.String(" ("); C.Int(CodeSize * 100 DIV rom); C.StringLn("%)"); C.Ln; - C.String( " ram: "); C.Int(DataSize); C.String(" of "); C.Int(ram); C.String(" ("); C.Int(DataSize * 100 DIV ram); C.StringLn("%)") - + C.String( " ram: "); C.Int(DataSize); C.String(" of "); C.Int(ram); C.String(" ("); C.Int(DataSize * 100 DIV ram); C.StringLn("%)") END CodeGen; diff --git a/programs/develop/oberon07/Source/UTILS.ob07 b/programs/develop/oberon07/source/UTILS.ob07 similarity index 85% rename from programs/develop/oberon07/Source/UTILS.ob07 rename to programs/develop/oberon07/source/UTILS.ob07 index 6b77353cbf..d854e0639f 100644 --- a/programs/develop/oberon07/Source/UTILS.ob07 +++ b/programs/develop/oberon07/source/UTILS.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2018-2020, Anton Krotov + Copyright (c) 2018-2021, Anton Krotov All rights reserved. *) @@ -23,7 +23,8 @@ CONST max32* = 2147483647; vMajor* = 1; - vMinor* = 43; + vMinor* = 52; + Date* = "07-may-2021"; FILE_EXT* = ".ob07"; RTL_NAME* = "RTL"; @@ -162,20 +163,9 @@ END Byte; PROCEDURE Align* (VAR bytes: INTEGER; align: INTEGER): BOOLEAN; -VAR - res: BOOLEAN; - BEGIN - IF bytes MOD align # 0 THEN - res := maxint - bytes >= align - (bytes MOD align); - IF res THEN - bytes := bytes + align - (bytes MOD align) - END - ELSE - res := TRUE - END - - RETURN res + INC(bytes, (-bytes) MOD align) + RETURN bytes >= 0 END Align; @@ -221,6 +211,6 @@ END hexdgt; BEGIN - time := GetTickCount(); + time := HOST.GetTickCount(); maxreal := HOST.maxreal END UTILS. \ No newline at end of file diff --git a/programs/develop/oberon07/Source/WRITER.ob07 b/programs/develop/oberon07/source/WRITER.ob07 similarity index 86% rename from programs/develop/oberon07/Source/WRITER.ob07 rename to programs/develop/oberon07/source/WRITER.ob07 index bfb1806769..14d7882ca6 100644 --- a/programs/develop/oberon07/Source/WRITER.ob07 +++ b/programs/develop/oberon07/source/WRITER.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2018-2020, Anton Krotov + Copyright (c) 2018-2021, Anton Krotov All rights reserved. *) @@ -18,10 +18,7 @@ VAR PROCEDURE align* (n, _align: INTEGER): INTEGER; BEGIN - IF n MOD _align # 0 THEN - INC(n, _align - (n MOD _align)) - END - + ASSERT(UTILS.Align(n, _align)) RETURN n END align; diff --git a/programs/develop/oberon07/Source/X86.ob07 b/programs/develop/oberon07/source/X86.ob07 similarity index 95% rename from programs/develop/oberon07/Source/X86.ob07 rename to programs/develop/oberon07/source/X86.ob07 index de17592282..7707771637 100644 --- a/programs/develop/oberon07/Source/X86.ob07 +++ b/programs/develop/oberon07/source/X86.ob07 @@ -1,7 +1,7 @@ (* BSD 2-Clause License - Copyright (c) 2018-2020, Anton Krotov + Copyright (c) 2018-2021, Anton Krotov All rights reserved. *) @@ -851,9 +851,7 @@ BEGIN IF opcode = IL.opLEAVER THEN UnOp(reg1); IF reg1 # eax THEN - GetRegA; - ASSERT(REG.Exchange(R, reg1, eax)); - drop + mov(eax, reg1) END; drop END; @@ -872,10 +870,8 @@ BEGIN pop(ebp); - n := param2; - IF n > 0 THEN - n := n * 4; - OutByte(0C2H); OutWord(n MOD 65536) (* ret n *) + IF param2 > 0 THEN + OutByte(0C2H); OutWord(param2 * 4 MOD 65536) (* ret param2*4 *) ELSE ret END @@ -1321,8 +1317,12 @@ BEGIN |IL.opCASELR: cmprc(eax, param1); - jcc(jl, param2); - jcc(jg, cmd.param3) + IF param2 = cmd.param3 THEN + jcc(jne, param2) + ELSE + jcc(jl, param2); + jcc(jg, cmd.param3) + END |IL.opCODE: OutByte(param2) @@ -2176,8 +2176,6 @@ BEGIN |IL.opFNAME: fname := cmd(IL.FNAMECMD).fname - |IL.opLOOP, IL.opENDLOOP: - END; cmd := cmd.next(COMMAND) @@ -2374,7 +2372,7 @@ BEGIN opt.pic := TRUE END; - REG.Init(R, push, pop, mov, xchg, NIL, NIL, {eax, ecx, edx}, {}); + REG.Init(R, push, pop, mov, xchg, {eax, ecx, edx}); prolog(opt.pic, target, opt.stack, dllinit, dllret); translate(opt.pic, tcount * 4); diff --git a/programs/develop/oberon07/tools/RVMxI.ob07 b/programs/develop/oberon07/tools/RVMxI.ob07 new file mode 100644 index 0000000000..af40b4481a --- /dev/null +++ b/programs/develop/oberon07/tools/RVMxI.ob07 @@ -0,0 +1,668 @@ +(* + BSD 2-Clause License + + Copyright (c) 2020-2021, Anton Krotov + All rights reserved. +*) + +(* + RVMxI executor and disassembler + + Usage: + RVMxI.exe -run [program parameters] + RVMxI.exe -dis +*) + +MODULE RVMxI; + +IMPORT SYSTEM, File, Args, Out, API, HOST; + + +CONST + + szWORD = HOST.bit_depth DIV 8; + + opSTOP = 0; opRET = 1; opENTER = 2; opNEG = 3; opNOT = 4; opNOP = 5; + opXCHG = 6; opLDB = 7; opLDH = 8; opLDW = 9; opPUSH = 10; opPUSHC = 11; + opPOP = 12; opLABEL = 13; opLEA = 14; opLLA = 15; + opLDD = 16; (* 17, 18 *) + opJMP = 19; opCALL = 20; opCALLI = 21; + + opMOV = 22; opMUL = 24; opADD = 26; opSUB = 28; opDIV = 30; opMOD = 32; + opSTB = 34; opSTH = 36; opSTW = 38; opSTD = 40; (* 42, 44 *) + opAND = 46; opOR = 48; opXOR = 50; opASR = 52; opLSR = 54; + opLSL = 56; opROR = 58; (* 60, 62 *) opCMP = 64; + + opMOVC = 23; opMULC = 25; opADDC = 27; opSUBC = 29; opDIVC = 31; opMODC = 33; + opSTBC = 35; opSTHC = 37; opSTWC = 39; opSTDC = 41; (* 43, 45 *) + opANDC = 47; opORC = 49; opXORC = 51; opASRC = 53; opLSRC = 55; + opLSLC = 57; opRORC = 59; (* 61, 63 *) opCMPC = 65; + + opBIT = 66; opSYSCALL = 67; opJBT = 68; opADDRC = 69; + + opJEQ = 70; opJNE = 71; opJLT = 72; opJGE = 73; opJGT = 74; opJLE = 75; + opSEQ = 76; opSNE = 77; opSLT = 78; opSGE = 79; opSGT = 80; opSLE = 81; + + + nREG = 16; + ACC = 0; BP = 3; SP = 4; + + Types = 0; + Strings = 1; + Global = 2; + Heap = 3; + Stack = 4; + + +TYPE + + COMMAND = POINTER TO RECORD + + op, param1, param2: INTEGER; + next, prev: COMMAND + + END; + + LABELS = ARRAY 30000 OF COMMAND; + + SECTIONS = ARRAY 5 OF INTEGER; + + +VAR + + Sections: SECTIONS; + + first, last: COMMAND; + + Labels: LABELS; + + F: INTEGER; buf: ARRAY 65536 OF BYTE; cnt: INTEGER; + + +PROCEDURE syscall (ptr: INTEGER); +VAR + fn, r, n: INTEGER; + + proc2: PROCEDURE (a, b: INTEGER): INTEGER; + proc3: PROCEDURE (a, b, c: INTEGER): INTEGER; + proc4: PROCEDURE (a, b, c, d: INTEGER): INTEGER; + + r1, r2: REAL; + + + PROCEDURE GetInt (ptr, n: INTEGER): INTEGER; + BEGIN + SYSTEM.GET(ptr + SYSTEM.SIZE(INTEGER) * n, n) + RETURN n + END GetInt; + + + PROCEDURE GetReal (ptr, n: INTEGER): REAL; + VAR + r: REAL; + + BEGIN + SYSTEM.GET(ptr + SYSTEM.SIZE(INTEGER) * n, r) + RETURN r + END GetReal; + + +BEGIN + fn := GetInt(ptr, 0); + CASE fn OF + | 0: + HOST.ExitProcess(GetInt(ptr, 1)) + + | 1: + SYSTEM.PUT(SYSTEM.ADR(proc2), SYSTEM.ADR(HOST.GetCurrentDirectory)); + r := proc2(GetInt(ptr, 1), GetInt(ptr, 2)) + + | 2: + n := GetInt(ptr, 1); + SYSTEM.PUT(SYSTEM.ADR(proc3), SYSTEM.ADR(HOST.GetArg)); + r := proc3(n - ORD(n = 0) + 2, GetInt(ptr, 2), GetInt(ptr, 3)) + + | 3: + SYSTEM.PUT(SYSTEM.ADR(proc4), SYSTEM.ADR(HOST.FileRead)); + SYSTEM.PUT(ptr, proc4(GetInt(ptr, 1), GetInt(ptr, 2), GetInt(ptr, 3), GetInt(ptr, 4))) + + | 4: + SYSTEM.PUT(SYSTEM.ADR(proc4), SYSTEM.ADR(HOST.FileWrite)); + SYSTEM.PUT(ptr, proc4(GetInt(ptr, 1), GetInt(ptr, 2), GetInt(ptr, 3), GetInt(ptr, 4))) + + | 5: + SYSTEM.PUT(SYSTEM.ADR(proc2), SYSTEM.ADR(HOST.FileCreate)); + SYSTEM.PUT(ptr, proc2(GetInt(ptr, 1), GetInt(ptr, 2))) + + | 6: + HOST.FileClose(GetInt(ptr, 1)) + + | 7: + SYSTEM.PUT(SYSTEM.ADR(proc2), SYSTEM.ADR(HOST.FileOpen)); + SYSTEM.PUT(ptr, proc2(GetInt(ptr, 1), GetInt(ptr, 2))) + + | 8: + HOST.OutChar(CHR(GetInt(ptr, 1))) + + | 9: + SYSTEM.PUT(ptr, HOST.GetTickCount()) + + |10: + SYSTEM.PUT(ptr, HOST.UnixTime()) + + |11: + SYSTEM.PUT(SYSTEM.ADR(proc2), SYSTEM.ADR(HOST.isRelative)); + SYSTEM.PUT(ptr, proc2(GetInt(ptr, 1), GetInt(ptr, 2))) + + |12: + SYSTEM.PUT(SYSTEM.ADR(proc2), SYSTEM.ADR(HOST.chmod)); + r := proc2(GetInt(ptr, 1), GetInt(ptr, 2)) + + |100..103: + r1 := GetReal(ptr, 1); + r2 := GetReal(ptr, 2); + CASE fn OF + |100: SYSTEM.PUT(ptr, r2 * r1) + |101: SYSTEM.PUT(ptr, r2 / r1) + |102: SYSTEM.PUT(ptr, r2 + r1) + |103: SYSTEM.PUT(ptr, r2 - r1) + END + + |104: + r1 := GetReal(ptr, 2); + r2 := GetReal(ptr, 3); + CASE GetInt(ptr, 1) OF + |0: SYSTEM.PUT(ptr, ORD(r2 = r1)) + |1: SYSTEM.PUT(ptr, ORD(r2 # r1)) + |2: SYSTEM.PUT(ptr, ORD(r2 < r1)) + |3: SYSTEM.PUT(ptr, ORD(r2 <= r1)) + |4: SYSTEM.PUT(ptr, ORD(r2 > r1)) + |5: SYSTEM.PUT(ptr, ORD(r2 >= r1)) + END + + |105: + SYSTEM.PUT(ptr, FLOOR(GetReal(ptr, 1))) + + |106: + SYSTEM.PUT(ptr, FLT(GetInt(ptr, 1))) + + END +END syscall; + + +PROCEDURE exec (VAR Labels: LABELS; first, last: COMMAND; Sections: SECTIONS); +VAR + cmd: COMMAND; + param1, param2, i: INTEGER; + R: ARRAY nREG OF INTEGER; + + fe, fl, fb: BOOLEAN; + +BEGIN + FOR i := 0 TO LEN(Labels) - 1 DO + cmd := Labels[i]; + IF cmd # NIL THEN + REPEAT + cmd := cmd.next + UNTIL cmd.op # opLABEL; + Labels[i] := cmd + END + END; + + cmd := first; + WHILE cmd # NIL DO + IF cmd.op = opLABEL THEN + cmd.prev.next := cmd.next; + cmd.next.prev := cmd.prev + END; + cmd := cmd.next + END; + + FOR i := 0 TO LEN(Labels) - 1 DO + IF Labels[i] # NIL THEN + Labels[i] := Labels[i].prev + END + END; + + cmd := first; + WHILE cmd # NIL DO + param1 := cmd.param1; + param2 := cmd.param2; + + CASE cmd.op OF + |opSTOP: cmd := last + |opRET: SYSTEM.GET(R[SP], cmd); INC(R[SP], szWORD) + |opENTER: DEC(R[SP], szWORD); SYSTEM.PUT(R[SP], R[BP]); R[BP] := R[SP]; + WHILE param1 > 0 DO DEC(R[SP], szWORD); SYSTEM.PUT(R[SP], 0); DEC(param1) END + |opPOP: SYSTEM.GET(R[SP], R[param1]); INC(R[SP], szWORD) + |opPUSH: DEC(R[SP], szWORD); SYSTEM.PUT(R[SP], R[param1]) + |opPUSHC: DEC(R[SP], szWORD); SYSTEM.PUT(R[SP], param1) + |opCALL: DEC(R[SP], szWORD); SYSTEM.PUT(R[SP], cmd); cmd := Labels[param1] + |opCALLI: DEC(R[SP], szWORD); SYSTEM.PUT(R[SP], cmd); SYSTEM.GET(SYSTEM.ADR(R[param1]), cmd) + |opNEG: R[param1] := -R[param1] + |opNOT: R[param1] := ORD(-BITS(R[param1])) + |opNOP: + |opXCHG: i := R[param1]; R[param1] := R[param2]; R[param2] := i + |opLDB: i := param1 MOD 256; SYSTEM.GET8(R[param1 DIV 256] + param2, R[i]); R[i] := R[i] MOD 256 + |opLDH: i := param1 MOD 256; SYSTEM.GET16(R[param1 DIV 256] + param2, R[i]); R[i] := R[i] MOD 65536 + |opLDW: SYSTEM.GET32(R[param1 DIV 256] + param2, R[param1 MOD 256]); + $IF (CPU_X8664) + R[param1 MOD 256] := R[param1 MOD 256] MOD 100000000H + $END + |opLDD: SYSTEM.GET(R[param1 DIV 256] + param2, R[param1 MOD 256]) + |opLLA: SYSTEM.GET(SYSTEM.ADR(Labels[param2]), R[param1]) + |opJMP: cmd := Labels[param1] + |opMOV: R[param1] := R[param2] + |opMOVC: R[param1] := param2 + |opMUL: R[param1] := R[param1] * R[param2] + |opMULC: R[param1] := R[param1] * param2 + |opADD: INC(R[param1], R[param2]) + |opADDC: INC(R[param1], param2) + |opSUB: DEC(R[param1], R[param2]) + |opSUBC: DEC(R[param1], param2) + |opDIV: R[param1] := R[param1] DIV R[param2] + |opDIVC: R[param1] := R[param1] DIV param2 + |opMOD: R[param1] := R[param1] MOD R[param2] + |opMODC: R[param1] := R[param1] MOD param2 + |opSTB: SYSTEM.PUT8(R[param1 DIV 256] + param2, R[param1 MOD 256]) + |opSTH: SYSTEM.PUT16(R[param1 DIV 256] + param2, R[param1 MOD 256]) + |opSTW: SYSTEM.PUT32(R[param1 DIV 256] + param2, R[param1 MOD 256]) + |opSTD: SYSTEM.PUT(R[param1 DIV 256] + param2, R[param1 MOD 256]) + |opSTBC: SYSTEM.PUT8(R[param1], param2) + |opSTHC: SYSTEM.PUT16(R[param1], param2) + |opSTWC: SYSTEM.PUT32(R[param1], param2) + |opSTDC: SYSTEM.PUT(R[param1], param2) + |opAND: R[param1] := ORD(BITS(R[param1]) * BITS(R[param2])) + |opANDC: R[param1] := ORD(BITS(R[param1]) * BITS(param2)) + |opOR: R[param1] := ORD(BITS(R[param1]) + BITS(R[param2])) + |opORC: R[param1] := ORD(BITS(R[param1]) + BITS(param2)) + |opXOR: R[param1] := ORD(BITS(R[param1]) / BITS(R[param2])) + |opXORC: R[param1] := ORD(BITS(R[param1]) / BITS(param2)) + |opASR: R[param1] := ASR(R[param1], R[param2]) + |opASRC: R[param1] := ASR(R[param1], param2) + |opLSR: R[param1] := LSR(R[param1], R[param2]) + |opLSRC: R[param1] := LSR(R[param1], param2) + |opLSL: R[param1] := LSL(R[param1], R[param2]) + |opLSLC: R[param1] := LSL(R[param1], param2) + |opROR: R[param1] := ROR(R[param1], R[param2]) + |opRORC: R[param1] := ROR(R[param1], param2) + |opLEA: R[param1 MOD 256] := Sections[param1 DIV 256] + param2 + (*|opLABEL:*) + |opSYSCALL: syscall(R[param1]) + |opADDRC: R[param1 MOD 256] := R[param1 DIV 256] + param2 + |opCMP: fl := R[param1] < R[param2]; fe := R[param1] = R[param2]; fb := fl & (R[param1] >= 0) + |opCMPC: fl := R[param1] < param2; fe := R[param1] = param2; fb := fl & (R[param1] >= 0) + |opJEQ: IF fe THEN cmd := Labels[param1] END + |opJNE: IF ~fe THEN cmd := Labels[param1] END + |opJLT: IF fl THEN cmd := Labels[param1] END + |opJLE: IF fl OR fe THEN cmd := Labels[param1] END + |opJGT: IF ~fl & ~fe THEN cmd := Labels[param1] END + |opJGE: IF ~fl THEN cmd := Labels[param1] END + |opSEQ: R[param1] := ORD(fe) + |opSNE: R[param1] := ORD(~fe) + |opSLT: R[param1] := ORD(fl) + |opSLE: R[param1] := ORD(fl OR fe) + |opSGT: R[param1] := ORD(~fl & ~fe) + |opSGE: R[param1] := ORD(~fl) + |opJBT: IF fb THEN cmd := Labels[param1] END + |opBIT: R[param1] := ORD({R[param2]}) + END; + cmd := cmd.next + END +END exec; + + +PROCEDURE disasm (name: ARRAY OF CHAR; t_count, c_count, glob, heap: INTEGER); +VAR + cmd: COMMAND; + param1, param2, i, t, ptr: INTEGER; + b: BYTE; + Names: ARRAY 5, 16 OF CHAR; + + + PROCEDURE String (s: ARRAY OF CHAR); + VAR + n: INTEGER; + + BEGIN + n := LENGTH(s); + IF n > LEN(buf) - cnt THEN + ASSERT(File.Write(F, SYSTEM.ADR(buf[0]), cnt) = cnt); + cnt := 0 + END; + SYSTEM.MOVE(SYSTEM.ADR(s[0]), SYSTEM.ADR(buf[0]) + cnt, n); + INC(cnt, n) + END String; + + + PROCEDURE Ln; + BEGIN + String(0DX + 0AX) + END Ln; + + + PROCEDURE hexdgt (n: INTEGER): CHAR; + BEGIN + IF n < 10 THEN + INC(n, ORD("0")) + ELSE + INC(n, ORD("A") - 10) + END + + RETURN CHR(n) + END hexdgt; + + + PROCEDURE Hex (x: INTEGER); + VAR + str: ARRAY 19 OF CHAR; + n: INTEGER; + + BEGIN + n := szWORD * 2 + 2; + str[n] := 0X; + WHILE n > 2 DO + str[n - 1] := hexdgt(x MOD 16); + x := x DIV 16; + DEC(n) + END; + str[1] := "x"; + str[0] := "0"; + String(str) + END Hex; + + + PROCEDURE Byte (x: BYTE); + VAR + str: ARRAY 5 OF CHAR; + + BEGIN + str[4] := 0X; + str[3] := hexdgt(x MOD 16); + str[2] := hexdgt(x DIV 16); + str[1] := "x"; + str[0] := "0"; + String(str) + END Byte; + + + PROCEDURE Reg (n: INTEGER); + VAR + s: ARRAY 2 OF CHAR; + BEGIN + IF n = BP THEN + String("BP") + ELSIF n = SP THEN + String("SP") + ELSE + String("R"); + s[1] := 0X; + IF n >= 10 THEN + s[0] := CHR(n DIV 10 + ORD("0")); + String(s) + END; + s[0] := CHR(n MOD 10 + ORD("0")); + String(s) + END + END Reg; + + + PROCEDURE Reg2 (r1, r2: INTEGER); + BEGIN + Reg(r1); String(", "); Reg(r2) + END Reg2; + + + PROCEDURE RegC (r, c: INTEGER); + BEGIN + Reg(r); String(", "); Hex(c) + END RegC; + + + PROCEDURE RegL (r, label: INTEGER); + BEGIN + Reg(r); String(", L"); Hex(label) + END RegL; + + +BEGIN + Names[Types] := "TYPES"; + Names[Strings] := "STRINGS"; + Names[Global] := "GLOBAL"; + Names[Heap] := "HEAP"; + Names[Stack] := "STACK"; + + F := File.Create(name); + ASSERT(F > 0); + cnt := 0; + String("CODE:"); Ln; + cmd := first; + WHILE cmd # NIL DO + param1 := cmd.param1; + param2 := cmd.param2; + CASE cmd.op OF + |opSTOP: String("STOP") + |opRET: String("RET") + |opENTER: String("ENTER "); Hex(param1) + |opPOP: String("POP "); Reg(param1) + |opNEG: String("NEG "); Reg(param1) + |opNOT: String("NOT "); Reg(param1) + |opNOP: String("NOP") + |opXCHG: String("XCHG "); Reg2(param1, param2) + |opLDB: String("LDB "); Reg(param1 MOD 256); String(", ["); Reg(param1 DIV 256); String(" + "); Hex(param2); String("]") + |opLDH: String("LDH "); Reg(param1 MOD 256); String(", ["); Reg(param1 DIV 256); String(" + "); Hex(param2); String("]") + |opLDW: String("LDW "); Reg(param1 MOD 256); String(", ["); Reg(param1 DIV 256); String(" + "); Hex(param2); String("]") + |opLDD: String("LDD "); Reg(param1 MOD 256); String(", ["); Reg(param1 DIV 256); String(" + "); Hex(param2); String("]") + |opPUSH: String("PUSH "); Reg(param1) + |opPUSHC: String("PUSH "); Hex(param1) + |opLLA: String("LLA "); RegL(param1, param2) + |opJMP: String("JMP L"); Hex(param1) + |opCALL: String("CALL L"); Hex(param1) + |opCALLI: String("CALL "); Reg(param1) + |opMOV: String("MOV "); Reg2(param1, param2) + |opMOVC: String("MOV "); RegC(param1, param2) + |opMUL: String("MUL "); Reg2(param1, param2) + |opMULC: String("MUL "); RegC(param1, param2) + |opADD: String("ADD "); Reg2(param1, param2) + |opADDC: String("ADD "); RegC(param1, param2) + |opSUB: String("SUB "); Reg2(param1, param2) + |opSUBC: String("SUB "); RegC(param1, param2) + |opDIV: String("DIV "); Reg2(param1, param2) + |opDIVC: String("DIV "); RegC(param1, param2) + |opMOD: String("MOD "); Reg2(param1, param2) + |opMODC: String("MOD "); RegC(param1, param2) + |opSTB: String("STB ["); Reg(param1 DIV 256); String(" + "); Hex(param2); String("], "); Reg(param1 MOD 256) + |opSTH: String("STH ["); Reg(param1 DIV 256); String(" + "); Hex(param2); String("], "); Reg(param1 MOD 256) + |opSTW: String("STW ["); Reg(param1 DIV 256); String(" + "); Hex(param2); String("], "); Reg(param1 MOD 256) + |opSTD: String("STD ["); Reg(param1 DIV 256); String(" + "); Hex(param2); String("], "); Reg(param1 MOD 256) + |opSTBC: String("STB ["); Reg(param1); String("], "); Hex(param2) + |opSTHC: String("STH ["); Reg(param1); String("], "); Hex(param2) + |opSTWC: String("STW ["); Reg(param1); String("], "); Hex(param2) + |opSTDC: String("STD ["); Reg(param1); String("], "); Hex(param2) + |opAND: String("AND "); Reg2(param1, param2) + |opANDC: String("AND "); RegC(param1, param2) + |opOR: String("OR "); Reg2(param1, param2) + |opORC: String("OR "); RegC(param1, param2) + |opXOR: String("XOR "); Reg2(param1, param2) + |opXORC: String("XOR "); RegC(param1, param2) + |opASR: String("ASR "); Reg2(param1, param2) + |opASRC: String("ASR "); RegC(param1, param2) + |opLSR: String("LSR "); Reg2(param1, param2) + |opLSRC: String("LSR "); RegC(param1, param2) + |opLSL: String("LSL "); Reg2(param1, param2) + |opLSLC: String("LSL "); RegC(param1, param2) + |opROR: String("ROR "); Reg2(param1, param2) + |opRORC: String("ROR "); RegC(param1, param2) + |opLEA: String("LEA "); Reg(param1 MOD 256); String(", "); String(Names[param1 DIV 256]); String(" + "); Hex(param2) + |opADDRC: String("ADD "); Reg(param1 MOD 256); String(", "); Reg(param1 DIV 256); String(", "); Hex(param2) + |opLABEL: String("L"); Hex(param1); String(":") + |opSYSCALL: String("SYSCALL "); Reg(param1) + |opCMP: String("CMP "); Reg2(param1, param2) + |opCMPC: String("CMP "); RegC(param1, param2) + |opJEQ: String("JEQ L"); Hex(param1) + |opJNE: String("JNE L"); Hex(param1) + |opJLT: String("JLT L"); Hex(param1) + |opJLE: String("JLE L"); Hex(param1) + |opJGT: String("JGT L"); Hex(param1) + |opJGE: String("JGE L"); Hex(param1) + |opSEQ: String("SEQ "); Reg(param1) + |opSNE: String("SNE "); Reg(param1) + |opSLT: String("SLT "); Reg(param1) + |opSLE: String("SLE "); Reg(param1) + |opSGT: String("SGT "); Reg(param1) + |opSGE: String("SGE "); Reg(param1) + |opJBT: String("JBT L"); Hex(param1) + |opBIT: String("BIT "); Reg2(param1, param2) + END; + Ln; + cmd := cmd.next + END; + + String("TYPES:"); + ptr := Sections[Types]; + FOR i := 0 TO t_count - 1 DO + IF i MOD 4 = 0 THEN + Ln; String("WORD ") + ELSE + String(", ") + END; + SYSTEM.GET(ptr, t); INC(ptr, szWORD); + Hex(t) + END; + Ln; + + String("STRINGS:"); + ptr := Sections[Strings]; + FOR i := 0 TO c_count - 1 DO + IF i MOD 8 = 0 THEN + Ln; String("BYTE ") + ELSE + String(", ") + END; + SYSTEM.GET8(ptr, b); INC(ptr); + Byte(b) + END; + Ln; + + String("GLOBAL:"); Ln; + String("WORDS "); Hex(glob); Ln; + String("HEAP:"); Ln; + String("WORDS "); Hex(heap); Ln; + String("STACK:"); Ln; + String("WORDS 8"); Ln; + + ASSERT(File.Write(F, SYSTEM.ADR(buf[0]), cnt) = cnt); + File.Close(F) +END disasm; + + +PROCEDURE GetCommand (adr: INTEGER): COMMAND; +VAR + op, param1, param2: INTEGER; + res: COMMAND; + +BEGIN + op := 0; param1 := 0; param2 := 0; + SYSTEM.GET(adr, op); + SYSTEM.GET(adr + szWORD, param1); + SYSTEM.GET(adr + szWORD * 2, param2); + NEW(res); + res.op := op; + res.param1 := param1; + res.param2 := param2; + res.next := NIL + + RETURN res +END GetCommand; + + +PROCEDURE main; +VAR + name, param: ARRAY 1024 OF CHAR; + cmd: COMMAND; + file, fsize, n: INTEGER; + + descr: ARRAY 12 OF INTEGER; + + offTypes, offStrings, GlobalSize, HeapStackSize, DescrSize: INTEGER; + +BEGIN + Out.Open; + Args.GetArg(1, name); + F := File.Open(name, File.OPEN_R); + IF F > 0 THEN + DescrSize := LEN(descr) * SYSTEM.SIZE(INTEGER); + fsize := File.Seek(F, 0, File.SEEK_END); + ASSERT(fsize > DescrSize); + file := API._NEW(fsize); + ASSERT(file # 0); + n := File.Seek(F, 0, File.SEEK_BEG); + ASSERT(fsize = File.Read(F, file, fsize)); + File.Close(F); + + SYSTEM.MOVE(file + fsize - DescrSize, SYSTEM.ADR(descr[0]), DescrSize); + offTypes := descr[0]; + ASSERT(offTypes < fsize - DescrSize); + ASSERT(offTypes > 0); + ASSERT(offTypes MOD (3 * szWORD) = 0); + offStrings := descr[1]; + ASSERT(offStrings < fsize - DescrSize); + ASSERT(offStrings > 0); + ASSERT(offStrings MOD szWORD = 0); + ASSERT(offStrings > offTypes); + GlobalSize := descr[2]; + ASSERT(GlobalSize > 0); + HeapStackSize := descr[3]; + ASSERT(HeapStackSize > 0); + + Sections[Types] := API._NEW(offStrings - offTypes); + ASSERT(Sections[Types] # 0); + SYSTEM.MOVE(file + offTypes, Sections[Types], offStrings - offTypes); + + Sections[Strings] := API._NEW(fsize - offStrings - DescrSize); + ASSERT(Sections[Strings] # 0); + SYSTEM.MOVE(file + offStrings, Sections[Strings], fsize - offStrings - DescrSize); + + Sections[Global] := API._NEW(GlobalSize * szWORD); + ASSERT(Sections[Global] # 0); + + Sections[Heap] := API._NEW(HeapStackSize * szWORD); + ASSERT(Sections[Heap] # 0); + + Sections[Stack] := Sections[Heap] + HeapStackSize * szWORD - szWORD*8; + + n := offTypes DIV (3 * szWORD); + + first := GetCommand(file + offTypes - n * (3 * szWORD)); + first.prev := NIL; + last := first; + DEC(n); + WHILE n > 0 DO + cmd := GetCommand(file + offTypes - n * (3 * szWORD)); + IF cmd.op = opLABEL THEN + Labels[cmd.param1] := cmd + END; + last.next := cmd; + cmd.prev := last; + last := cmd; + DEC(n) + END; + file := API._DISPOSE(file); + Args.GetArg(2, param); + IF param = "-dis" THEN + Args.GetArg(3, name); + IF name # "" THEN + disasm(name, (offStrings - offTypes) DIV szWORD, fsize - offStrings - DescrSize, GlobalSize, HeapStackSize) + END + ELSIF param = "-run" THEN + exec(Labels, first, last, Sections) + END + ELSE + Out.String("file not found"); Out.Ln + END +END main; + + +BEGIN + main +END RVMxI. \ No newline at end of file diff --git a/programs/develop/oberon07/tools/RVMxI.txt b/programs/develop/oberon07/tools/RVMxI.txt new file mode 100644 index 0000000000..945ef862be --- /dev/null +++ b/programs/develop/oberon07/tools/RVMxI.txt @@ -0,0 +1,270 @@ + + Экспериментальная 32/64-битная виртуальная машина RVMxI +--------------------------------------------------------------------------------------------------- + +Использование + + Скомпилировать исполнитель/дизассемблер в .\tools\RVMxI.ob07 + для Windows32/64 Console или Linux32/64: + + Compiler.exe .\tools\RVMxI.ob07 win32con -nochk a -out RVMxI.exe + Compiler.exe .\tools\RVMxI.ob07 win64con -nochk a -out RVMxI.exe + Compiler ./tools/RVMxI.ob07 linux32exe -nochk a -out RVMxI + Compiler ./tools/RVMxI.ob07 linux64exe -nochk a -out RVMxI + + Будет создан файл "RVMxI.exe" и/или "RVMxI". + + Компилировать программу в байт-код RVMxI: + + Compiler.exe program.ob07 rvm32i [-ram size] [-def host_linux] + Compiler.exe program.ob07 rvm64i [-ram size] [-def host_linux] + -ram size -- установить размер оперативной памяти для программы в килобайтах 32768..262144 + (32..256 Мбайт), по умолчанию 32768 (32 Мбайт) + -def host_linux -- если байт-код будет исполняться на Linux (по умолчанию -- Windows) + + Будет создан файл "program.bin". + + Выпонить программу: + + RVMxI.exe program.bin -run <параметры> + + Дизассемблировать программу: + + RVMxI.exe program.bin -dis program.txt + + Будет создан файл "program.txt". +--------------------------------------------------------------------------------------------------- + +Архитектура + + Регистры + + Не меньше пяти 32/64-битных регистров: + + R0, R1, R2 регистры общего назначения + BP(R3) указатель кадра стэка + SP(R4) указатель стэка (растет вниз) + + R5, R6... регистры общего назначения (опционально) + + Регистра связи нет (адрес возврата передается через стэк), + регистр-счетчик команд (PC) -- скрытый, регистр флагов -- скрытый. + + Нет вещественных регистров, операции с плавающей точкой (single (32-бит) или double (64-бит)) + эмулируются. + + Формат кадра стэка + + Стэк: + + меньше <- |лок. переменные|старый BP|адрес возврата|парам1|парам2|...|парамN| -> больше + + (* 32 бита *) + адрес(парам1) = BP + 8 + адрес(парам2) = BP + 12 + ... + + (* 64 бита *) + адрес(парам1) = BP + 16 + адрес(парам2) = BP + 24 + ... + + Параметры передаются через стэк справа налево (как cdecl), результат передается через R0, + вызывающая процедура очищает стэк (как cdecl). + +--------------------------------------------------------------------------------------------------- + +Формат "исполняемого" файла + + RECORD + + Text: ARRAY i OF RECORD opcode, param1, param2: INTEGER END; (* байт-код *) + Types: ARRAY t OF INTEGER; (* таблица типов-записей *) + Strings: ARRAY s OF BYTE; (* строковые литералы *) + offTypes: INTEGER; (* смещение таблицы типов-записей от начала файла (в байтах) *) + offStrings: INTEGER; (* смещение строковых литералов от начала файла (в байтах) *) + GlobalSize: INTEGER; (* размер глобальных переменных (в словах; слово = 4 байта) *) + HeapStackSize: INTEGER; (* размер области кучи/стэка (в словах; слово = 4 байта) *) + Reserved: ARRAY 8 OF INTEGER (* зарезервировано *) + + END + + Где: + + INTEGER = INT32/INT64 + i = offTypes DIV (3 * sizeof(INTEGER)); + t = (offStrings - offTypes) DIV sizeof(INTEGER) + s = FILE_SIZE - offStrings - 12 * sizeof(INTEGER) +--------------------------------------------------------------------------------------------------- + +Система команд + + мнемоника опкод парам1 парам2 действие + + STOP 0 0 0 остановить программу + RET 1 0 0 возврат из процедуры (pop PC) + ENTER imm 2 imm 0 push BP; BP := SP; WHILE imm > 0 DO push 0; DEC(imm) END + NEG Rn 3 n 0 Rn := -Rn + NOT Rn 4 n 0 Rn := ORD(-BITS(Rn)) + NOP 5 0 0 нет операции + XCHG Rn, Rm 6 n m temp := Rn; Rn := Rm; Rm := temp + LDB Rn, [Rm + imm] 7 m*256 + n imm Rn := UInt8Ptr(Rm + imm)^ + LDH Rn, [Rm + imm] 8 m*256 + n imm Rn := UInt16Ptr(Rm + imm)^ + LDW Rn, [Rm + imm] 9 m*256 + n imm Rn := UInt32Ptr(Rm + imm)^ +* PUSH Rn 10 n 0 DEC(SP, 4); UInt32Ptr(SP)^ := Rn +* PUSH imm 11 imm 0 DEC(SP, 4); UInt32Ptr(SP)^ := imm +* POP Rn 12 n 0 Rn := UInt32Ptr(SP)^; INC(SP, 4) +** PUSH Rn 10 n 0 DEC(SP, 8); UInt64Ptr(SP)^ := Rn +** PUSH imm 11 imm 0 DEC(SP, 8); UInt64Ptr(SP)^ := imm +** POP Rn 12 n 0 Rn := UInt64Ptr(SP)^; INC(SP, 8) + L#hex: 13 hex 0 метка: + LEA Rn, TYPES + imm 14 n + 000H imm Rn := imm + address(TYPES) + LEA Rn, STRINGS + imm 14 n + 100H imm Rn := imm + address(STRINGS) + LEA Rn, GLOBAL + imm 14 n + 200H imm Rn := imm + address(GLOBAL) + LEA Rn, HEAP + imm 14 n + 300H imm Rn := imm + address(HEAP) + LEA Rn, STACK + imm 14 n + 400H imm Rn := imm + address(STACK) + LLA Rn, L#hex 15 n hex Rn := address(L#hex) +** LDD Rn, [Rm + imm] 16 m*256 + n imm Rn := UInt64Ptr(Rm + imm)^ + + JMP L#hex 19 hex 0 goto L#hex + CALL L#hex 20 hex 0 push PC; goto L#hex + CALL Rn 21 n 0 push PC; goto Rn + MOV Rn, Rm 22 n m Rn := Rm + MOV Rn, imm 23 n imm Rn := imm + MUL Rn, Rm 24 n m Rn := Rn * Rm + MUL Rn, imm 25 n imm Rn := Rm * imm + ADD Rn, Rm 26 n m Rn := Rn + Rm + ADD Rn, imm 27 n imm Rn := Rn + imm + SUB Rn, Rm 28 n m Rn := Rn - Rm + SUB Rn, imm 29 n imm Rn := Rn - imm + DIV Rn, Rm 30 n m Rn := Rn DIV Rm + DIV Rn, imm 31 n imm Rn := Rn DIV imm + MOD Rn, Rm 32 n m Rn := Rn MOD Rm + MOD Rn, imm 33 n imm Rn := Rn MOD imm + STB [Rn + imm], Rm 34 n*256 + m imm UInt8Ptr(Rn + imm)^ := Rm MOD 256 + STB [Rn], imm 35 n imm UInt8Ptr(Rn)^ := imm MOD 256 + STH [Rn + imm], Rm 36 n*256 + m imm UInt16Ptr(Rn + imm)^ := Rm MOD 65536 + STH [Rn], imm 37 n imm UInt16Ptr(Rn)^ := imm MOD 65536 +* STW [Rn + imm], Rm 38 n*256 + m imm UInt32Ptr(Rn + imm)^ := Rm +* STW [Rn], imm 39 n imm UInt32Ptr(Rn)^ := imm +** STW [Rn + imm], Rm 38 n*256 + m imm UInt32Ptr(Rn + imm)^ := Rm MOD 100000000H +** STW [Rn], imm 39 n imm UInt32Ptr(Rn)^ := imm MOD 100000000H +** STD [Rn + imm], Rm 40 n*256 + m imm UInt64Ptr(Rn + imm)^ := Rm +** STD [Rn], imm 41 n imm UInt64Ptr(Rn)^ := imm + + AND Rn, Rm 46 n m Rn := ORD(BITS(Rn) * BITS(Rm)) + AND Rn, imm 47 n imm Rn := ORD(BITS(Rn) * BITS(imm)) + OR Rn, Rm 48 n m Rn := ORD(BITS(Rn) + BITS(Rm)) + OR Rn, imm 49 n imm Rn := ORD(BITS(Rn) + BITS(imm)) + XOR Rn, Rm 50 n m Rn := ORD(BITS(Rn) / BITS(Rm)) + XOR Rn, imm 51 n imm Rn := ORD(BITS(Rn) / BITS(imm)) + ASR Rn, Rm 52 n m Rn := ASR(Rn, Rm) + ASR Rn, imm 53 n imm Rn := ASR(Rn, imm) + LSR Rn, Rm 54 n m Rn := LSR(Rn, Rm) + LSR Rn, imm 55 n imm Rn := LSR(Rn, imm) + LSL Rn, Rm 56 n m Rn := LSL(Rn, Rm) + LSL Rn, imm 57 n imm Rn := LSL(Rn, imm) + ROR Rn, Rm 58 n m Rn := ROR(Rn, Rm) + ROR Rn, imm 59 n imm Rn := ROR(Rn, imm) + + CMP Rn, Rm 64 n m сравнить Rn и Rm + CMP Rn, imm 65 n imm сравнить Rn и imm + BIT Rn, Rm 66 n m Rn := ORD({Rm}) + SYSCALL Rn 67 n 0 системный вызов; Rn содержит адрес параметров + JBT L#hex 68 hex 0 перейти на метку L#hex, если "ниже" + ADD Rn, Rm, imm 69 m*256 + n imm Rn := Rm + imm + JEQ L#hex 70 hex 0 перейти на метку L#hex, если "равно" + JNE L#hex 71 hex 0 перейти на метку L#hex, если "не равно" + JLT L#hex 72 hex 0 перейти на метку L#hex, если "меньше" + JGE L#hex 73 hex 0 перейти на метку L#hex, если "не меньше" + JGT L#hex 74 hex 0 перейти на метку L#hex, если "больше" + JLE L#hex 75 hex 0 перейти на метку L#hex, если "не больше" + SEQ Rn 76 n 0 если "равно": Rn := 1, иначе Rn := 0 + SNE Rn 77 n 0 если "не равно": Rn := 1, иначе Rn := 0 + SLT Rn 78 n 0 если "меньше": Rn := 1, иначе Rn := 0 + SGE Rn 79 n 0 если "не меньше": Rn := 1, иначе Rn := 0 + SGT Rn 80 n 0 если "больше": Rn := 1, иначе Rn := 0 + SLE Rn 81 n 0 если "не больше": Rn := 1, иначе Rn := 0 + +Команда CMP сохраняет результат сравнения в скрытом регистре, этот результат используется +в командах перехода по условию (JEQ, JNE, JLT, JGE, JGT, JLE, JBT) а также в командах +установки регистра по условию (SEQ, SNE, SLT, SGE, SGT, SLE). + +* Команда для 32-битной виртуальной машины +** Команда для 64-битной виртуальной машины + +--------------------------------------------------------------------------------------------------- + +Общая структура программы + + CODE: (* машинный код *) + LEA SP, STACK + 0x00000000 (* точка входа; инициализация регистра SP *) + ... + STOP (* конец программы *) + + TYPES: (* таблица типов-записей *) + WORD 0x00000000, 0x00000000, 0x00000000, 0x00000000 + WORD 0x00000002, 0x00000002, 0x00000002, 0x00000002 + WORD 0x00000000, 0x00000006, 0x00000000, 0x00000000 + WORD 0x00000002, 0x00000000, 0x0000000D, 0x0000000E + WORD 0x0000000C, 0x0000000E, 0x0000000C, 0x00000000 + WORD 0x00000000, 0x0000000C, 0x0000000C, 0x00000016 + WORD 0x00000000, 0x0000000C, 0x0000000C, 0x0000000C + WORD 0x00000000, 0x00000000, 0x0000000C, 0x0000000C + WORD 0x0000000C, 0x0000000C, 0x0000000C, 0x0000000C + WORD 0x0000000C, 0x0000000C, 0x00000000, 0x00000000 + WORD 0x0000000C, 0x0000000C, 0x0000000C, 0x00000000 + WORD 0x00000000, 0x0000000C, 0x0000002D, 0x0000002D + WORD 0x0000002D, 0x00000030, 0x00000030, 0x00000030 + WORD 0x00000030, 0x0000002D, 0x00000000, 0x00000000 + WORD 0x0000000A, 0x00000000, 0x00000002, 0x00000000 + WORD 0x00000000, 0x00000000, 0x00000000, 0x00000000 + WORD 0x00000000, 0x00000000, 0x00000000, 0x00000000 + WORD 0x00000000, 0x0000000C, 0x0000000C, 0x00000000 + WORD 0x00000000, 0x0000000C, 0x00000049, 0x00000049 + WORD 0x00000049, 0x0000004C, 0x0000004C, 0x0000004C + WORD 0x00000049, 0x0000000C, 0x00000000, 0x0000000C + WORD 0x00000053, 0x00000053, 0x00000053, 0x00000053 + WORD 0x0000000C, 0x00000000, 0x00000000, 0x00000000 + WORD 0x00000006, 0x0000000C + + STRINGS: (* строковые литералы *) + BYTE 0x46, 0x50, 0x55, 0x00, 0x54, 0x72, 0x61, 0x70 + BYTE 0x00, 0x0D, 0x0A, 0x00, 0x61, 0x73, 0x73, 0x65 + BYTE 0x72, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x66, 0x61 + BYTE 0x69, 0x6C, 0x75, 0x72, 0x65, 0x00, 0x4E, 0x49 + BYTE 0x4C, 0x20, 0x64, 0x65, 0x72, 0x65, 0x66, 0x65 + BYTE 0x72, 0x65, 0x6E, 0x63, 0x65, 0x00, 0x62, 0x61 + BYTE 0x64, 0x20, 0x64, 0x69, 0x76, 0x69, 0x73, 0x6F + BYTE 0x72, 0x00, 0x4E, 0x49, 0x4C, 0x20, 0x70, 0x72 + BYTE 0x6F, 0x63, 0x65, 0x64, 0x75, 0x72, 0x65, 0x20 + BYTE 0x63, 0x61, 0x6C, 0x6C, 0x00, 0x74, 0x79, 0x70 + BYTE 0x65, 0x20, 0x67, 0x75, 0x61, 0x72, 0x64, 0x20 + BYTE 0x65, 0x72, 0x72, 0x6F, 0x72, 0x00, 0x69, 0x6E + BYTE 0x64, 0x65, 0x78, 0x20, 0x6F, 0x75, 0x74, 0x20 + BYTE 0x6F, 0x66, 0x20, 0x72, 0x61, 0x6E, 0x67, 0x65 + BYTE 0x00, 0x69, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64 + BYTE 0x20, 0x43, 0x41, 0x53, 0x45, 0x00, 0x61, 0x72 + BYTE 0x72, 0x61, 0x79, 0x20, 0x61, 0x73, 0x73, 0x69 + BYTE 0x67, 0x6E, 0x6D, 0x65, 0x6E, 0x74, 0x20, 0x65 + BYTE 0x72, 0x72, 0x6F, 0x72, 0x00, 0x43, 0x48, 0x52 + BYTE 0x20, 0x6F, 0x75, 0x74, 0x20, 0x6F, 0x66, 0x20 + BYTE 0x72, 0x61, 0x6E, 0x67, 0x65, 0x00, 0x57, 0x43 + BYTE 0x48, 0x52, 0x20, 0x6F, 0x75, 0x74, 0x20, 0x6F + BYTE 0x66, 0x20, 0x72, 0x61, 0x6E, 0x67, 0x65, 0x00 + BYTE 0x42, 0x59, 0x54, 0x45, 0x20, 0x6F, 0x75, 0x74 + BYTE 0x20, 0x6F, 0x66, 0x20, 0x72, 0x61, 0x6E, 0x67 + BYTE 0x65, 0x00, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x20 + BYTE 0x28, 0x00, 0x29, 0x3A, 0x20, 0x00, 0x6D, 0x6F + BYTE 0x64, 0x75, 0x6C, 0x65, 0x3A, 0x20, 0x00, 0x6C + BYTE 0x69, 0x6E, 0x65, 0x3A, 0x20, 0x00, 0x52, 0x54 + BYTE 0x4C, 0x00, 0x54, 0x65, 0x73, 0x74, 0x00, 0x00 + + GLOBAL: + WORDS 0x00000004 (* размер глобальных переменных в словах (слово = 4 или 8 байт) *) + + HEAP: + WORDS 0x007FFFBF (* размер области кучи/стэка в словах (слово = 4 или 8 байт) *) + STACK: + WORDS 8 (* зарезервировано *) +---------------------------------------------------------------------------------------------------