ееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееее-ACPMUG 07ACATALOG 7 VOLUME7 DOCPILOT ASMЂ PILOT ASMЂ !"#PILOT ASMЂ$%&'()*+,-./0123PILOT ASMЂ456789:;<=>?@ABCPILOT ASMDE A LOW MEMORY LOCATION IMPLEMENTATION. UR FILES IS DISTRIBUTED AS PER THE HEW RELEASE IN CASE ANYONE HAS USE OF THE MDS IMPLIMENTATION. THE DR. DOBBS LISTING SHOWSTING WITH X-REFERENCE TABLES 7.4 6K PILOT.OBJ RELOCATABLE MDS OBJECT 7 VOLUME7.DOC COMMENTS 7.1 6K PILOT LOADED MDS OBJECT 7.2 66K PILOT.ASM PILOT SOURCE 7.3 135K PILOT.LST MDS ASSEMBLER LISееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееN DR. DOBBS OF APRIL AND MAY 1977 RESPECTIVELY ALTERNATIVELY FOR FULL LANGUAGE DOCUMENTATION WRITE FOR Guide to 8080 PILOT, Version 1.1 John P. Connors The Lister Hill National Center for Biomedical Communications National Library of ееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееPILOT +FGHIJKPILOT OBJ-LMNOPQеNOTE BAKNOTE TXTRееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееQU ORIGN+100H ;START OF STACK ; PORT EQU 0F6H ;MDS CONSOLE INPUT PORT STPORT EQU 0F7H ;MDS CONSOLE STATUS PORT RDA EQU 02H ;READ DATA AVAILABLE MASK. TBE EQU 01H ;TRANSMIT BUFFER EMPTY MASK. ; INTSRAM BUFFER. PBUFE EQU ORIGN+1FFFH ;END OF PROGRAM BUFFER. LINE EQU 72 ;MAX INPUT AT STARTUP. VIDEO EQU 0FE77H ;EXTERNAL VIDEO DISPLAY ADDR. MNTR EQU 0008H ;EXTERNAL MONITOR ADDRESS STKPR EееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееMedicine Bethesda MD 20014 THE SOURCE ASSEMBLES CLEANLY ON CP/M ASSEMBLER EXCEPT FOR ONE MVI R,-X. THE FULL SET OF FOUR FILES IS DISTRIBUTED AS PER THE HEW RELEASE IN CASE ANYONE HAS USE OF THE MDS IMPLIMENTATION. THE DR. DOBBS LISTING SHOWSVOLUME 7 PILOT - PROGRAMMED INQUIRY, LEARNING AND TEACHING NUMBER SIZE NAME COMMENTS CATALOG.7 CONTENTS OF CP/M VOL 7 VOLUME7.DOC COMMENTS 7.1 6K PILOT LOADED MDS OBJECT 7.2 66K PILOT.ASM PILOT SOURCE 7.3 135K PILOT.LST MDS ASSEMBLER LISееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееPILOT - PROGRAMMED LEARNING AND INQUIRY PILOT IS A LANGUAGE DESIGNED FOR INTERACTIVE CONVERSATION, WHERE EASY PATTERN MATCHING OF RESPONSES IS REQUIRED. USED IN COMPUTER-ASSISTED INSTRUCTION. THE COMPLETE DOCUMENTATION AND LISTING WERE PUBLISHED Iееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееее; THIS WORK WAS PREPARED UNDER CONTRACT TO THE LISTER HILL NATIONAL CENTER ; FOR BIOMEDICAL COMMUNICATIONS, NATIONAL LIBRARY OF MEDICINE, BETHESDA, ; MARYLAND BY JOHN A. STARKWEATHER OF THE UNIVERSITY OF CALIFORNIA AT ; SAN FRANCISCO. ; ; ; ; LXI D,CI MVI C,24 CALL BLKTFR JMP RSTRT IOJMP: JMP CHI ;COPY OF STD JMP TABLE JMP CHO JMP CHI JMP CHO JMP CHO JMP MNTR JMP MNTR JMP;LEVEL 3 DW 0 ;LEVEL 4 DW 0 ;LEVEL 5 DW 0 ;LEVEL 6 DW 0 ;LEVEL 7 (TOP) APTR: DW 0 ;A STMT POINTER EPTR: DW 0 ;ENTRY POINTERNSOLE STATUS PORT RDA EQU 02H ;READ DATA AVAILABLE MASK. TBE EQU 01H ;TRANSMIT BUFFER EMPTY MASK. ; INTSRT EQU 38H ;MDS INTERRUPT 7 FOR RESTARTING PILOT. ; ORG INTSRT ;RESTART PROGRAM BY USE OF INTERRUPT 7. ASEG JMP START DS 81 ;M LIST AREA LABSAV: DS 12 ;LABEL SAVE AREA LASTOP: DS 11 ;LAST OP CODE NVAR: DS 53 ;NUMERIC VARIABLE STORAGE WORD: DS 81 ;WORD AREA ; ; START AND TERMINATION OF MAIN PR ;ALTERN INTERPRETER ; ; DATA AREAS TOPP: DW 0 ;TOP OF PROGRAM STORAGE HLSAV: DW 0 ;TEMPORARY POINTER (HL) HLLSAV: DW 0 ;TEMPORARY POINTER (HL) HL2SAV: DW 0 ;TEMPORARY POINTER (HL) P I L O T 8080 V E R S I O N 1.2 ; ; 9/15/77 ; ; ; ORIGN EQU 06000H ;ORIGIN OF PROGRAM. PSTRT EQU ORIGN+2E0H ;START OF PILOT INTERPRETER. PBUFB EQU ORIGN+1000H ;BEGINNING OF PROGRAM BUFFER. PBUFE EQU ORIGN+1FFFH ;END OF PROGRAM BUFFER. L 0 ;SCAN BEGINNING ADDR CHMAX: DS 1 ;MAXCHARSACCEPTED LEVEL: DS 1 ;CURRENT RTURN LEVEL LNSKP: DS 1 ;LINE NUMBER SKIP MBRCH: DS 1 ;M-BREAK CHAR SCNT: DS 1 ;STRING C CPTR: DW 0 ;CHAR POINTER IPTR: DW 0 ;INPUT BUFFER POINTER MPTR: DW 0 ;M-STMT POINTER MEMTP: DW 0 ;LAST MEMORY LOCATION OUTADR: DW 0 ;CO,LOPO OUTPUT VECTOR SCANB: DW ;ENTRY SETS NORMAL I/O ; ;LXI H,CTV ;ENTRY TO USE VIDEO OUTPUT ;SHLD CO+1 ; AT STARTUP ;SHLD LO+1 ;SHLD PO+1 ;JMP RSTRT ;CTV: PUSH B ;MOV B,C ;CALL VIDEO ;POGRAM ; ORG HERE CAN SET BEGINNING OF ROM AREA ; ORG PSTRT START: LXI SP,STKPR ;INITIALIZE STACK POINTER LXI H,PBUFE-1 ;INITIALIZE APTR SHLD APTR LXI H,IOJMP ;SET NORMAL I/O VECTORS DESAV: DW 0 ;TEMPORARY POINTER (DE) LLSAV: DW 0 ;LAST LINE POINTER RETSAV: DW 0 ;ZERO LEVEL OF STACK DW 0 ;LEVEL 1 DW 0 ;LEVEL 2 DW 0 INE EQU 72 ;MAX INPUT AT STARTUP. VIDEO EQU 0FE77H ;EXTERNAL VIDEO DISPLAY ADDR. MNTR EQU 0008H ;EXTERNAL MONITOR ADDRESS STKPR EQU ORIGN+100H ;START OF STACK ; PORT EQU 0F6H ;MDS CONSOLE INPUT PORT STPORT EQU 0F7H ;MDS COOUNT TEMP: DS 1 ;TEMPORARY BINARY VALUE VARSAV: DS 1 ;VARIABLE SAVED YNSW: DS 1 ;YN-SWITCH, 000: NO MATCH TSAVE: DS 81 ;T-TEXT AREA EBUFF: DS 81 ;ENTRY BUFFER AREA MSAVE: ;READER INPUT TO A REG. LO: JMP CHO ;LIST OUTPUT FROM C REG. PO: JMP CHO ;PUNCH OUTPUT FROM C REG. EXIT: JMP MNTR ;RETURN TO MONITOR EDIT: JMP MNTR ;CALL TO EDITOR ASCAN: JMP BASIC OP B ;RET ; ; JUMP TABLE FOR I/O ROUTINES ; ONLY TTY ROUTINES ARE PROVIDED INTERNALLY ; ORG STKPR CI: JMP CHI ;CHAR INPUT TO A REG. CO: JMP CHO ;CHAR OUTPUT FROM C REG. RI: JMP CHI BASIC ; RSTRT: LXI SP,STKPR ;INIT STACK ON RESTART CALL INIT ;INITIALIZE THE REST CALL SCAN ;SCAN THE BUFFER JMP RSTRT ;START OVER ; DB '020677',0DH ; DB 'PILO ;ELSE ADDR FIRST CHAR SHLD HLSAV ;SET POINTER CALL TOP ;DISPLAY TEXT RET ; ; TEXT CHECK FOR PRESENCE OF LINE FEEDS, ; LINE COUNTS, OR LINE NUMBERS. ; SETS LNSKP TO NO. OF CHARS TO SKIP BEFORE TE ;SAVE IT LXI H,LASTOP ; ADDR LAST OP CODE SHLD LLSAV ;SAVE OP CODE ADDR MVI B,':' CALL INDX ;ADDR COLON POS CALL OLDOP ;USE PART OF OPS XRA A ; SET ;ZERO RETURN LEVEL STA LEVEL STA LNSKP ;ZERO LN NO. SKIP LXI H,CO ;RESET CONSOLE OUTPUT SHLD OUTADR RET ; ; SCAN OF INPUT BUFFER ; ENTER: HL=BUFFER ADDR ; RETURNS: HL ; THEN RETURN CALL VARCHK ;IF VARIABLE PRESENT < 1 RZ ; THEN RETURN LHLD LLSAV ;ADDR OP CODE CALL GETCTL ;GET THE CONTROL WORD CALL CTLMCH ;CALL SPECIFIC CONTSKIP ANY LN NOS., ETC. CALL GETCH ; GET FIRST TEXT CHAR CPI ':' ;IF COLON CZ CONTIN ; THEN CONTINUE SAME OP JZ SCAN ; IF CALLED THEN NEXT SCAN CPI '*' ;T-8080, 1.1',0DH ; ; ; ; INITIALIZE DATA FOR NEW PROGRAM ; INIT: LXI H,IBUFF ;RESET INPUT POINTER SHLD IPTR ; TO FRONT OF BUFFER SHLD SCANB ;SET SCAN BEGINNING LXI H,PBUFE ;SET LAST MEMSAV ;ADDR OP CODE MVI B,':' ; LOOK FOR COLON CALL INDX ;IF NOT FOUND MOV A,C ORA A JZ ALTSC ; THEN TRY ALTERN SCAN INX H ;COLON ADDR + 1 RETURN FLAG RET ; ; OP CODES-- INTERPRET OPERATION ; ENTER: HL = FIRST NON-BLANK CHAR IN LINE ; RETURNS: RETURN (ZERO) FLAG SET ; OPS: SHLD LLSAV ;SAVE OP CODE ADDR CALL SAVOP ;SAVE OP CODE LHLD LL=LAST ADDR, B=LAST CHAR (01) ; SCAN: LHLD IPTR ;GET POINTER MOV A,M ;GET FIRST CHAR CPI 1 ;IF END MARKER RZ ; THEN RETURN CPI 0DH ;IF NOT END OF LINE ROL CPI 1 ;IF CONTROL FOUND RNZ ; THEN RETURN ALTSC: LHLD LLSAV ;ADDR FIRST CHAR CALL ASCAN ;TRY ALTERN SCAN RZ ;IF OK, THEN RETURN LHLD LLSAVIF ASTERISK CZ GETWD ; THEN SKIP LABEL JZ SCAN+3 ;IF CALLED THEN RESCAN CALL OPS ;PROCESS OPERATIONS JMP SCAN ; CONTIN: INX H ;COLON ADDR + 1 SHLD HLSAV ORY LOC SHLD MEMTP CALL NEWN ;SET A-POINTER CALL INITV ;INITIALIZE VARIABLES MVI M,1 ; SET STOP MVI A,LINE ;RESET INMAX TO LINE STA CHMAX XRA A SHLD HLSAV ;SAVE IT DCX H ;ADDR POS OF COLON OLDOP: DCX H ;ADDR POS BEFORE COLON CALL YNCHK ;IF YN-SW OFF(Y) OR ON(N) ORA A ; (A=000) RZ ; THEN RETURN INX H ;HL=START OF NEXT LINE SHLD IPTR ;SAVE THAT ADDR DCX H ;HL=BREAK CHAR CALL BACKUP ;RESET HL TO CURRENT LINE CALL SKLN ; JNZ CKEND ; THEN CK FOR SOURCE END INX H ; ELSE BUMP POINTER JMP SCAN+3 ; AND CONTINUE CKEND: CALL CNTLN ;HL=EOL, A=BR CHAR CPI 1 ;IF END MARKER RZ XT ; TXTCK: LXI H,PBUFF ;ADDR PROGRAM TEXT CALL CNTLN ;ADDR CR INX H MOV A,M ;GET NEXT CHAR CPI 0AH ;IF NOT LF JNZ CKLC ; THEN CK FOR LINE COUNT MOV A,M ; GET CHAR CPI '(' ;IF PAREN NOT PRESENT JNZ BADFRM ; THEN COMPLAIN INX H ;BUMP POINTER MOV B,M ; SAVE CHAR IN B CALL VARMCH ONDITIONS ; Y AND N FOLLOWING OP CODE ; ACT AS A SWITCH ALONG WITH YN-SWITCH ; ENTER: HL = ADDR OF COLON ; RETURNS: A = 000 IF NO ACTION REQUIRED ; ELSE A = CHAR BEFORE COLON ; HL = ADDR OF LAST CHAR BEFORE COLON DCX D ;DECR IT DAD D ;ADDR LINE END MOV A,M ;GET CHAR CPI 0DH ;IF NOT CR JNZ CKLN ; THEN CK FOR LINE NO. INX H ;ELSE CK ANOTHER LIN ; AND RETURN ; ; CHECK FOR NUMERIC VARIABLE CONDITIONS ; VARIABLE IN PARENTHESES AFTER OP CODE ; CAUSES EXECUTION IF VALUE +1 OR MORE ; ENTER: A = LAST CHAR BEFORE COLON ; RETURNS: ZERO FLAG OFF IF NO ACTION REQUIRED ; VARCHK: CPI ;TOO LOW CPI '9'+1 JM YNUM ORA H ;TOO HIGH RET YNUM: XRA A ;OK RET ; ; SKIP LINE NUMBER AND LINE COUNT ; BASED ON VALUE OF LNSKP ; SKLN: LDA LNSKP CALL CNTLN ;ELSE CK ANOTHER LINE INX H MOV A,M CPI 0AH ;IF NOT LF JNZ CKLC ; THEN CK FOR LINE COUNT LDA LNSKP ;ELSE ADD 1 TO LNSKP ADI 1 STA WITH CHAR YCHK: LDA YNSW ;IF YN-SWITCH ORA A ; SHOWS MATCH JZ DONT ; THEN QUIT ORA H ; ELSE SET SWITCH ON RET ; AND RETURN NCHK: LDA YNSW ; YNCHK: CALL GETLCH ;GET LAST CHARACTER CPI 'Y' ;IF Y JZ YCHK CPI 'N' ;IF N JZ NCHK ORA A ; ELSE SET SWITCH ON RET ; AND RETURNE CALL SKLN MOV E,M DCX D DAD D MOV A,M CPI 0DH ;IF NOT CR JNZ CKLN ; THEN CK FOR LINE NOS. LDA LNSKP ;ELSE ADD 1 TO LNSKP ADI 1 ')' ;IF VARIABLE PRESENT JZ VCHK ; THEN CHECK IT ORA H ; ELSE SET SWITCH ON RET ; AND RETURN VCHK: DCX H ;DECR POINTER DCX H ; TWICE ;GET SKIP COUNT ORA A ;IF ZERO RZ ; THEN RETURN INX H ;SKIP A CHARACTER DCR A ;DECR COUNT JMP SKLN+3 ;MORE ; ; CHECK FOR Y OR N CLNSKP CKLC: LXI H,PBUFF ;CK FOR LINE COUNT CALL CNTLN ;ADDR CR INX H ; NEXT CHAR CALL SKLN ;SKIP ANY LF MOV E,M ;GET POSSIBLE LINE COUNT MVI D,0 ORA A ; SHOWS NO MATCH JNZ DONT ; THEN QUIT ORA H ; ELSE SET SWITCH ON RET ; AND RETURN DONT: XRA A ; SET SWITCH OFF RET CALL NUM ;IF NOT ASCII NUMBER RNZ ; THEN QUIT LDA LNSKP ;ELSE ADD 4 TO LNSKP ADI 4 STA LNSKP RET ; NUM: CPI '0' ;CHECK FOR ASCII NUMBER RM STA LNSKP CKLN: LXI H,PBUFF+1 ;NOW LOOK FOR LN NOS. CALL CNTLN ;ADDR CR INX H ; NEXT CHAR CALL SKLN ;SKIP LF OR LN CNT MOV A,M ;GET CHAR AFTER LN CT ;LOOK IT UP CPI 1 ;IF END MARKER JZ BADFRM ; THEN COMPLAIN INX H ; ELSE POINT AT VALUE MOV A,M ; GET VALUE CPI 01 JM VOFF ; THEN 'WA',0DH ; DW WAIT DB 1 ; CURSR: MVI C,1BH CALL CO MVI C,'&' CALL CO MVI C,61H CALL CO LHLD HLSAV CURS1: MOV A,M CPI ',' JZ CURS3 CPI 0DH JZ CURS4 MOV C,A CURS2: CALL CO INX H JMP CURS1 CURS3: MVI C,'r' JMP CPI 1 ;IF END MARKER RZ ; THEN RETURN XCHG ;ELSE RESET DE TO NEXT ITEM JMP LSTMCH ; AND TRY IT ; ; CONTROL LIST - OP CODES AND KEYWORDS ; CTLST: DB 'T',0DH VARMCH: LXI H,NVAR MOV A,M CPI 1 ;IF LIST END RZ ; THEN RETURN CMP B ;IF MATCH RZ ; THEN RETURN INX H ; ELSE LOOK AGAIN LPRG DB 'SAVE',0DH ;SAVE PROGRAM DW SPRG DB 'IEP',0DH ;INTERPRET EXIST PROG DW IEP DB 'BYE',0DH DW EXIT DB 'EDIT',0DH DW EDIT ;COMMON DATAPOINT PILOT CGINNING OF LIST ; RETURNS: DE = ADDR OF POINTER (L BYTE) ; IF WORD NOT IN LIST THEN A = 01 ; LSTMCH: LXI H,WORD ; HL=INPUT WORD CALL CMPR ;COMPARE WORD WITH LIST ORA A ; IF MATCH QUIT ORA H ; ELSE SET SWITCH ON RET ; AND RETURN VOFF: XRA A ; SET SWITCH OFF RET ; AND RETURN ; BADFRM: LHLD LLSAV ;SHOW THE LINE CALL TOP+3 DW COP DB 'U',0DH DW UOP DB 'E',0DH DW EOP DB 'Y',0DH DW TOP DB 'N',0DH DW TOP DB 'LOAD',0DH ;LOAD NEW PROGRAM DW LOAD DW TOP DB 'A',0DH DW AOP DB 'M',0DH DW MOP DB 'MC',0DH DW MC DB 'J',0DH DW JOP DB 'R',0DH DW ROP DB 'C',0DH INX H JMP VARMCH+3 ; ; CONTROL MATCH- CALLS SPECIFIC CONTROL OPERATIONS ; ENTER: 'WORD':CONTROL WORD ; RETURNS: IF WORD NOT IN LIST, THEN 01 RETURNED ; HL: START OF NEXT WORD ; CTLMCH: LXI D,CTLST ; DODES NOT IN OPERATION DB 'CA',0DH DW CURSR DB 'CE',0DH DW CLRE DB 'CL',0DH DW CLRL DB 'CH',0DH DW CLRH DB 'RL',0DH DW ROLL ; DB RNZ ; THEN RETURN INX H ;ELSE HL = DE XCHG INX H ;AND INCR HL TO INX H ;NEXT LIST ADDR INX H MOV A,M ; GET NEXT LIST CHAR LXI H,EXPMSG CALL ERROR RET ; ; VARIABLE MATCH - LOOKUP OF VARIABLE NAME/VALUE LIST ; ENTER: VARIABLE NAME CHAR IN B REGISTER ; RETURNS: HL = ADDR OF MATCHED NAME ; IF VAR NOT IN LIST THEN A = 01 ; DB 'INMAX',0DH ;LIMITS CHARS ACCEPTED DW INMAX DB 'NEW$',0DH ;ERASE $TEXT DW NEWN DB 'DP',0DH ;DISPLAY PROGRAM DW DPRG DB 'PRINT',0DH ;PRINT PROGRAM DW MOV E,M INX H MOV D,M PUSH D ;CALL ADDR ON STACK RET RTRN: XRA A RET ; ; LIST MATCH - LOOKUP OF WORD/ADDRESS LIST ; ENTER: 'WORD' = WORD TO BE FOUND ; DE = ADDR OF BEE=CONTROL LIST ADDR CALL LSTMCH ;LOOK FOR WORD CPI 1 ;IF NOT FOUND RZ ; THEN RETURN XCHG INX H LXI D,RTRN ;PUT RETURN ON STACK PUSH D CURS2 CURS4: MVI C,'C' CALL CO RET CLRE: MVI C,1BH CALL CO MVI C,'J' CALL CO RET CLRL: MVI C,1BH CALL CO MVI C,'K' CALL CO RET CLRH: MVI C,1BH CALL CO MVI C,'H' CALL CO JMP CLRE ROLL: MVI C,1BH CALL CO MVI C,'S' CALTURNS: ZERO AND SIGN FLAGS SET AS THOUGH ; A CONTAINED HL AND DE WAS COMPARED ; CALLED BY BLKBF ; ADRCMP: MOV A,H ; GET H CMP D ;COMPARE D RM ;IF D > H THEN RETURN EXPRESSION CALL GETCH ;GET FIRST CHAR CPI '*' ;IF * JZ JOP2 ; THEN MOVE WORD MVI A,'*' STA WORD ;ELSE ADD * LXI D,WORD+1 ; THEN MOVE WORD MOV M,E RET ; ; CHAR TO BINARY CONVERSION FOR CONTROL ARGUMENTS ; NUMBER CONTROL - FINDS 1 OR 2 DIGIT NUMBER OR NAME ; OF VARIABLE IN NEXT WORD. NEGATIVE VALUES SET TO ZERO. ; ENTER: HLSAV = EXPRESSION ADDRESS ; RETURNS: E = BINAH ;BUMP ADDR MOV A,C ; DECR COUNT SUI 1 MOV C,A ; IF COUNT NOT ZERO JNZ BLKSET ; THEN STORE ANOTHER RET ; ; BLANK THE INPUT BUFFER ; BLKBF: LHLD APTR ; AND RETURN INX H ;ELSE POINT AT VALUE MOV E,M ; PUT VALUE IN E JMP CVNUM+3 ; AND QUIT CVNUM: CALL GETNM ;CONVERT NUMBER MOV A,E ; GET VALUE L CO RET ;WAIT: RET ; ; INTERPRET EXISTING PROGRAM ; STARTS SCAN OF PROGRAM BUFFER ; IEP: LXI H,PBUFF SHLD IPTR ;SET POINTER SHLD SCANB ; AND SCAN BEGINNING CALL TXTCK ;CK FOR CHAFOUND CZ NTFND ; THEN COMPLAIN RZ ; AND RETURN INX H SHLD IPTR ;NEW SCAN POSITION RET ;RESTART SCAN ; ; NTFND: LXI H,WORD ; SHOW THE LABEL LHLD HLSAV CALL WDTFR JMP JOP2+3 ;AND CONTINUE JOP2: CALL GETWD ;GET NEXT WORD LHLD SCANB ; START OF SCAN AREA CALL LOOKL ;LOOK FOR IT CPI 1 ;IF LABEL NOT RY VERSION OF THE NUMBER ; A = 0DH IF ALREADY AT END OF LINE ; HLSAV = BR CHAR ADDR ; NMCTL: LHLD HLSAV ;EXPRESSION ADDR CALL GETCH ;GET CHAR CPI 0DH ; IF CR RZ ;DE=TOP OF BUFFER XCHG LXI H,PBUFF ;HL=BOTTOM OF BUFFER MVI B,' ' BLKB2: MOV M,B INX H CALL ADRCMP JNZ BLKB2 RET ; ; ADDRESS COMPARISON - COMPARES HL + DE ; RE ORA A RP ;RETURN IF POSITIVE MVI E,0 ; ELSE SET TO ZERO RET ; ; JUMP TO LABEL NAME ; ENTER: HLSAV = EXPRESSION FIELD ; RETURNS: HL RESET OR MESSAGE ; JOP: LHLD HLSAV ;ADDR RS TO SKIP RET ; INMAX: CALL NMCTL ;E = NUMBER CONTROL MOV A,E CPI 73 ;LIMIT TO 72 JM INMX2 MVI A,72 MOV E,A INMX2: LXI H,CHMAX ; SET INPUT CHAR MAX CALL DSPLY LXI H,BLMSG CALL ERROR RET ; UOP: CALL SAVRET ;SAVE RETURN POINTER JMP JOP ; ; SET A BLOCK OF LENGTH C TO CHAR B ; BLKSET: MOV M,B ; STORE ONE CHAR INX JNZ CVNUM ; THEN CONVERT A NUMBER MOV B,M ; ELSE SAVE CHAR IN B CALL VARMCH ;LOOK IT UP CPI 1 ;IF END MARKER CZ BADFRM ; THEN COMPLAIN RZ ; THEN RETURN CALL GETWD ;GET NEXT WORD DCX H ;BACK UP TO BR CHAR SHLD HLSAV ;SAVE POINTER LXI H,WORD ; IN 'WORD' CALL LETTER ;IF NOT LETTER RNZ ;IF D NOT = H THEN RETURN MOV A,L ; GET L CMP E ;COMPARE E RET ; AND RETURN ; ; CHARACTER TO BINARY CONVERSION ; GET A DECIMAL NUMBER-- UP TO 99 ; ENT CALL CNTLN ;ELSE GO TO NEXT LINE INX H LDA TEMP ;IF TEMP=0 ORA A JZ LOOK ; THEN NO SKIPS JMP LOOK-3 ;ELSE SKIP LN NOS. CHK: SHLD HLSAV ;SAVE POINTER ; AND LOOP FRMCH: MOV A,C ; GET TENS COUNT ADI '0' ;ADD ASCII BIAS CPI '0' ;IF CHAR IS 0 JZ FRMU ; THEN FORM UNITS MOV M,A ; STORE THE CHAR INX ;LIMIT RANGE RM ; TO NUMERALS CPI '9'+1 RP SUI '0' ;REMOVE ASCII BIAS ADD A ;MULT. BY 10 MOV E,A ; E=A*2 ADD A A A ;SET TEMP FOR NO SKIPS STA TEMP JMP LOOK LOOKL: ORA H ;SET TEMP ON FOR SKIPS STA TEMP CALL SKLN ;SKIP ANY LINE NOS. LOOK: CALL GETCH ;NEXT CHAR CPI DH AFTER RIGHT DIGIT ; PUTNM: MVI C,0 ; INITIALIZE C MOV A,E ; GET BINARY NUMBER ORA A ; IF NEGATIVE CM NEG ; THEN SHOW MINUS SIGN CPI 10 ;IF < 10ER: HL= CHAR ADDR OF ONE OR TWO DIGIT NUMBER ; RETURNS: BINARY NUMBER IN E ; IF INPUT NOT NUMERIC, THEN E = 0 ; GETNM: MVI E,0 ; INIT. OUTPUT VALUE INX H ;LOOK AT NEXT CHAR CALL BRCHAR ;IF E EOL MOV M,A RET ; NEG: MVI A,'-' ; STORE MINUS SIGN MOV M,A INX H ;BUMP CHAR ADDRESS XRA A ; MAKE BINARY POSITIVE SUB E MOV E,A ; H ;BUMP CHAR ADDR FRMU: MOV A,E ; GET THE UNITS ADI '0' ;ADD ASCII BIAS MOV M,A ; STORE THE CHAR INX H ;BUMP POINTER MVI A,0DH ; STOR; A*4 ADD A ; A*8 ADD E ; A+E=A*10 MOV E,A ; SAVE IT INX H ;HL=HL+1 UNITS: MOV A,M ; GET SECOND CHAR CPI '0' ;LIMIT RANGE 1 ;IF DATA END RZ ; THEN RETURN CPI '*' ;IF * JZ CHK ; THEN CHECK THE LABEL CPI '$' ;IF $ JZ CHK ; THEN CHECK STRING NAME JM FRMCH ; THEN FORM CHAR SUI 10 ; ELSE SUBTR 10 MOV E,A ; SAVE IN E MOV A,C ; INCR TENS COUNT ADI 1 MOV C,A JMP PUTNM+2 BREAK CHAR JZ SDIG ; THEN SINGLE DIGIT CPI '+' JZ SDIG CPI '-' JZ SDIG DCX H ;ELSE BACK UP MOV A,M ; GET FIRST CHAR CPI '0' SAVE IN E RET ; ; LOOK FOR *LABEL OR $NAME OF STRING VARIABLE ; (LOOKL OR LOOKS) ; ENTER: 'WORD'=LABEL TO BE FOUND, HL=SCAN ADDR ; RETURNS: HL = ADDR OF BLANK AFTER LABEL ; IF LABEL NOT FOUND THEN A = 01 ; LOOKS: XRBACK UP POINTER JMP UNITS ;CONVERT UNITS POSITION ; ; BINARY TO CHARACTER CONVERSION ; PUT BINARY NUMBER IN DECIMAL CHARS -99 TO +99 ; ENTER: BINARY NUMBER IN E ; HL = CHARACTER AREA ; RETURNS: HL = ADDR OF 0 RM ; TO NUMERALS CPI '9'+1 RP SUI '0' ;REMOVE ASCII BIAS ADD E ;ADD NEW DIGIT MOV E,A ; TO E RET SDIG: DCX H ; CALL CNTWD ;C = WORD LENGTH MOV A,C CPI 13 ;LIMIT TO 12 CHARS JM MVLAB MVI C,12 MVLAB: LHLD HLSAV ;RETRIEVE POINTER LXI D,LABSAV ; DESTIN ADDR CAEXT JMP CNTWD+2 ;NEXT CHAR ; ; WORD TRANSFER ; MOVES STRING FROM HL TO DE + 0DH ADDED ; ENTER: HL= SOURCE ADDR, DE= DESTIN ADDR ; RETURNS: HL= SOURCE ADDR AFTER BR CHAR ; DE= DESTIN ADDR AFTER 0DH ; B= RET ; ; GET CHARACTER-- SKIPS LEADING BLANKS ; ENTER: HL=SOURCE ADDR ; RETURNS: HL=NEXT NON-BLANK ADDR, A=CHAR ; GETCH: MOV A,M ; GET CHARACTER CPI 20H ;IF NOT BLANK RNZ ; THEEL JMP LOOK ; AND CONTINUE LFND: LHLD HLSAV ;RETRIEVE POINTER CALL CNTWD ;SKIP LABEL RET ; AND RETURN ; ; COMPARE STRINGS X AND Y ; ENTER: HL= X ITEM ADDR, DE= Y ITEM ADDR KS LXI D,WORD ; DESTIN ADDR CALL WDTFR ;MOVE IT RET ; ; COUNT WORD ; ENTER: HL=SOURCE ADDR ; RETURNS: HL=BR CHAR ADDR ; A,B=BR CHAR, C=COUNT INCL BR CHAR ; CNTWD: MVI C,1 ; ; GET Y CHAR CPI 0DH ; IF END OF LINE JZ MCH ; THEN MATCH FOUND CALL CNTWD ;ADDR Y BR CHAR XCHG ;SET DE XRA A ; NOMATCH RET NOMCH:LL BLKTFR ;MOV A,BSAV=LABEL XCHG ;HL:DESTIN BR CHAR+1 DCX H ; DESTIN BR CHAR MVI A,0DH ; REPLACE WITH 0DH MOV M,A LXI H,LABSAV LXI D,WORD GET CHARACTER CPI 20H ;IF NOT BLANK RNZ ; THEN RETURN DCX H ;ELSE GET NEXT CHAR JMP GETLCH ; ; GET WORD -- UP TO FIRST BREAK CHARACTER ; IGNORES LEADING BLANKS N RETURN INX H ; ELSE GET NEXT CHAR JMP GETCH ; ; GET LAST CHAR - SCANS BACKWARD, SKIPS BLANKS AND CR'S ; ENTER: HL = STRING ADDR ; RETURNS: HL = LAST NON-BLANK CHAR, A = CHAR ; GETLCH: MOV A,M ; ; BOTH ITEMS TERMINATE IN 0DH ; RETURNS: A=0 FOR NO MATCH, ; HL AND DE AT 0DH ADDRESS ; CMPR: MOV A,M ; GET X CHAR CPI 0DH ; IF END OF LINE JZ XEND ; THEN END OF X ITEM COUNT=1 CALL BRCHAR ;IF CHAR=BREAK RZ ; C=CHAR COUNT MOV A,C ; GET COUNT ADI 1 ;C=C+1 MOV C,A ; STORE IT INX H ;HL=N CALL CNTWD ;ADDR Y BR CHAR YENDB: XCHG ; SET DE CALL CNTWD ;ADDR X BR CHAR XRA A ; NO MATCH RET MCH: XCHG ;SET DE & HL ORA H ; MATCH ; WORD ADDR CALL CMPR ;COMPARE THEM ORA A ; LOOK AT A REGISTER JNZ LFND ;IF MATCH THEN LABEL FOUND LHLD HLSAV ;ELSE RETRIEVE POINTER CALL CNTWD ;SKIP LAB ; ENTER: HL=SOURCE ADDR ; RETURNS: 'WORD'=SOURCE STRING + 0DH ; HL= BR CHAR+1 ADDR, B= BR CHAR ; DE= 'WORD' ADDR AFTER 0DH ; C = NO OF CHARS MOVED INCL BR CHAR ; GETWD: CALL GETCH ;IGNORE LEADING BLAN CMP C ;IF A(Y) NOT= C(X) JNZ NOMCH ;THEN NO MATCH INX H ;ADDR NEXT X ITEM XCHG JMP CMPR ;START OVER XEND: XCHG ;ADDR Y ITEM MOV A,M MOV C,A ; SAVE X CHAR IN C INX H ;ADDR Y ITEM XCHG MOV A,M ; GET Y CHAR CPI 0DH ; IF END OF LINE JZ YENDB ; THEN END OF Y ITEM BR CHAR ; C= NO OF CHARS MOVED INCL BR CHAR ; WDTFR: MVI C,1 ; INIT COUNT CALL BRCHAR ;IF BREAK CHAR JZ MVBR ; THEN END OF SOURCE INX H ;HL= DESTIN ADDR XCHG CHAR AFTER MATCH ; INDEX: XRA A STA SCNT ;INIT STRING COUNT INDE2: LHLD HLSAV ;ADDR STRING XCHG ;DE = STRING ADDR LHLD HLLSAV ;ADDR SUBSTRING MOV B,M ;FIRST TLN+2 ;NEXT CHAR ; ; BACKUP-- DECREMENTS HL BY VALUE OF C-1 ; ENTER: HL START VALUE, C=COUNT ; RETURNS: NEW HL VALUE ; BACKUP: MOV A,C ; GET COUNT CPI 1 ;IF COUNT=1 RZ ; THENORD' ; REPLACES FINAL Y OR N WITH 0DH ; ENTER: HL = SOURCE ADDR ; GETCTL: LXI D,WORD ; DESTIN ADDR CALL WDTFR ;MOVE WORD MOV A,C ; GET COUNT CPI 3 ;IF < 3 CHARS MOVED TE RZ CPI '(' ;L PARENS RZ CPI ')' ;R PARENS RZ CPI 27H ;APOSTROPHE RZ CPI 1 ;END OF LIST RET ;BR CHAR NOT FO RETURNS: C=CHAR COUNT INCL 0DH OR 01 ; HL=BREAK POS., A=BR CHAR ; CNTLN: MVI C,1 ; COUNT=1 MOV A,M ; GET CHARACTER CPI 0DH ; IF 0DH RZ ; C=CHAR COUNT MOV M,B ; MOVE CHARACTER MOV A,C ; INCR COUNT ADI 1 MOV C,A INX H ;HL= NEXT SOURCE ADDR XCHG JMP WDTFR+2 MVBR: INX H ;HL= DESTIHAR THEN Z FLAG TRUE ; BRCHAR: MOV A,M ; GET CHAR MOV B,A ; AND SAVE IT CPI ' ' ;CHECK FOR VARIOUS RZ ;BREAK CHARACTERS CPI 0DH ; END OF LINE RETURN SUI 1 ;C=C-1 MOV C,A ; STORE C DCX H ;HL=HL-1 JMP BACKUP ; ; BREAK CHARACTER SEARCH ; ENTER: HL=CHAR ADDR ; RETURNS: A, B = CHARACTER ; IF BR C RM ; THEN RETURN MOV H,D ; ADDR WORD MOV L,E DCX H ;AVOID COLON DCX H CALL GETLCH ;GET LAST CHAR CPI 'Y' ;IF Y JZ YNUND ; ; INDEX - FIND CHAR POSITION OF MATCHED STRING ; ENTER: HLSAV = STRING ADDR, HLLSAVE = SUBSTR ADDR ; RETURNS: C = CHAR POS OF MATCH, IF NOMATCH, C=0 ; HLSAV = STRING ADDR OF FIRST MATCHED CHAR ; EPTR = ADDR OF NEXT CPI 1 ;IF 01 RZ ; C=CHAR COUNT MOV A,C ; GET COUNT ADI 1 ;C=C+1 MOV C,A ; STORE IT INX H ;HL=NEXT JMP CNN BR CHAR ADDR XCHG MVI A,0DH ; REPLACE WITH 0DH MOV M,A INX H ;HL= SOURCE BR CHAR ADDR+1 XCHG XRA A ; SET RETURN FLAG RET ; ; GET CONTROL WORD IN 'W RZ CPI ',' RZ CPI ';' RZ CPI ':' RZ CPI '.' RZ CPI '?' RZ CPI 21H ;EXCLAMATION RZ CPI '"' ;DOUBLE QUOSTOP ; SAVOP: MVI B,':' CALL INDX ;COUNT CHARS TO COLON LHLD LLSAV ;ADDR OP CODE LXI D,LASTOP CALL BLKTFR ;MOVE CHAR STRING RET ; ; COUNT LINE ; ENTER: HL=SOURCE ADDR ; OUT ; THEN REMOVE IT CPI 'N' ;IF NOT N RNZ ; THEN RETURN YNOUT: MVI A,0DH ; REPLACE Y OR N MOV M,A ; WITH 0DH RET ; ; SAVE OP CODE THROUGH COLON IN LASUBSTR CHAR IN B INX H ;ADDR STRING XCHG CALL INDX ;LOOK FOR FIRST CHAR MOV A,C ORA A ; IF NOT FOUND RZ ; THEN RETURN SHLD HLSAV EXPRESSION FIELD ; TOP: LHLD HLSAV ;RETRIEVE POINTER SHLD CPTR ;SAVE CHAR POINTER SHLD LLSAV ;SAVE FIRST CHAR ADDR LXI H,TSAVE ; DESTIN START ADDR SHLD DESAV ;SAVE DESTIEX FOR POSITION OF $ OR # ; ENTER: HL = STRING ADDRESS ; RETURNS: BA = $, #, OR 0DH; C = CHAR POS ; HL = ADDR OF MATCHED CHAR ; SINDX: MVI C,1 ; INIT C REGISTER MOV A,M ; GET CHAR CPI SHLD EPTR ;SAVE NEXT CHAR ADDR XCHG ;ADDR END OF 'WORD' MVI A,0DH ; TERMINATE WITH 0DH MOV M,A LHLD HLLSAV ;ADDR SUBSTR XCHG ;DE = SUBSTR ADDR ;TOO HIGH? XRA A ; ELSE RESET ZERO FLAG RET ; AND RETURN IF LETTER NOTL: ORA H ; RETURN IF NOT LETTER RET ; ; SETUP GETS CHAR COUNT AND SETS ADDR FOR TEXT MOVES ; SETUP ; GET CHAR CMP B ;IF B-CHAR FOUND RZ ; THEN RETURN CPI 0DH ; IF END OF LINE JZ ZC ; THEN ZERO COUNT MOV A,C ; ELSE ADI 1 ; ELSE SAVE POINTER LDA SCNT ;GET OLD STRING COUNT ADD C ;ADD NEW COUNT STA SCNT ; IN SCNT LHLD HLLSAV ;ADDR SUBSTR CALL CNTLN ;COUNT SUBSTR CHARS ; ELSE ADI 1 ;BUMP COUNT MOV C,A INX H ;BUMP ADDR JMP SINDX+2 ;GO TO NEXT ; ; LETTER TESTS WHETHER CHARACTER IS UPCASE A-Z ; ENTER: HL = ADDR OF CHAR ; RETURNS: ZERO FL '$' ;IF $ RZ ; THEN RETURN CPI 043O ;IF # RZ ; THEN RETURN CPI 0DH ; IF EOL RZ ; THEN RETURN MOV A,C LXI H,WORD ; ADDR PORTION OF STRING CALL CMPR ;COMPARE THEM ORA A ; IF FOUND JNZ SETCNT ; THEN SET POSITION COUNT LHLD HLSAV ; ELSE GET STRING POINTER : CALL CNTLN ;C=CHAR COUNT MOV B,C ; SAVE COUNT CALL BACKUP ;RESET HL MOV C,B ; RESET COUNT RET ; ; T OPERATION--DISPLAY 'T' STATEMENT ; ENTER: HLSAV= FIRST CHAR OF T ; BUMP COUNT MOV C,A INX H ; BUMP ADDR JMP INDX+2 ; GO TO NEXT ZC: XRA A ; RETURN WITH MOV C,A ; C = 0 RET ; ; SINDX - SPECIAL IND MOV A,C ; REDUCE COUNT TO SUI 1 ; ALPHA CHARS MOV C,A LXI D,WORD ; MOVE SAME NUMBER OF LHLD HLSAV ; CHARS FROM STRING CALL BLKTFR ; TO 'WORD' AG TRUE IF IT IS ; B = CHARACTER ; LETTER: MOV A,M ; GET CHAR MOV B,M ; SAVE IN B CPI 41H ;CHECK RANGE JM NOTL ;TOO LOW? CPI 5AH JP NOTL RACTER POSITION OF SINGLE LETTER ; ENTER: HL = STRING ADDR, B= CHAR ; RETURNS: C = CHAR POS OF MATCH, IF NOMATCH, C=0 ; HL = ADDR OF MATCHED CHAR OR EOL ; INDX: MVI C,1 ; INIT C REGISTER MOV A,M INX H ; BUMP IT SHLD HLSAV ; SAVE IT JMP INDE2 ; AND TRY AGAIN SETCNT: LXI H,SCNT ; PUT STRING COUNT IN C MOV C,M RET ; AND RETURN ; ; INDX - FIND CHAN ADDR XCHG ;AND KEEP IN DE TMORE: LHLD CPTR ;GET CHAR POINTER CALL SINDX ;LOOK FOR $ OR # CPI '$' ;IF $ FOUND JZ GETXT ; THEN GET LABELED TEXT CPI 0EXT RET ; ; GET A-TEXT POINTED TO BY MATCHED LABEL ; ENTER: HL = BLANK AFTER MATCHED LABEL ; DESAV = DESTIN ADDRESS ; RETURNS: A-TEXT MOVED TO DESTINATION ; DESAV = NEXT DESTIN ADDRESS ; GETA: INX H UT DIGITS IN WORD CALL PUTNM LHLD DESAV ;DESTIN ADDR XCHG LXI H,WORD ; DIGIT CHAR ADDR CALL SETUP ;C = CHAR COUNT+1 MOV A,C SUI 1 MOV C,A ; LHLD CPTR ;ADDRESS INPUT TALL: CALL SETUP ;C = CHAR COUNT CALL BLKTFR ;MOVE T-TEXT MVI A,0DH ; TERMINATE XCHG MOV M,A LXI H,TSAVE ; ADDRESS TEXT XCHG SHLD DESAV ;SAVE DESTIN POINTER MOV H,B ; GET CHAR POINTER MOV L,C CALL GETWD ;GET LABEL DCX H ;ADDR BR CHAR SHLD CPTR ;SAVE CHAR POINTER L,C INX H ;BUMP TO VAR NAME MOV C,M ; SAVE NAME IN C INX H ;BUMP ADDR SHLD CPTR ;SAVE CHAR POINTER MOV B,C ; PUT VAR NAME IN B CALL VAR43O ;IF # FOUND JZ GETNUM ; THEN GET NUMBER JMP TMOVE ;ELSE MOVE REST OF TEXT GETXT: CALL INSERT ;INSERT TEXT CPI 1 ;IF FOUND (A NOT 01) JNZ TMORE ; THEN CF '$' ; RETURNS: TSAVE CONTAINS ASSEMBLED T-TEXT ; IF LABEL NOT FOUND, THEN A = 01 ; INSERT: MOV A,C ; GET POSITION COUNT SUI 1 ;REDUCE COUNT BY 1 JZ LBL ;IF 0 THEN POINT TO LABE C = CHAR COUNT CALL BLKTFR ;MOVE DIGITS XCHG SHLD DESAV ;SAVE DESTIN ADDR XRA A ; SET RETURN FLAG RET ; ; INSERT LABELED TEXT INTO T-STATEMENT ; ENTER: C = POSITION O CALL DSPLY ;DISPLAY T STATEMENT XRA A ; SET RETURN FLAG RET ; ; INSERT NUMERIC VALUE INTO T-STATEMENT ; ENTER: C = POSITION OF '#' ; RETURNS: TSAVE CONTAINS ASSEMBLED T-TEXT ; IF LABEL NOT LHLD APTR ;HL = START OF LIST INX H CALL LOOKS ;LOOK FOR STRING NAME CPI 1 ;IF NOT FOUND (A = 01) RZ ; THEN RETURN CALL GETA ; ELSE GET A-TMCH ;LOOK UP VAR NAME CPI 1 ;IF NOT FOUND (A = 01) RZ ; THEN RETURN INX H ;ELSE POINT AT VALUE MOV E,M ; GET VALUE IN E LXI H,WORD ; PONTINUE LXI D,TSAVE ; ELSE DISPLAY THE LINE LHLD LLSAV JMP TALL GETNUM: CALL INSNUM ;INSERT NUMBER JMP GETXT+3 ; AND SEE IF FOUND TMOVE: LHLD DESAV ;DESTIN ADDR XCHG L MOV C,A LHLD DESAV ;DESTIN ADDR XCHG LHLD CPTR ;GET CHAR POINTER CALL BLKTFR ;MOVE FRONT OF TEXT LBL: MOV B,H ; SAVE CHAR POINTER IN BC MOV C,L LHLD CPTR ;GET CHAR POINTER CALL BLKTFR ;MOVE FRONT OF TEXT VBL: MOV B,H MOV C,L XCHG SHLD DESAV ;SAVE DESTIN POINTER MOV H,B ; GET CHAR POINTER MOV FOUND, THEN A = 01 ; INSNUM: MOV A,C ; GET POSITION OF # SUI 1 ;REDUCE COUNT BY 1 JZ VBL ;IF 0 THEN GET VARIABLE MOV C,A LHLD DESAV ;DESTIN ADDR XCHG ;ADDR FIRST A-CHAR MOV B,H ; BC = A-TEXT ADDR MOV C,L LHLD DESAV ;DESTIN ADDR XCHG MOV H,B ; HL = A-TEXT ADDR MOV L,C CALL SETUP ;C = COV A,M ; GET CHARACTER CPI 1 ;IF 01 (END OF SPACE) JZ STOVF ; THEN STORAGE OVERFLOW MOV A,B ; DECR COUNT SUI 1 MOV B,A JNZ DECA ;B ; ; A ITEM STORE - STORAGE OF LABELED TEXT FROM ENTRY ; FROM TOP OF INPUT BUFFER AREA AND SETS POINTER ; ASTORE: LXI H,EBUFF ; SOURCE ADDR CALL CNTLN ;C = CHAR COUNT MOV B,C ; DUPL COUNT IN B CALL GETCH ;GET FIRST CHAR CPI '$' ;IF NOT $ JNZ NIN ; THEN LOOK FOR # LXI D,LABSAV ; ELSE ADDR DESTIN CALL WDTFR ; SAVE THE LABEL CALL ENTRY ;GET THE H,D DCX H ;BACK UP ONE CHAR MVI A,' ' ;AND SET MOV M,A ; BLANK THERE RET ; ; DECREMENT ADDRESS FOR TEXT STORAGE ; ENTER: HL = LAST (LOWEST) ADDRESS USED (01) ; MOV A,M ;GET CHAR CPI 0DH ;IF CR JZ RSTRT ; THEN RESTART CALL OPS ;ELSE DO IMMED OP JMP ENTRY ; AND ACCEPT MORE INPUT ; CKNUM: CPI '0' ;CHECK FOR NHAR COUNT MOV A,C ; REDUCE COUNT TO SUI 1 ; EXCLUDE MOVE OF 0DH MOV C,A CALL BLKTFR ;MOVE A-TEXT XCHG SHLD DESAV ;SAVE DESTIN POINTER XRA A ALL BLKTFR ;MOVE TEXT LXI H,LABSAV ; ADDR LABEL CALL CNTLN ;C = CHAR COUNT MOV B,C ; DUPL COUNT IN B LHLD APTR ;GET A-POINTER CALL DECA ;BACK UP ADDR LHLD APTR ;LAST A-ADDR CALL DECA ;BACK UP DESTIN ADDRESS MOV A,C ; IF CHAR COUNT = 0 ORA A RZ ; THEN RETURN LXI H,EBUFF ; SOURCE ADDR C ENTRY CALL ASTORE ; STORE IT RET ; THEN EXIT NIN: CPI 043O ;IF NOT # JNZ CENT ; THEN CALL ENTRY INX H ;ELSE ADDR VARIABLE MOV A,M ; B & C = CHAR COUNT IN WORD TO BE MOVED ; RETURNS:DE = DESTIN ADDR, C = CHAR COUNT ; APTR POINTS AT STOP(01) BELOW LIST ; DECA: MOV E,L ;DESTIN ADDR IN DE MOV D,H DCX H ;DECR POINTER MUMBER JM NERR ;TOO LOW CPI '9'+1 RM ;MUST BE NUMBER NERR: LXI H,NMSG ;OUT OF RANGE CALL ERROR ;SEND MESSAGE CALL ENTRY ;TRY AGAIN JMP CKNUM ; SET RETURN FLAG RET ; ; A OPERATION-- ACCEPT INPUT ; ENTER: HLSAV = ADDR AFTER COLON ; RETURNS: INPUT IN EBUFF ; 'CTL Z' ALLOWS SINGLE STATEMENT EXECUTION OR QUIT ; AOP: LHLD HLSAV ;ADDR EXPRESSION MOV A,C ; IF CHAR COUNT = 0 ORA A RZ ; THEN RETURN LXI H,LABSAV ; SOURCE ADDR CALL BLKTFR ;MOVE THE LABEL MOV L,E ; ADDR A-TEXT MOVY RET ; ENTRY: CALL KEYIN ;GET ONE LINE IN EBUFF LXI H,EBUFF ;IF ENTRY NOT CTL Z MOV A,M CPI 1AH RNZ ;THEN RETURN INX H ;ELSE BUMP POINTER GET THE NAME STA VARSAV ;AND SAVE IT CALL ENTRY ;GET THE ENTRY CALL CKNUM ;REQUIRE NUMERIC CALL NSTORE ; STORE THE NUMBER RET ;THEN EXIT CENT: CALL ENTRACK UP AGAIN? SHLD APTR ;SAVE A-POINTER MVI M,1 ;SET STOP RET ; STOVF: LXI H,NRMSG ; COMPLAIN OF OVERFLOW CALL ERROR MVI C,0 ; SET CHAR COUNT = 0 RET ; CHAR MOV B,A ; SAVE IT CPI 0DH ; IF EOL RZ ; THEN RETURN LDA MBRCH ;GET CURRENT BR CHAR CMP B RET ; ; PAD ADDS A BLANK TO EACH END OF A STRING OF LINE CPI 0DH JZ MDONE ; THEN QUIT INX H ;ADDR NEXT CHAR MOV A,M ; IF END OF LINE CPI 0DH JZ MDONE ; THEN QUIT JMP NEXTM ;EL ; ELSE BUMP TO NEXT MOV M,E RET ; ; M OPERATION - MOVING WINDOW STRING MATCH ; COMPARE ITEMS IN LIST WITH LAST INPUT ; M-ITEMS HAVE MULTIPLE BLANKS REDUCED TO ONE ; INPUT HAS BLANK ADDED AT EACH END AND ; M ;HL = NEXT SOURCE ADDR JMP MMOV2 ;CHECK THE NEXT CHAR SMOV: INX H XCHG ;HL = DESTIN BR CHAR ADDR MVI A,0DH ; PUT AN 0DH THERE MOV M,A INX H XCHG LXI H,EBUFF ; PUT EBUFF ADDR SHLD HLSAV ; IN HLSAV LXI H,MSAVE ; PUT MSAVE ADDR SHLD HLLSAV ; IN HLLSAV CALL INDEX ;LOOK FOR M-ITEM MOV A,C ORA ; NUMBER STORAGE - STORAGE OF NUMERIC VALUE FROM ENTRY ; AS VALUE OF VARIABLE NAME IN A-STATEMENT ; NSTORE: LXI H,EBUFF ; SOURCE ADDR CALL GETCH ;ADDR 1ST CHAR CALL GETNM ;GET THE NUMBER MOVE M-ITEM TO MSAVE ; ITEMS ARE SEPARATED BY COMMA OR TERMINATED BY 0DH ; ENTER: MPTR = M-ITEM ADDRESS ; RETURNS: HL & MPTR = NEXT M-ITEM ADDR ; B = BR CHAR ; MMOV: LHLD MPTR ;GET M-POINTER LXI D,MSAVE SE MORE M-ITEMS MDONE: CALL SWN ;SET SWITCH NO RET ; SWY: ORA H ; SET YN SWITCH YES STA YNSW RET ; SWN: XRA A ; SET YN SWITCH NO STA YNSW RET ; ; M-MOVE: ULTIPLE BLANKS REDUCED TO ONE. ; ENTER: HLSAV = ADDR AFTER LAST COLON, INPUT IN EBUFF ; RETURNS: YNSW = 0 IF MATCH NOT FOUND WITH LAST ENTRY ; MC: LXI H,MBRCH ;SET BR CHAR MVI M,'^' ; TO CARET (SHIFT N) JMP MO ;HL = NEXT M-ITEM ADDR SHLD MPTR ;SAVE M-POINTER RET ; ; M-BREAK CHAR BETWEEN ITEMS ; ENTER: HL = CHAR ADDR ; RETURNS: A,B = CHAR. IF BR CHAR THEN Z FLAG TRUE ; MBR: MOV A,M ; GET A ; IF ITEM FOUND CNZ SWY ; THEN SET SWITCH YES RNZ ; AND RETURN LHLD MPTR ;RETRIEVE M-POINTER DCX H ;ADDR BR CHAR MOV A,M ; IF ENDLXI H,VARSAV ; GET THE NAME IN B MOV B,M CALL VARMCH ;LOOK IT UP CPI 1 ;IF END MARKER CZ BADFRM ;THEN COMPLAIN RZ ; AND RETURN INX H ; DESTIN ADDR MMOV2: CALL MBR ;IF BR CHAR OR EOL JZ SMOV ; THEN STOP THE MOVE INX H XCHG ;HL = DESTIN ADDR MOV M,B ; MOVE CHAR INX H XCHG EM SHLD HLSAV CALL SQUEZ ;REDUCE MULTIPLE BLANKS LXI H,EBUFF SHLD HLSAV ;HLSAV = STRING ADDR CALL PAD ;ADD BLANKS AT EACH END CALL SQUEZ ;REDUCE MULTIPLE BLANKS P1 MOP: LXI H,MBRCH ;SET BR CHAR TO COMMA MVI M,',' MOP1: LHLD HLSAV ;ADDR EXPRESSION FIELD SHLD MPTR ;INIT M-POINTER NEXTM: CALL MMOV ;MSAVE = M-ITEM LHLD MPTR ;ADDR M-IT; ENTER: HLSAV = STRING ADDRESS ; PAD: LXI H,WORD MVI A,' ' ; SET BLANK AT FRONT OF MOV M,A INX H ;DE = DESTIN ADDR XCHG LHLD HLSAV ;GET SOURCE ADDR CALL ;ADD VALUES CPI 100 ;IF > 99 JP OVMSG ; THEN COMPLAIN MOV E,A ; ELSE FORM NEW VALUE JMP AVAL ;ASSIGN VALUE SUBV: INX H ;BUMP POINTER OR X = X - X ; WHERE X = SINGLE LETTER VARIABLE NAME A-Z ; FIRST LETTER ONLY OF LONGER NAME GETS USED ; ENTER: HLSAV = ADDR OF EXPRESSION FIELD ; COP: LHLD HLSAV ;ADDR EXPRESSION FIELD MVI B,'=' ; CALL CNTLN LXI H,WORD CALL BLKTFR RET ; ; SQUEZ REDUCES MULTIPLE BLANKS TO A SINGLE BLANK ; ENTER: HLSAV = STRING ADDRESS ; SQUEZ: LHLD HLSAV ;ADDR STRING SHLD HLLSAV ;SAVE POINTER CHAR CPI 0DH ; IF END OF LINE JZ AVAL ; THEN ASSIGN VALUE CPI '-' ;IF MINUS JZ SUBV ; THEN SUBTRACT VALUE CPI '+' ;IF PLUS JZ ADDV DH ; SHIFT: INX H ;ADDR NEXT CHAR MOV B,M ; GET IT IN B DCX H ;MOVE IT MOV M,B MOV A,M CPI 0DH ; IF IT WAS EOL RZ ; THEN RECNTLN ;C = CHAR COUNT LHLD HLSAV ;GET SOURCE ADDR CALL BLKTFR ;MOVE TEXT XCHG ;ADDR NEW TEXT END DCX H ;SET BLANK AT MVI A,' ' ; END OF ;IF NOT MINUS SIGN JNZ CGVAL ; THEN GET THE VALUE SHLD HLLSAV ;SAVE THE POINTER XRA A STA TEMP ;SET TEMP = 0 LHLD HLLSAV ;RETRIEVE POINTER JMP SUBV LOOK FOR EQUAL SIGN CALL INDX MOV A,C ORA A ; IF NOT PRESENT JZ EXMSG ; THEN COMPLAIN INX H ;BUMP POINTER CALL GETCH ;GET THE CHAR CPI '-' MOV A,M ; GET CHAR CKEOL: CPI 0DH ; IF EOL RZ ; THEN RETURN CPI ' ' ;IF BLANK JZ CKNC ; THEN CHECK NEXT CHAR INX H ;ELSE BUMP ADDR ; THEN ADD VALUE CALL GVALUE ;ELSE GET VALUE JMP AVAL ;ASSIGN VALUE ADDV: INX H ;BUMP POINTER CALL GVALUE ;GET THE VALUE LDA TEMP ;GET OLD VALUE ADD ETURN INX H ; ELSE MOVE ANOTHER JMP SHIFT ; ; C OPERATION: COMPUTE WITH TEXT OF STATEMENT ; LIMITED TO: X = NN (NN = INTEGER -99 TO +99) ; OR X = X + NN OR X = X - NN ; OR X = X + X MOV M,A ; TEMP STRING INX H ;SET EOL MVI A,0DH MOV M,A LHLD HLSAV ;MOVE NEW STRING XCHG ; TO ORIGINAL LXI H,WORD ; LOCATION ; AND SUBTRACT CGVAL: CALL GVALUE ;GET THE VALUE LXI H,TEMP ; SAVE IT MOV M,E LHLD CPTR ;RETRIEVE CHAR POINTER INX H ;BUMP POINTER CALL GETCH ;GET CALL SHIFT ; REMOVE A BLANK LHLD HLLSAV ; RETRIEVE ADDRESS JMP CKNC1 ; AND CONTINUE ; ; SHIFT STRING CHARS LEFT WITH LOSS OF FIRST CHAR ; ENTER: HL = ADDR OF STRING ; RETURNS: HL = ADDR OF 0 JMP SQUEZ+3 ; AND CONTINUE CKNC: INX H ;IF NEXT CHAR IS CKNC1: MOV A,M ; NOT BLANK CPI ' ' ; THEN CHECK IF EOL JNZ CKEOL SHLD HLLSAV ;ELSE SAVE ADDRESS CALL GVALUE ;GET THE VALUE LDA TEMP ;GET OLD VALUE SUB E ;SUBTRACT VALUES CPI 9DH ;IF >= -99 JP AVAL-1 ; THEN CONTINUE CPI 100 ;IF > 99 NEXT LETTER MOV B,A ; SAVE IN B JMP NV ;NEXT VARIABLE ; ; SAVE RETURN POINTER IN STACK ; ENTER: IPTR = START OF NEXT SOURCE LINE ; RETURNS: LEVEL BUMPED ONE HIGHER ; IPTR COPIED AT LEVEET ; AND RETURN ; ; BASIC INTERPRETATION - ; IF PROGRAM TEXT IS NOT LEGAL PILOT, THEN ; AN ALTERNATE INTERPRETER SUCH AS BASIC CAN BE ; SUPPLIED TO BE TRIED BEFORE PILOT COMPLAINS. ; BASIC: ORA H ;DUMMY ILLEGAL ERROR RET ; ; GVALUE - GETS VALUE OF CONSTANT OR VARIABLE ; ENTER: HL = ADDRESS OF CHAR NAMING THE VARIABLE ; CPTR = ADDRESS OF CHAR ; RETURNS: E = VALUE ; CPTR = ADDRESS OF THE CHARACTER ; GVALUE: CALL GEERO VALUE ; INITV: LXI H,NVAR ;ADDR FRONT OF VAR LIST MVI B,'A' ;START WITH 'A' MOV A,B NV: CPI 'Z'+1 ;IF ALPHABET COMPLETE RZ ;THEN RETURN MOV M,A ; RY VALUE IN E ; ASSIGN: LHLD HLSAV ;ADDR EXPRESSION FIELD CALL GETCH ;GET FIRST CHAR CALL LETTER ;IF NOT A LETTER JNZ EXMSG ; THEN COMPLAIN MOV B,M ; GET CHAR IN B JP UNMSG ; THEN COMPLAIN MOV E,A AVAL: CALL ASSIGN RET ; EXMSG: CALL TOP ;SHOW THE BAD EXPR LXI H,EXPMSG CALL ERROR RET ; OVMSG: MVI E,99 ; SET VALUE TO 99 JZ RSTRT CALL RESRET ; ELSE SET RETURN FROM RET ; PILOT CALL ; LOAD: LXI H,PBUFF CALL INPUT RET ; ; NEW$ DELETES $NAMES BY RESETTING A-POINTER ; NEWN: LHLD APTR ;REMORETURN RET ; ; R OPERATION - ; ENTER: HLSAV = R-STATEMENT ADDRESS ; ROP: RET ; ; E OPERATION - RETURNS FROM CALL OR ENDS PROGRAM ; EOP: LDA LEVEL ;IF RETURN LEVEL = 0 ORA A ; THEN QUIT TCH ;GET CHAR MOV E,A ; SAVE IN E CALL LETTER ;IF LETTER JZ LTR ; THEN PROCEED CALL GETNM ;ELSE EXPECT NUMBER SHLD CPTR ;SAVE CHAR POINTER STORE THE LETTER INX H ;BUMP ADDRESS MVI A,0 MOV M,A ; STORE ZERO INX H ;BUMP THE ADDRESS MOV A,B ; GET LETTER ADI 1 ;CHANGE TO CALL VARMCH ;LOOK IT UP CPI 1 ;IF END MARKER CZ BADFRM ; THEN COMPLAIN RZ ; AND RETURN INX H ; ELSE BUMP TO VALUE ADDR MOV M,E R CALL ASSIGN CALL TOP ;SHOW THE EXPR LXI H,OVFMSG CALL ERROR RET ; UNMSG: MVI E,-99 ; SET VALUE TO -99 CALL ASSIGN CALL TOP LXI H,UNFMSG CALL VE STOP CHAR MVI M,20H LHLD MEMTP ;ADDR MEMTP MVI M,1 ;PLACE STOP CHAR DCX H SHLD APTR ;STORE MEMTP-1 ADDRESS RET ; ; INITIALIZE NUMERIC VARIABLES ; SETS A-Z TO Z ; AND RETURN INX H ;ELSE POINT AT VALUE MOV E,M ; SAVE VALUE IN E RET ; ; ASSIGN SETS A NEW VALUE TO AN OLD OR NEW VARIABLE ; ENTER: HLSAV = ADDR OF EXPRESSION FIELD ; BINA RET LTR: SHLD CPTR ;SAVE CHAR POINTER CONV: MOV B,M ; SAVE CHAR IN B CALL VARMCH ;LOOK IT UP CPI 1 ;IF END MARKER CZ BADFRM ; THEN COMPLAIN RZ L POSITION ; SAVRET: LXI H,LEVEL ;GET CURRENT LEVEL MOV A,M ADI 1 ;BUMP TO NEXT LEVEL CPI 8 ;IF < 8 JM SAV2 ; THEN CONTINUE LXI H,STMSG ;ELSE STACK OVEPTR DCX H ;DECR POINTER SHLD EPTR JMP KIN2+3 ; CRLF: MVI C,0DH CALL CO LF: MVI C,0AH CALL CO RET ; ; INPUT PROGRAM TO BUFFER AREA ; DEL (SHIFT O) CANCELS LAST CHAES B FOR CHAR COUNT, C FOR OUTPUT ; KEYIN: LXI H,EBUFF ;POINT AT EBUFF SHLD EPTR ;SAVE POINTER LXI H,CHMAX ;GET MAX COUNT MOV B,M KIN2: LHLD EPTR ;RETRIEVE POINTER CALL CI MOV M,E RET ; ; RESET RETURN POINTER FROM STACK ; RETURNS: IPTR SET TO LAST SAVED RETURN ; LEVEL REDUCED BY ONE ; RESRET: LDA LEVEL ;GET RETURN LEVEL ADD A ;DOUBLE IT MOV C,A I C,0DH ;ELSE END WITH CR MOV M,C CALL CO ; AND SEND IT KOUT: CALL LF ;SEND LINE FEED RET ; AND RETURN CANL: MVI C,3CH ;SEND < CALL CO CALLE CHARACTER INX H ;GET NEXT DEST ADDR XCHG MOV M,B ; PUT IT IN DEST LOCATION INX H ;GET NEXT SOURCE ADDR XCHG MOV A,C ; DECREMENT COUNT SERFLOW CALL ERROR RET SAV2: MOV M,A ; STORE IT ADD A ;DOUBLE IT MOV C,A ; SAVE IN C LHLD IPTR ;PUT IPTR IN DE XCHG LXI H,RETSAV JZ CANL ; THEN CANCEL LINE CPI 61H ;FORCE UPPER CASE JM NTR XRI 20H NTR: MOV M,A ;STORE THE CHAR INX H ;INCR POINTER SHLD EPTR ;SAVE IT ;GET CHAR AND ECHO CPI 5FH ;IF DEL JZ CANC ; THEN CANCEL LAST CHAR CPI 7FH ;IF RUBOUT JZ CANC ; THEN CANCEL LAST CHAR CPI 15H ;IF CTL/U ; SAVE IN C LXI H,RETSAV ; GET BASE ADDR MOV A,L ADD C ;BASE + 2 X LEVEL MOV L,A ; HL = STACK ADDR MOV D,M ; SAVE POINTER IN DE ADI CRLF ;SEND CRLF JMP KEYIN ; START OVER CANC: MOV A,B ;INCR CHAR COUNT LXI H,CHMAX ; UNLESS AT BEGINNING MOV C,M CMP C JZ KIN2 INR B LHLD UI 1 MOV C,A JNZ BLKTFR ;IF NONZERO THEN NEXT RET ; ; KEYBOARD INPUT TO EBUFF ; ENTER: CHMAX= MAXIMUM CHARS ALLOWED IN LINE ; DEL (SHIFT O) OR RUBOUT CANCELS LAST CHAR ; CTL/U CANCELS CURRENT LINE ; US ; GET BASE ADDR MOV A,L ADD C ;BASE + 2 X LEVEL MOV L,A ; HL = STACK ADDR MOV M,D ; SAVE IPTR ADI 1 MOV L,A ; HL = STACK ADDR+1 CPI 0DH ;IF CR JZ KOUT ; THEN STOP ENTRY DCR B ;ELSE DECR CHAR COUNT MOV A,B ORA A ;IF COUNT NOT 0 JNZ KIN2 ; THEN NEXT CHAR MVNSFER FROM HL TO DE, C CHARACTERS ; RETURNS: HL AND DE AT LAST CHAR+1 ADDR ; BLKTFR: MOV A,C ; GET COUNT ORA A ; IF COUNT = 0 RZ ; THEN RETURN MOV B,M ; GET A SOURC1 MOV L,A ; HL = STACK ADDR+1 MOV E,M XCHG SHLD IPTR ;RESET IPTR LXI H,LEVEL ;REDUCE LEVEL MOV A,M SUI 1 MOV M,A RET ; ; BLOCK TRAR, CTL/U CANCELS LINE ; TERMINATES WITH CTL/Z (1AH) ; INPUT: CALL BLKBF ;BLANK THE BUFFER LXI H,PBUFF ;SET POINTER INPT1: MOV A,M ;GET EXISTING CHAR SHLD LLSAV ;SAVE FIRST CHAR ADDR CDATA AVAIL (RDA) ; BIT 0 (1H) FOR TRANSMIT BUFFER EMPTY (TBE) ; ; OUTPUT CHAR FROM C ; LOOKS FOR CTL/Z INPUT FOR PANIC EXIT ; CHO: IN STPORT ;GET STATUS ANI RDA ;IF NO INPUT JZ CHO1 ;THEN CONTINUE CALL CI ;ELSE SEE WHAT IT IS CP ;SAVE IT MOV E,L CPI 1 ;IF 01 RZ ; THEN RETURN MOV C,A ;PUT CHAR IN C LHLD OUTADR ;MAKE AN INDIRECT CALL CALL OVCTR ; TO SEND THE CHAR CPI 7FH ;IGNORE RUBOUTS JZ INPT3 CPI 1AH ;IF TERM CHAR CTL/Z JZ INEND ; THEN END OF INPUT CPI 15H ;IF CTL/U JZ KLN ; THEN KILL THE LINE CALL PRGOUT RET ; LPRG: LXI H,LO ;LIST PROGRAM IN MEMORY SHLD OUTADR CALL PRGOUT LXI H,CO ;RESET TO CONSOLE SHLD OUTADR RET ; SPRG: LXI H,PO ;SAV CALL DSPLY LXI H,IOVMSG CALL ERROR INEND: MVI M,1 ;STORE END MARK SHLD TOPP ;STORE ADDRESS CALL CRLF ;SEND CRLF LXI H,LEVEL ;ZERO RETURN LEVEL MVI M,0 PI 1 ;IF END MARK JZ CHOP ; THEN CHOP ENTRY CALL RI ;GET CHAR CPI ' ' ;IF NOT BLANK JNZ INPT3+3 ; THEN CONTINUE JMP INPT1 ;ELSE SKIP LEADING AN INDIRECT CALL CALL OVCTR ; TO SEND IT XCHG ;RETRIEVE POINTER CALL SKLN ;SKIP ANY LINE NOS. RET OVCTR: PCHL ; ; OUTPUT PROGRAM IN MEMORY TO 01 END MARK ; PRGOUT: LXI H,PBUFF CPI 0DH ;IF CR JZ ENDOL ; THEN EOL XCHG ;ELSE RETRIEVE POINTER JMP DSPLY ;AND DISPLAY MORE ENDOL: MVI C,0AH ;SEND LINE FEED LHLD OUTADR ;MAKE CPI 5FH ;IF DEL JZ CLC ; THEN CANCEL LAST CHAR MOV M,A ;ELSE STORE THE CHAR INX H ;AND INCR THE POINTER CPI 0DH ;IF NOT CR JNZ INPT2 E PROGRAM SHLD OUTADR CALL PRGOUT LXI H,CO ;RESET TO CONSOLE SHLD OUTADR RET ; ; I/O ROUTINES ; USE STPORT (MDS-0F7H) FOR STATUS, PORT (MDS-0F6H) FOR DATA ; STATUS BIT 1 (2H) FOR READ RET ; ; DISPLAY A CHARACTER STRING TO CR OR 01 ; ENTER: HL = STARTING ADDRESS ; OUTADR CONTAINS ADDRESS OF CO, LO, OR PO ; DSPLY: MOV A,M ;GET A CHARACTER INX H ;BUMP POINTER MOV D,H BLANK INPT2: MOV A,M ;GET EXISTING CHAR CPI 1 ;IF END MARK JZ CHOP ; THEN CHOP ENTRY INPT3: CALL RI ;GET CHARACTER CPI 0 ;IGNORE NULLS JZ INPT3 ;PGM START ADDR CALL DSPLY ;DISPLAY ONE LINE CPI 1 ;IF NOT END MARK JNZ PRGOUT+3 ; THEN MORE RET ; DPRG: LXI H,CO ;DISPLAY PROGRAM IN MEMORY SHLD OUTADR EL LAST CHAR JMP INPT3 KLN: MVI C,3CH ;SEND < CALL CO CALL CRLF ;SEND CRLF LHLD LLSAV ;ADDR FRONT OF LINE JMP INPT3 CHOP: LHLD LLSAV ;ADDR FRONT OF LINE ; THEN GET NEXT CHAR CALL LF ;ELSE SEND LF JMP INPT1 ;AND GET NEXT NEW LINE INPT4: MOV M,A ;STORE CHAR INX H ;INCR POINTER JMP INPT2 CLC: DCX H ;CANCI 1AH ;IF CNTRL/Z JZ INTR ;THEN INTERRUPT CHO1: IN STPORT ;NOW FOR STANDARD OUTPUT ANI TBE JZ CHO1 MOV A,C OUT PORT RET ; INTR: PUSH H ;SAVE REGISTERS PUSH D DXVdSKLNзjSMOVзmSPRG*kSQUEZаbSTARTaSTKPR‰nSTMSGOjSTOVFчSTPORT;uіkSUBVОjSWNЙjSWY iTALLTBEIaTEMPЬhTMOREiTMOVEМhTOPaTOPPLaTSAVEйcTXTCK|nUNFMSGЁfUNITSzгkUNMSG[fUOPѓdVARCHKґdVARMCHJaVARSAV0i1|‚mCHOPaCIlcCKEND1kCKEOLdCKLC2dCKLN=kCKNC>kCKNC1тiCKNUMpmCLCЎeCLRE·eCLRH¬eCLRLNgCMPRрgCNTLNхz™gCNTWDaCO–cCONTINlCONV\kCOP8aCPTRmCRLFВdCTLMCHнdCTLSTѓeCURS1ЏeCURS2–eCURS3›eCURS4qeCURSRvAG SET ; ERROR: CALL DSPLY XRA A RET ; ; ERROR MESSAGES ; BLMSG: DB '- LABEL NOT FOUND',0DH ; IOVMSG: DB '/OVERFLOW',0DH ; NRMSG: DB '*NO ROOM',0DH ; EXPMSG: DB '*ILLEGAL EXPRESSION',0DH ; OVFMSG: DB '*VMNTRyjMOP~jMOP1 99',0DH ; UNFMSG: DB '*VALUE < -99',0DH ; STMSG: DB '*USE DEPTH EXCEEDED',0DH ; NMSG: DB '*NUMERIC RESPONSE REQUIRED',0DH ; INTMSG: DB '*INTERRUPTED',0DH ; IBUFF: DB 'T:',0DH DB 'T:PILOT-8080, 1.1',0DH ; GФkOVMSGьjPADpPBUFBяPBUFEpPBUFF aPOцPORTБmPRGOUTаbPSTRTёfPUTNMRDAаx‹lRESRET$aRETSAVaRIДeROLL.lROPcRSTRTЦdRTRNxlSAV2бgSAVOPflSAVRET\cSCANBaSCANBHaSCNTґfSDIG v…hSETCNTГhSETUPPkSHIFTџhSIN MODULE(wўkADDV}fADRCMPШcALTSC«iAOP4aAPTRaASCANlASSIGNjASTOREЖkAVALhBACKUP§dBADFRM,lBASICtfBLKB2TykfBLKBFafBLKSET§lBLKTFR6nBLMSG hBRCHARmCANCшlCANLЧiCENTkCGVAL!nCHIgCHKDaCHMAXчmCHOnCHO STPORT ;NORMAL INPUT ANI RDA JZ CHI IN PORT ANI 7FH MOV C,A CALL CO RET ; ; ERROR - DISPLAYS ERROR MESSAGE ; ENTER: HL = ADDRESS OF MESSAGE ; RETURNS: ZERO FLlKEYINВlKIN2tmKLNфlKOUT?bLABSAVKbLASTOPuiLBLіhLETTEREaLEVELmLFGgLFNDHLINEП{"aLLSAVFaLNSKP aLO:lLOADчfLOOKрfLOOKLйfLOOKSЧmLPRGШdLSTMCHlLTRтjMBRGaMBRCHqjMC|gMCHЕjMDONEэ}>aMEMTPУjMMOVЩjMMOV2 DB '*% IEP:',0DH ; ; ORG HERE CAN SET START OF RAM PROGRAM BUFFER SPACE ; ORG PBUFB PBUFF: DB 1 ; ; SOURCE PROGRAM AND $STRING STORAGE HERE TO MEMTP END START DB ':LOAD A NEW PROGRAM?',0DH ; DB 'A:',0DH ; DB 'M: Y',0DH ; DB 'JN:*%',0DH ; DB 'T:ENTER PILOT PROGRAM',0DH ; DB ':TERMINATE INPUT WITH CTL/Z',0DH ; DB 'LOAD:',0DH ;VBLЉdVCHKwюVIDEOҐdVOFF§gWDTFR‹bWORDfgXENDodYCHKvgYENDBв*`dYNCHKЭgYNOUTKaYNSWTdYNUMњhZCн8Гаb¶HaГ!nГчmГ!nГчmГчmГГГ,lGa аb1a!ю"4a!чbaН§lГcГ!nГчmГ!nГчmГчmГГГ,l1еееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееел+> w#> w*aл!‹bНрg!‹bН§lЙ*a"a~ю Ию К=k#Г-k#~ю В1k"aНPk*aГ>k#F+p~ю И#ГPk*a=НЉhy·ККk#Нgю-Вk"aЇ2Ia*aГіkНтk!Ias*8a#Нgю КЖkю-Кіkю+КўkНтkГЖk#Нтk:IaѓюdтФk_ГЖk#Нтk:Ia“юќтЕkюdтгk_НlЙНМh![nН1nЙcНlНМh!onН1nЙќНlНМh!|nН1nЙНg_НіhКlН„f"8aЙ"8aFНґdюМ§dИ/lY МhN МhLOAD :lINMAX ЬeNEW$ AlDP НmPRINT ЧmSAVE зmIEP ПeBYE aEDIT aCA qeCE ЎeCL ¬eCH ·eRL ДeНa&НaaНa*a~ю,К–eю К›eOНa#ГѓerГЏeCНaЙНaJНaЙНaKНaЙНaHНaГЎeНaSНaЙ!p":a"BaНйcЙНнe{юIъиe>H_!DasЙ*aНgю ИНЏg+"a!‹bНіhВfFНґdюМ§dИAM :TERMINATE INPUT WITH CTL/Z LOAD: *% IEP: ¦p„аbґсPTH EXCEEDED *NUMERIC RESPONSE REQUIRED *INTERRUPTED T: T:PILOT-8080, 1.1 :LOAD A NEW PROGRAM? A: M: Y JN:*% T:ENTER PILOT PROGRН§l> лw!LaНњmЇЙyЦК0iO* aл*8aН§lDMл" a`i#N#"8aAНґdюИ#^!‹bНёf* aл!‹bНГhyЦOН§lл" aЇЙyЦКuiO* aл*8aН§lDMл" a`iНЏg+"8a*4a#НйfюИН’iЙ#DM* aл`iНГhyЦOН§lл" aЇЙ*aНgю$ВГi?bН§gНЫiНjЙю#ВЧi#~2JaНЫiНтiНXjЙНЫiЙНёl!ќa~юА#~ю КcНЄcГЫiю0ъъiю:ш!ќnН1nНЫiГтi!ќaНрgA*4aaН2cН\cГc020677 PILOT-8080, 1.1 !Еn":a"Ba!я">aНAlНPl6>H2DaЇ2Ea2Fa!a"@aЙ*:a~юИю Вlc#Г_cНрgюИ#":a+НhНVdНgю:М–cК\cю*МЏgК_cНЄcГ\c#"a!Kb""a:НЉhНВcЇЙ""aНбg*"a:НЉhy·КШc#"a++Н`d·ИНѓdИ*"aНДgНВdюА*"aНaИ*"a"aНМhЙ!pНрg#~ю ВdНрg#~ю Вd:FaЖ2Fa!pНрg#Н+"6aГЕl Нa НaЙНkf!p~""aюК‚mНaю ВEmГ(m~юК‚mНaюКBmюКBmюКЋmюКtmю_Кpmw#ю Вa6+"4aЙ!VbAxю[Иw#>w#xЖGГVl!Ea~Жюъxl!‰nН1nЙw‡O*:aл!$a}ЃorЖosЙ:Ea‡O!$a}ЃoVЖo^л":a!Ea~ЦwЙy·ИF#лp#лyЦOВ§lЙ!ќa"6a!DaF*6aНaю_КmюКmюКшlюaъЮlо w#"6aю Кфlx·ВВl qНaНmЙ<НaНmГёlx!DaN№КВl*6a#^ГfН„f{·рЙ*aНgю*К:f>*2‹bЊb*aН§gГ=fНЏg*BaНрfюМNfИ#":aЙ!‹bНњm!6nН1nЙНflГfp#yЦOВafЙ*4aл!p p#Н}fВtfЙ|єшА}»Й#Н hКґfю+Кґfю-Кґf+~ю0шю:рЦ0‡_‡‡ѓ_#~ю0шю:рЦ0ѓ_Й+ГЁf{·ьбfю ъОfЦ _yЖOГєfyЖ0ю0КШfw#{Ж0w#> wЙ>-w#Ї“_ЙЇ2IaГчfґ2IaНVdНgюИю*Кgю$КgНрg#:Ia·КееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееН9jy·И!ќaН§l!?bНрgA*4aН9jy·И!?bН§lkb+> wЙ]T+~юКOjxЦGВ9j"4a6Й!RnН1nЙ!ќaНgН„f!JaFНґdюМ§dИ#sЙ!Ga6^Г~j!Ga6,*a" w#л" w#л*aНрg*aН§lVd^~ю В2d#НVd^~ю В2d:FaЖ2Fa!pНрg#НVd~НJdА:FaЖ2FaЙю0шю:ъTdґЙЇЙ:Fa·И#=ГYdН‡gюYКodюNКxd·Й:Ka·КЃdґЙ:Ka·ВЃdґЙЇЙю)КЉdґЙ++~ю(В§d#FНґdюК§d#~юъҐdґЙЇЙ*"aНПh![nН1nЙ!Vb~юИёИ##Г·dнdНШdюИл#ЦdХ^#VХЙЇЙ!‹bНNg·А#л###~юИлГШdT МhA «iM yjMC qjJ fR .lC \kU [fE ЙеХЕ!ёnН1nНЫiБСбЙЫчжК!nЫцжOНaЙНњmЇЙ- LABEL NOT FOUND /OVERFLOW *NO ROOM *ILLEGAL EXPRESSION *VALUE > 99 *VALUE < -99 *USE DEPTH EXCEEDED *NUMERIC RESPONSE REQUIRED *INTERRUPTED T: T:PILOT-8080, 1.1 :LOAD A NEW PROGRAM? A: M: Y JN:*% T:ENTER PILOT PROGRИю Ию,Ию;Ию:Ию.Ию?Ию!Ию"Ию(Ию)Ию'ИюЙЇ2Ha*aл*aF#лНЉhy·И"a:HaЃ2Ha*aНрgyЦO‹b*aН§l"6aл> w*aл!‹bНNg·В…h*a#"aГ9h!HaNЙ~ёИю КњhyЖO#ГЊhЇOЙ~ю$Ию#Ию ИyЖO#ГЎh~FюAъБhюZтБhЇЙґЙНрgAНhHЙ*a"8a""a!La" aл*8aНџhю$Кпhю#КiГiНdiюВЬhLa*"aГ iНiГтh* aл*8aНГhчfГфf"aН™gyю ъ#g *a?bН§lл+> w!?b‹bНNg·ВGg*aН™gГчf*aН™gЙ~ю КfgO#л~ю Кvg№Вsg#лГNgл~ю К|gН™gлЇЙН™gлН™gЇЙлґЙ~ю А#Гg~ю А+Г‡gНg‹bН§gЙН hИyЖO#Г›gН hК»g#лpyЖO#лГ©g#л> w#лЇЙ‹bН§gyюшbk++Н‡gюYКЭgюNА> wЙ:НЉh*"aKbН§lЙ~ю ИюИyЖO#ГтgyюИЦO+Гh~Gю MODULEwўkADDV}fADRCMPШcALTSC«iAOP4aAPTRaASCANlASSIGNjASTOREЖkAVALhBACKUP§dBADFRM,lBASICtfBLKB2TykfBLKBFafBLKSET§lBLKTFR6nBLMSG hBRCHARmCANCшlCANLЧiCENTkCGVAL!nCHIgCHKDaCHMЖO#ГЎh~FюAъБhюZтБhЇЙґЙНрgAНhHЙ*a"8a""a!La" aл*8aНџhю$Кпhю#КiГiНdiюВЬhT|чhLa*"aГ iНiГтh* aл*8aНГhН§l> лw!LaНњmЇЙyЦК0iO* aл*8aН§lDMл" a`i#N#"8aAНґdюИ#^!‹bНёf* aл!‹bНГhyЦOН§lл" aЇЙyЦКuiO* aл8|oi*8aН§lDMл" a`iНЏg+"8a*4a#НйfюИН’iЙ#DM* aл`iНГhГчmГчmГГГ,l1aН2cН\cГc020677 PILOT-8080, 1.1 !Еn":a"Ba!я">aНAlНPl6>H2DaЇ2Ea2Fa!a {Xc"@aЙ*:a~юИю Вlc#Г_cНрgюИ#":a+НhНVdНgю:М–cК\cю*МЏgК_cНЄcГ\c#"a!Kb""a:НЉhНВcЇЙ""aНбg*"a:НЉhy·КШc#"a++Н`d·ИНѓdИ*"a¦{ПcНДgНВdюА*"aНaИ*"a"aНМhЙ!pНрg#~юVALUE«uaHL2SAVaHLLSAVaHLSAVЕnIBUFFПeIEP9hINDE25hINDEXЉhINDXЋmINEND2cINITPlINITVЬeINMAXиeINMX2ьz(mINPT1 wЙ>-w#Ї“_ЙЇ2IaГчfґ2IaНVdНgюИю*Кgю$КgНрg#:Ia·КчfГфf"a}{gН™gyю ъ#g *a?bН§lл+> w!?b‹bНNg·ВGg*aН™gГчf*aН™gЙ~ю КfgO#л~ю Кvg№Вsg#лГNgл~ю К|gН™gлЇЙН™gлН™gЇЙлґЙ~ю А#Гg~ю А+Г‡g.}ЏgНg‹bН§gЙН hИyЖO#Г›gН hК»g#лpyЖO#лГ©PkSHIFTџhSINDXVdSKLNзjSMOVзmSPRG*kSQUEZаbSTARTaSTKPR‰nSTMSGOjSTOVFчSTPORT;uіkSUBVОjSWNЙjSWY iTALLTBEIaTEMPЬhTMOREiTMOVEМhTOPaTOPPLaTSAVEйcTXTCK|nUNFMSGЁfUNITSzгkUNMSG[fUOPѓdVARCHKґdVARMAXчmCHOnCHO1|‚mCHOPaCIlcCKEND1kCKEOLdCKLC2dCKLN=kCKNC>kCKNC1тiCKNUMpmCLCЎeCLRE·eCLRH¬eCLRLNgCMPRрgCNTLNхz™gCNTWDaCO–cCONTINlCONV\kCOP8aCPTRmCRLFВdCTLMCHнdCTLSTѓeCURS1ЏeCURS2–eCURS3›eC#~юИлГШdT МhA «iM yjMC qjJ fR .lC \kU [fE /lY МhN МhLOAD :lINMAX ЬeNEW$ AlDP Нmt}5ePRINT ЧmSAVE зmIEP ПeBYE aEDIT aCA qeCE ЎeCL ¬eCH ·eRL ДeНa&НaaНa*a~ю,К–eю К›eOНa#ГѓerГЏeCНaЙНaJНaЙ0|®eНaKНaЙНaHНaГЎeНaSНaЙ!p":a" ВdНрg#~ю Вd:FaЖ2Fa!pНрg#НVd^~ю В2d#НVd^~ю В2d:FaЖ2Fa!pНрg#НVd~НJdА:FaЖ…}Fd2FaЙю0шю:ъTdґЙЇЙ:Fa·И#=ГYdН‡gюYКodюNКxd·Й:Ka·КЃdґЙ:Ka·ВЃdґЙЇЙю)КЉdґЙ++~ю(В§d#FНґdюК§d#~юъҐdґЙЇЙ*"aНПh![nН1nЙ!Vb~юИёИ##8zїdГ·dнdНШdюИл#ЦdХ^#VХЙЇЙ!‹bНNg·А#л##fJOP:fJOP2ёlKEYINВlKIN2tmKLNфlKOUT?bLABSAVKbLASTOPuiLBLіhLETTEREaLEVELmLFGgLFNDHLINEП{"aLLSAVFaLNSKP aLO:lLOADчfLOOKрfLOOKLйfLOOKSЧmLPRGШdLSTMCHlLTRтjMBRGaMBRCHqjMC|gMCHЕjMDONEэ}>aMEMTPУg#л> w#лЇЙ‹bН§gyюшbk++Н‡gюYКЭgюNА> wЙ:НЉh*"aKbН§lЙ~ю ИюИyЖO#ГтgyюИЦOђ{h+Гh~Gю Ию Ию,Ию;Ию:Ию.Ию?Ию!Ию"Ию(Ию)Ию'ИюЙЇ2Ha*aл*aF#лНЉhy·И"a:HaЃ2Ha*aНрgyЦO‹b*aН§l"6aл> w*aл!‹bНNg·В…h*a#ў|h"aГ9h!HaNЙ~ёИю КњhyЖO#ГЊhЇOЙ~ю$Ию#Ию ИyCHJaVARSAV0iVBLЉdVCHKwюVIDEOҐdVOFF§gWDTFR‹bWORDfgXENDodYCHKvgYENDBв*`dYNCHKЭgYNOUTKaYNSWTdYNUMњhZCн8Гаb¶HaГ!nГчmГ!nГчmГчmГГГ,lG|аb1a!ю"4a!чbaН§lГcГ!nГчmГ!nURS4qeCURSRvxfCVNUM9jDECA aDESAVЃdDONTНmDPRGњmDSPLYќaEBUFFaEDITіmENDOLЫiENTRY/lEOP6aEPTR1nERRORaEXITпzКkEXMSG[nEXPMSGОfFRMCHШfFRMU’iGETAgGETCHДgGETCTL‡gGETLCH„fGETNMiGETNUMЏgGETWDпhGETXTтkGBaНйcЙНнe{юIъиe>H_!DasЙ*aНgю ИНЏg+"a!‹bНіhВfFНґdюМ§dИ#^ГfН„f{·рЙ*aНgю*Р}&fК:f>*2‹bЊb*aН§gГ=fНЏg*BaНрfюМNfИ#":aЙ!‹bНњm!6nН1nЙНflГfp#yЦOВafЙ*4aл!p p#Н}fВtfЙ|єшА}»Й#Н hКґfю+Кґfю-Кґf+~ю0шю:рї}џfЦ0‡_‡‡ѓ_#~ю0шю:рЦ0ѓ_Й+ГЁf{·ьбfю ъОfЦ _ymOVCTRonOVFMSGФkOVMSGьjPADpPBUFBяPBUFEpPBUFF aPOцPORTБmPRGOUTаbPSTRTёfPUTNMRDAаx‹lRESRET$aRETSAVaRIДeROLL.lROPcRSTRTЦdRTRNxlSAV2бgSAVOPflSAVRET\cSCANBaSCANBHaSCNTґfSDIG v…hSETCNTГhSETUPjMMOVЩjMMOV2MNTRyjMOP~jMOP1 wЙ]T+~юКOjxЦGВ9j"4a6Й!RnН1nЙ!ќaНgС|^jН„f!JaFНґdюМ§dИ#sЙ!Ga6^Г~j!Ga6,*a" w#л" w#л*aНрg*aН§lл+> w#> w*aл!‹bНрg!‹bН§lЙ*a"a~ю Ию К=k#Г-k#~ю В1k"aНPk*a’}MkГ>k#F+p~ю И#ГPk*a=НЉhy·ККk#Нgю-Вk"aЇ2Ia*aГіkНтkееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееmГ(mw#Гa6+"4aЙ!VbAxю[Иw#>w#xЖGГVl!Ea~Жюъxl!‰nееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееаbґс080, 1.1 :LOAD A NEW PROGRAM? A: M: Y JN:*% сDэnT:ENTER PILOT PROGRAM :TERMINATE INPUT WITH CTL/Z LOAD: *% IEP: Пp„OM *ILLEGAL EXPRESSION *VALUE > 99 *VALUE < -99 §x‰n*USE DEPTH EXCEEDED *NUMERIC RESPONSE REQUIRED *INTERRUPTED T: T:PILOT-8080, 1.1 :LOAD A NEW PROGRAM? A: M: Y JN:*% сDэnT:ENTER PILOT PROGRAM :TERMINATE INPUT WITH CTL/Z LOAD: *% IEP: Пp„ееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееее