0001 ;=============================================================== 0002 ; 0003 ; PACK input-ref output-ref 0004 ; 0005 ; Packs an ASCII file using a digraph algorithm, in which 0006 ; common letter-pairs are combined into single bytes. The 0007 ; algorithm is of little use with program or data files, but 0008 ; typically reduces the size of a document by 30 percent. 0009 ; 0010 ; input-ref :: [x:] inputname [.typ] 0011 ; 0012 ; If the drivecode x: is omitted the default drive is used. An 0013 ; input filename is required. A filetype is optional (or, to 0014 ; be precise, a filetype of 3 blanks is allowed). 0015 ; 0016 ; output-ref :: [y:] [outputname] [.typ] 0017 ; 0018 ; Each omitted part of the output fileref is supplied from the 0019 ; input-ref. Thus the default drive is the input drive, the 0020 ; default name is the input name, and the default type is the 0021 ; input type. If all are omitted, the output file replaces the 0022 ; input file. 0023 ; ***************************************************** 0024 ; * This program was originally published in * 0025 ; * A PROGRAMMER'S NOTEBOOK * 0026 ; * Utilities for CP/M-80 * 0027 ; * by David E. Cortesi * 0028 ; * Copyright (C) Reston Publishing Company Inc. 1983 * 0029 ; ***************************************************** 0030 ;=============================================================== 0031 MACLIB CPMEQU 0032 MACLIB PROG 0033 PROLOG 0034 ;=============================================================== 0035 ; Equates for compression byte values: 0036 CompressFlag equ 080h ; high bit of compressed byte 0037 CopyThis equ 0EAh ; prefix for data > 127 0038 EndLine equ 0E8h ; stands for CR, LF 0039 EndLineTab equ 0E9h ; stands for CR, LF, TAB 0040 LimitC equ 8 ; 1+maximum 2nd-byte index 0041 ;=============================================================== 0042 ; Macro used to construct the lookup table 0043 ENTER MACRO CHAR 0044 ORG TABLE+&CHAR 0045 DB CVALUE 0046 CVALUE SET CVALUE+1 0047 ENDM 0048 ;=============================================================== 0049 ; Table used for Lookup function. Filled with FFh at first, 0050 ; then character values plugged in with the ENTER macro. 0051 Table ds 128 0052 EndTable equ $ 0053 org Table 0054 $-PRINT 0055 rept 128 0056 db 255 0057 endm 0058 $+PRINT 0059 CVALUE set 0 0060 ENTER ' ' 0061 ENTER 'e' 0062 ENTER 't' 0063 ENTER 'a' 0064 ENTER 'o' 0065 ENTER 'i' 0066 ENTER 'n' 0067 ENTER 's' 0068 ENTER 'h' 0069 ENTER 'r' 0070 ENTER 'd' 0071 ENTER 'l' 0072 ENTER 'u' 0073 org EndTable 0074 ;=============================================================== 0075 ; Utility I/O variables... 0076 ; #include utilio.inc,IOVars 0077 ;=============================================================== 0078 ; the main program -- initialization 0079 Main: 0080 call SetUpInput ; open the input file 0081 lxi b,InFCB ; BC-->default fileref 0082 lxi d,OBspace ; DE-->start of buffer space 0083 ; prolog sets HL-->end of buffer space 0084 call SetUpOutput ; prepare the output stuff 0085 ;=============================================================== 0086 ; the main program -- main loop 0087 ; 0088 call Shift ; set up the B, C text window 0089 call Shift 0090 MainWhile: 0091 mov a,b ; while (B<>EOF)... 0092 cpi CpmEof 0093 jz MainEnd 0094 ; 0095 mov a,b 0096 call Lookup ; if (Lookup(B) < LimitB ) and 0097 ora a 0098 jm MainElse1 0099 mov h,a ; ...save Lookup(B)... 0100 mov a,c 0101 call Lookup 0102 cpi LimitC ; (Lookup(C) < LimitC ) then 0103 jnc MainElse1 0104 ; 0105 mov l,a ; ..save Lookup(C) 0106 mov a,h 0107 add a ; Lookup(B) shiftleft 3 0108 add a 0109 add a 0110 add l ; ..plus Lookup(C) 0111 ori CompressFlag ; ..plus CompressFlag 0112 mov c,a ; ..assigned to C 0113 call Shift ; drop superfluous B 0114 jmp MainShout 0115 ; 0116 MainElse1: ; can't compress as a digraph 0117 mov a,b 0118 ora a ; if (B>127) then 0119 jp MainElse2 0120 ; 0121 mvi a,CopyThis 0122 call PutChar ; PutChar(CopyThis) 0123 jmp MainShout 0124 ; 0125 MainElse2: 0126 cpi AsciiCR ; if (B=CR) and (C=LF) then 0127 jnz MainElse3 0128 mov a,c 0129 cpi AsciiLF 0130 jnz MainElse3 0131 ; 0132 mvi c,EndLine ; C := EndLine 0133 call Shift ; Shift superfluous B 0134 mov a,c 0135 cpi AsciiTAB ; if (C=TAB) then 0136 jnz MainShout 0137 mvi c,EndLineTab ; C := EndLineTab 0138 call Shift ; Shift superf. B 0139 jmp MainShout 0140 ; 0141 MainElse3:; Run-length encoding could go here -- see text. 0142 ; 0143 MainShout: 0144 call Shout 0145 jmp MainWhile ; ..end while 0146 ; 0147 MainEnd: 0148 call FinishOutput ; complete output file 0149 ret ; end main. 0150 ;--------------------------------------------------------------- 0151 ; Lookup searches for the byte in A in the list " etaoinshrdlu". 0152 ; If it is found, the byte's index 0...12 is returned. If not, 0153 ; an index greater than 127 is returned as a signal. If the 0154 ; byte itself is >127 it can't be in the table, so it becomes 0155 ; the signal itself. The search is done with a table lookup 0156 ; for speed, although a sequential search would work as well. 0157 ;--------------------------------------------------------------- 0158 Lookup: 0159 ora a ; if input>127, 0160 rm ; ..exit right now. 0161 push d 0162 push h 0163 mov e,a ; form table address from byte 0164 mvi d,0 0165 lxi h,Table 0166 dad d 0167 mov a,m ; return table entry. 0168 pop h 0169 pop d 0170 ret 0171 ;=============================================================== 0172 ; the included I/O subroutines -- GetChar, PutChar, DumpOutput 0173 ; #include utilio.inc,IOSubs 0174 ;=============================================================== 0175 ; the file preparation code -- SetUpInput, SetUp-, FinishOutput 0176 ; #include utilio.inc,IOSetup 0177 ;=============================================================== 0178 ; The end of the program, and the start of the buffer space. 0179 ; The technique of using all storage for buffer, used here, is 0180 ; a liability in MP/M. There, the entire output buffer should 0181 ; be defined in the program or obtained with XDOS service 129. 0182 ; 0183 OBspace equ $ 0184 END * CROSS-REFERENCE * def. val. symbol and uses * ---- 000D ASCIICR CPI-126 * ---- 000A ASCIILF CPI-129 * ---- 0009 ASCIITAB CPI-135 * 0036 0080 COMPRESSFLAG ORI-111 * 0037 00EA COPYTHIS MVI-121 * ---- 001A CPMEOF CPI-92 * 0038 00E8 ENDLINE MVI-132 * 0039 00E9 ENDLINETAB MVI-137 * 0052 01D6 ENDTABLE ORG-73 * ---- 05E7 FINISHOUTPUT CALL-148 * ---- 01D6 INFCB LXI-81 * 0040 0008 LIMITC CPI-102 * 0158 0397 LOOKUP CALL-96 -101 * 0079 0329 MAIN * 0116 0362 MAINELSE1 JM-98 JNC-103 * 0125 036F MAINELSE2 JP-119 * 0141 038D MAINELSE3 JNZ-127 -130 * 0147 0393 MAINEND JZ-93 * 0143 038D MAINSHOUT JMP-114 -123 JNZ-136 JMP-139 * 0090 033B MAINWHILE JMP-145 * 0183 0655 OBSPACE LXI-82 * ---- 03E3 PUTCHAR CALL-122 * ---- 046D SETUPINPUT CALL-80 * ---- 0513 SETUPOUTPUT CALL-84 * ---- 03AA SHIFT CALL-88 -89 -113 -133 -138 * ---- 03A6 SHOUT CALL-144 * 0051 0156 TABLE ORG-44 -53 LXI-165 * CENSUS OF OPCODE USAGE * * ADD 4 CALL 12 CPI 5 * CVALUE 2 DAD 1 DB 2 * DS 1 END 1 ENDM 2 * ENTER 14 EQU 7 JM 1 * JMP 4 JNC 1 JNZ 3 * JP 1 JZ 1 LXI 3 * MACLIB 2 MOV 12 MVI 4 * ORA 3 ORG 3 ORI 1 * POP 2 PRINT 2 PROLOG 1 * PUSH 2 REPT 1 RET 2 * RM 1