Metropoli BBS
VIEWER: plist.asm MODE: TEXT (ASCII)
 	name	plist
	page	78,132
	title	PLIST12 --- Print text file (version 1.2A)

;	Zider Brothers,	San Francisco
;
;	Based on LIST.ASM by Ray Duncan
;
;6.27	Fixed output buffer bug.
;	Added version id on help screen.
;	Added PLIST id to error messages.
;	Fixed automatic computation of remaining available space 
;	  (courtesy Chris Dunford via Vern Buerg).
;
;6.5.86	Fixed title buffer init to conform to page offset, line
;	  width parms.
;	Fixed end-of-input processing (now does not pump out extra
;	  line with pg_offset pad plus line feed)
;
;6.4.86	Add /7 option to strip hi-bit (make ok 8-bit the default now)
;	Enlarged I/O buffers to max space available (64K assumed - may 
;	  blow system if full 64KB not available for code).
;	DEL char (07Fh or 127 decimal) is now treated as low-order control
;	  character. 
;	Add /b option for blanks substituted for low-order control chars 
;	  (Default is that non-special treatment control chars are discarded 
;	  from the output listing stream to keep output devices from
;	  interpreting WordStar embedded print control chars).
;	Change default output file to zz.spl (from zz.lst).
;	Speed on AT 6/1 around 90-100K bps, and about 11-17,000 lines per minute.
;
;5.8.85	Add std	error out for error messages
;	Disable	code that toggles lpi, cpi on exit if parm was exercised
;	Change to COM file format
;	Input buffer moved to end, fill	above program
;	Change input block size	to 4096	bytes (for DOS 2.0 hard	disk)
;	Conversion speed from 14K bps to 19K bps, depending on tabs expansion
;	Make ZZ.LST the default (file) output--21K-24K bps (bits per second)
;
;5.7.85	Make compressed, 8 lpi the default (using IBM PC Graphics printer)
;	Add /N option to get uncompressed print	("normal" print)
;	Exit print without changing settings if	none set, toggle back if set
;	Disable	FF bracketing, make no FF's at begin/end the default
;	Add /F switch to enable	lead-in	FF (tail end still disabled)
;	Add /S switch to print to std output device (so	can redirect to	file)
;	Change name to PLIST to	avoid confusion	with LIST545, etc by Vern Buerg
;	Add syntax, options help when null command line	tail
;	Add page offset	of 8 spaces
;	Added clarifying comments, code section identification breaks.
;
;5.6.85	Hack to	add 8 Lines Per	Inch option (/8)
;
;-----original documentation:
;
; LIST --- a utility to	print out text files with titles and page
; numbers on  the current list device.	The high bit of	all
; characters is	 stripped [this option now must be specified on the command
; line with the /7 option], so that raw Wordstar or other word
; processing files can	be listed.  Embedded form feed codes are
; recognized, and tabs are  expanded.  Unknown control codes (such
; as the ^B and	^U codes found in Wordstar documents) are discarded.
; If using an Epson printer, compressed	mode can be turned on with
; /C switch in command so that lines up	to 128 characters long will
; fit on a normal page.	 Requires PC-DOS 2.0 or	MS-DOS 2.0.

; Used in the form:
; A>LIST path\filename.ext  ["title text"]  [/C]
; (items in square brackets are	optional)

; version 1.0	February 28, 1984
; Copyright (c)	1984 by	Ray Duncan
; May be freely	reproduced for non-commercial use.

cr	equ	0dh		;ASCII carriage	return
lf	equ	0ah		;ASCII line feed
ff	equ	0ch		;ASCII form feed
eof	equ	01ah		;End of	file marker
tab	equ	09h		;ASCII tab character
blank	equ	20h		;space character

command		equ	80h	;buffer	for command tail

prog_size	=	offset end_code		; s/b about 09f6h
end_segment	equ	0ffffh
stack_space	equ	100h
avail		=	end_segment-(offset end_code - cseg) - stack_space
;avail2		=	end_segment-prog_size-stack_space	;gives error
		public	buf_size
;buf_size	equ	1024
buf_size	equ	avail/2
		public	output_buffer
output_buffer	equ	prog_size+buf_size
chk_stack	equ	output_buffer+buf_size+1
stack_start	equ	end_segment-stack_space+1

inblksize	equ	buf_size
outblksize	equ	buf_size
;inblksize	equ	8192	;size of block reads from input	file
;outblksize	equ	8192	;size of block writes to output file
pg_offset	equ	8	;set page offset to 8 spaces
linesize equ	132-pg_offset	;maximum length	of output line
page6lpi	equ	58	;58 out of 66 lines
page8lpi	equ	80	;80 of of 88 lines
heading_lines	equ	3	;number	of lines in page heading

std_out		equ	1	;standard output
std_error	equ	2	;standard error--not redirectable
std_printer	equ	4	;standard printer
	page
cseg	segment	para public 'CODE'

;old assume:
;	assume	cs:cseg,ds:data,es:data,ss:stack
	assume	cs:cseg,ds:cseg,es:cseg,ss:cseg
	org	100H
ENTRY:	jmp	start
;
;DATA area at end of the program.
;
who_am_i	db	'PLIST12: Zider Brothers, San Francisco'
start:
list	proc	far		;entry point from PC-DOS

	push	ds		;save DS:0000 for final
	xor	ax,ax		;return	to PC-DOS
	push	ax

list13:				;make sure we're running under DOS 2.0.
	mov	ah,30h
	int	21h
	cmp	al,2
	jae	list01		;proceed, DOS 2.0 or greater
	mov	dx,offset msg3	;DOS 1.x --- print error message
	mov	cx,msg3_len
	jmp	list9


;----------------------------------------------------------
;		Process command line

list01:	call	get_title	;get listing title from
				;command line tail.
	call	get_switch	;look for /C, /N, /6, /8, etc switches,	if any
	call	get_filename	;get path and file spec. for
				;input file from command line tail.

	jnc	list15		;jump, got acceptable name.
	mov	dx,offset msg2	;missing or illegal filespec,
	mov	cx,msg2_len
	jmp	list9		;print error message and exit.

;----------------------------------------------------------
;		Open input file

list15:	call	open_input	;now try to open input file
	jnc	list2		;jump,opened input ok
	mov	dx,offset msg1	;open of input file failed,
	mov	cx,msg1_len
	jmp	list9		;print error msg and exit.

;----------------------------------------------------------
;		Open output file

list2:
	cmp	s_switch,0	;output	to std out?
	jne	list25		;jump if DOS std output	selected
	call	open_zzlst	;open default output file
	jnc	list25		;skip if ok open
	mov	dx,offset zzmsg	;opening default file error
	mov	cx,zzmsg_len
	jmp	list9		;print error msg and xit.

;----------------------------------------------------------
;		Initialization

list25:	call	init_buff	;initialize input deblocking buffer

;----------------------------------------------------------
;		Set page, printer configuration

list20:	test	compress_switch,-1 ;was	/C switch found?
	jz	list21
	call	compress_on	;yes,turn on compressed	print mode
list21:	test	ate_lpi,-1	;/8 switch found?
	jz	list22
	call	ate_on
list22:	test	six_lpi,-1	;/6 switch found?
	jz	list23
	call	six_on
list23:	test	norm_switch,-1	;was /N	switch found?
	jz	list3
	call	compress_off

;===============================================================;
;		Main program control loop			;
;								;

;----------------------------------------------------------
;		Process character input stream

list3:				
	call	get_char	;read 1	character from input.
	cmp	al,20h		;is it a low-order control code?
	jb	short list30	;yes, go check out what kind.
	cmp	al,07fh		;not low-order, pivot on DEL char (127 decimal)
	jb	list4		;ok char, write to list device.
	je	short list30	;treat it like low-order control char.

mod1	label	word
	nop			;high bit is set on char = upper 128 chars.
	nop			;..two bytes here may be modified to 
				;  'and  al,07h' by /7 option to strip hi-bit.
				;  Otherwise code falls through to jmp:
	jmp	list4		;now write to list device.

list30:	cmp	al,tab		;is it a tab command?
	je	list5		;yes,jump to special processing.
	cmp	al,cr		;carriage return?
	jne	list31		;
	mov	column,0	;carriage return, store it into output
	jmp	list45		;  string and initialize column count.
list31:	cmp	al,lf		;is it a line feed?
	je	list7		;yes,jump to special processing. (force print)
	cmp	al,ff		;is it a form feed?
	je	list6		;yes, jump to special processing.
	cmp	al,eof		;is it end of file marker?
	je	list8		;yes,jump to close files.
	test	blank_sub,-1	;substitute blank char for control char?	
	jz	list32		;no
	mov	al,blank	;yes, replace ctl char with blank
	jmp	list4		;now write to list device
list32:	jmp	list3		;none of the above--ignore it and get another

;----------------------------------------------------------
;		Special tab expansion

list5:				;process tab character
	mov	ax,column	;let DX:AX=column count
	cwd
	mov	cx,8		;divide	it by eight...
	idiv	cx
	sub	cx,dx		;remainder is in DX.
	add	column,cx	;update	column pointer.
list55:				;8 minus the remainder
	push	cx		;gives us the number of
	mov	al,20h		;spaces	to send	out to
	call	put_char	;move to the next tab position
	pop	cx		;restore space count
	loop	list55
	jmp	short list3	;get next character

;----------------------------------------------------------
;		Form feed processing

list6:				;form feed detected
	call	write_maybe	;if anything waiting in	output
				;buffer, print it first
	call	print_heading	;new page and print title
	jmp	list3		;get next character from input

;----------------------------------------------------------
;		Put character into output line buffer

list4:				
	inc	column		;bump line char count

list45:				;write this character into
	call	put_char	;forming output	string.
				;is output buffer about	to overflow?
	cmp	linput_ptr,linesize-1
	je	list7		;yes, force print of buffer.
	jmp	list3		;no, get next char. from input file.

;----------------------------------------------------------
;		Line feed  char or line full, flush line buffer

list7:				;line feed detected, interpreted
				;as print command.
	call	heading_maybe	;print heading if needed
	call	write_line	;print contents	of text	buffer
	jmp	list3		;get more from input file

;----------------------------------------------------------
;		End of file processing

list8:				;end of	file detected  (^Z, 1AH)
	call	close_input	;close input file
	call	write_maybe	;print anything	that's waiting
				;in output buffer.

;disable end of	job form feed check and form feed output:
;	cmp	ff_switch,0	;see if	FF's have been specified
;	je	list81		;skip it if /F not set
;	mov	al,ff		;send form feed	to finish listing.
;list81:	
;	call	put_char

; 	call	write_line	;why need? already called write_maybe
	call	flush_out	;flush output buffer
	call	close_output	;close output file
	jmp	list85		;skip following	code

;disable this exit code--leave printer in mode(s) selected by cmd line parms:
;				;turn off compressed print mode,
;				;if it was enabled.
;	test	compress_switch,-1
;	jz	list82
;	call	compress_off
;list82:	cmp	norm_switch,0
;	je	list83
;	call	compress_on
;list83:	cmp	ate_lpi,0
;	je	list84
;	call	six_on
;list84:	cmp	six_lpi,0
;	je	list85
;	call	ate_on

list85:	
	ret			;now return to PC-DOS.

;----------------------------------------------------------
;		Error: program termination
;
;DX	offset to error message
;CX	length of error message

error_out:
list9:				;come here to print error message
	mov	bx,std_error
	mov	ah,40H		
	int	21H
	mov	bx,std_error
	mov	cx,hlpmsg_len
	mov	dx,offset hlpmsg	;help with syntax added	here
	mov	ah,40H
	int	21H
	ret			;return to DOS

list	endp

;								;
;		End of main program control loop	   	;
;===============================================================;

page

;----------------------------------------------------------
;		Get filename

get_filename proc near		;process name of input file
				;DS:SI <- addr command line
	mov	si,offset command
				;ES:DI <- addr filespec	buffer
	mov	di,offset input_name
	cld
	lodsb			;any command line present?
	or	al,al		;return	error status if	not.
	jz	get_filename4
get_filename1:			;scan over leading blanks
	lodsb			;to file name
	cmp	al,cr		;if we hit carriage return
	je	get_filename4
	cmp	al,'/'		;or switch,
	je	get_filename4
	cmp	al,'"'          ;or quote mark, filename missing.
	je	get_filename4	;so go return error flag.
	cmp	al,20h		;is this a blank?
	jz	get_filename1	;if so keep scanning.
get_filename2:			;found first char of name,
	stosb			;move last char. to output
				;file name buffer.
	lodsb			;check next character, found
	cmp	al,cr		;carriage return yet?
	je	get_filename3	;yes,exit with success code.
	cmp	al,'"'          ;same if quote encountered.
	je	get_filename3
	cmp	al,20h		;is this a blank?
	jne	get_filename2	;if not	keep moving chars.
get_filename3:			;exit with carry =0
	clc			;for success flag
	ret
get_filename4:			;exit with carry =1
	stc			;for error flag
	ret
get_filename endp

;----------------------------------------------------------
;		Get title

get_title proc near		;process title for listing
				;DS:SI <- addr command line
	mov	si,offset command
				;ES:DI <- addr page heading buffer
	mov	di,offset heading1
	add	di,pg_offset	;mov pointer into buf by page offset amt
	cld
	lodsb			;any command line present?
	or	al,al		;no,exit
	jz	get_title3
get_title1:			;scan for leading <"> to find title.
	lodsb
	cmp	al,cr		;if we hit carriage return,
	je	get_title3	;title text is missing.
	cmp	al,'"'          ;found delimiter?
	jne	get_title1	;if so keep scanning.
get_title2:			;get next char.	of title.
	lodsb
	cmp	al,'"'          ;terminate if 2nd <"> delimiter
	je	get_title3	;or carriage return found
	cmp	al,cr
	je	get_title3
	stosb			;store this char. into page heading buffer
	jmp	get_title2	;examine next char.
get_title3:
	ret
get_title endp

;----------------------------------------------------------
;		Get switch

get_switch proc	near		;Scan the input	line for a "/"
				;delimiting a switch, then make
				;sure it is legal "/C" or "/c".
				;If legal switch found,	set
				;variable COMPRESS_SWITCH true.
				;Also check for	/8 for 8 lines per inch
				;		/6 for 6 lines per inch
				;		/N for normal (uncompressed)
				;		/S for std out
	mov	ax,std_printer	;set default output device to printer
	mov	output_handle,ax
	mov	si,offset command+1  ; DS:SI = addr of command line
get_switch1:			;look for "/" character
	lodsb
	cmp	al,cr		;if we run into	a carriage return,
	jnz	gsw1		;not cr
	jmp	get_switch2	;is cr,switch missing so take normal exit.
gsw1:	cmp	al,'/'
	jne	get_switch1	;not '/' yet, keep looking.
	lodsb			;found '/', pick up next char.
chk_8:	cmp	al,'8'		;8 lines per inch?
	jne	chk_6
	mov	es:ate_lpi,-1	;set 8 lines per inch switch
	jmp	get_switch1	;check for more	options
chk_6:	cmp	al,'6'		;6 lines per inch?
	jne	chk_7
	mov	es:six_lpi,-1	;set 6 lines per inch switch
	jmp	get_switch1	;check for more	options
chk_7:	cmp	al,'7'		;7-bits only? (strip high bit)
	jne	chk_b
	mov	es:sept_bits,-1	;set for 7-bit output only (flag not used..
				;  ..used self-modifying code instead:
	mov	ax,cs:and_w	;move op to in-line code location
	mov	cs:mod1,ax	;					)
	jmp	get_switch1	;check for more options
and_w	label	word		;and-operator
and_op:	and	al,07fh		;strip hi-bit op code bytes

chk_b:	cmp	al,'b'		;b=blank sub for low control chars
	jne	chk_c
	mov	es:blank_sub,-1	;set for blank
	jmp	get_switch1	;check for more options
chk_c:	or	al,20h		;and fold to lower case.
	cmp	al,'c'		;c=compress
	jne	chk_n		;not /C, check for /N
				;set compress switch
	mov	es:compress_switch,-1
	jmp	get_switch1	;check for more	options
chk_n:	cmp	al,'n'		;n=normal
	jne	chk_f		;not n,	check for /F
	mov	es:norm_switch,-1
	jmp	get_switch1	;check for more	options
chk_f:	cmp	al,'f'		;f=bracket print with FF's
	jne	chk_s
	mov	es:ff_switch,-1
	jmp	get_switch1	;check for more	options
chk_s:	cmp	al,'s'		;/S
	jne	get_switch2	;not f,	jump to	return
	mov	es:output_handle,std_out	;set output to std out
	mov	es:s_switch,-1
	jmp	get_switch1	;check for more	options

get_switch2:
	ret			;exit
get_switch endp

;----------------------------------------------------------
;		Open input file

open_input proc	near		;open input file
				;DS:DX=addr filename
	mov	dx,offset input_name
	mov	al,0		;AL=0 for read only
	mov	ah,3dh		;function 3dh=open
	int	21h		;handle	returned in AX,
	mov	input_handle,ax	;save it for later.
	ret			;CY is set if error
open_input endp

;----------------------------------------------------------
;		Open default output file

open_zzlst	proc	near	;open default output file
;This will open	an existing file if it exists
	mov	dx,offset zzlst	;ASCIIZ	string of default output file name
	mov	al,1		;open file for writing
	mov	ah,3dh		;open a	file
	int	21h
	jc	ozz1		;if CY, check if not found
savozz:	mov	output_handle,ax
	mov	zzlst_handle,ax	;in case we need it
;move to the end of the file for default file append
	mov	bx,ax		;handle to BX for LSEEK
	mov	cx,0		
	mov	dx,0
	mov	al,2		;to end of file plus offset of zero (CX:DX)
	mov	ah,42h		;LSEEK call (what's an LSEEK???)
	int	21h		;CY may be set here if invalid handle or function

ozzxit:	ret			;carry will be set if error

	public ozz1
ozz1:	cmp	ax,2		;if =2, then file not found and must be created
	jne	ozz9
	mov	dx,offset zzlst	;in case trashed by DOS
	mov	cx,20h		;creating normal file
	mov	ah,3ch		;create file call
	int	21h
	jnc	savozz		;ok create if no CY

ozz9:	stc			;other error (too many handles or access denied)
	ret
open_zzlst	endp

;----------------------------------------------------------
;		Initialize buffers

init_buff proc near		;initialize input buffer
	call	read_block	;read 1st block	of input file
	mov	linput_ptr,pg_offset	;initialize pointer to output string
	ret
init_buff endp

;----------------------------------------------------------
;		Read input block

read_block proc	near		;read block of data from input file.
	mov	bx,input_handle
	mov	cx,inblksize
	mov	dx,offset input_buffer
	mov	ah,3fh
	int	21h
	jnc	read_block1	;jump if no error status
	mov	ax,0		;simulate a zero length	read if	error
read_block1:
	cmp	ax,inblksize	;was full buffer read in?
	je	read_block2	;yes,jump
	mov	bx,ax		;no, store End-of-File mark
	mov	byte ptr [input_buffer+bx],eof
read_block2:
	mov	input_ptr,0	;initialize pointer to input buffer.
	ret
read_block endp

;----------------------------------------------------------
;		Set page, printer configuration

compress_on proc near		;turn on compressed printing mode
				;by sending command string.
	mov	cx,comp_command_length
	mov	bx,output_handle
	mov	dx,offset comp_command
	mov	ah,40h
	int	21h
	ret
compress_on endp

compress_off proc near			;turn off compressed printing mode
					;by sending command string.
	mov	cx,norm_command_length
	mov	bx,output_handle
	mov	dx,offset norm_command
	mov	ah,40h
	int	21h
	ret
compress_off endp

ate_on	proc	near			;turn on 8 lpi
	mov	ax,page8lpi
	mov	pagesize,ax
	mov	linecount,ax
	mov	cx,ate_lpi_cmd_len
	mov	bx,output_handle
	mov	dx,offset ate_lpi_cmd
	mov	ah,40H
	int	21H
	ret
ate_on	endp

six_on	proc	near			;turn on 6 lpi
	mov	ax,page6lpi
	mov	pagesize,ax
	mov	linecount,ax
	mov	cx,six_lpi_cmd_len
	mov	bx,output_handle
	mov	dx,offset six_lpi_cmd
	mov	ah,40H
	int	21H
	ret
six_on	endp


;----------------------------------------------------------
;		Get one character from input buffer

get_char proc	near		;get one character from	input buffer
	mov	bx,input_ptr	;is pointer at end of buffer?
	cmp	bx,inblksize
	jne	get_char1	;no,jump
				;yes, buffer is	exhausted,
	call	read_block	;new block must	be read	from disk.
	mov	bx,0		;initialize buffer pointer.
get_char1:
	mov	al,byte	ptr [input_buffer+bx]
	inc	bx		;bump input buffer pointer
	mov	input_ptr,bx
	ret
get_char endp

;----------------------------------------------------------
;		Put char into output line buffer

	public	put_char
put_char proc	near		;put one character into	output buffer
	mov	bx,linput_ptr
	mov	[line_buffer+bx],al
	inc	linput_ptr	;bump pointer to output	string
	ret
put_char endp

;----------------------------------------------------------
;		Heading maybe--if end of the page

	public	heading_maybe
heading_maybe proc near		;print heading if the line
				;count justifies it
	mov	ax,pagesize
	cmp	linecount,ax
	jl	heading_maybe2	;jump,page not full yet
	call	print_heading	;form feed (maybe) and print title
heading_maybe2:
	ret
heading_maybe endp

;----------------------------------------------------------
;		Print heading

	public print_heading
print_heading proc near		;print form feed, title, and page no.
	inc	pagecount	;bump page number,
	mov	ax,pagecount	;load it,
	aam			;and turn it into ASCII,
	add	ax,'00'
	mov	heading2,ah	;then store into heading string.
	mov	heading2+1,al
				;now print the heading string.
	cmp	pagecount,1	;check if first	page heading
	je	chk_ff		;see if	FF switch was specified
	public	ph2
ph2:	mov	dx,offset heading_buffer	;header including lead FF
	mov	cx,heading_length
	public	ph3
ph3:	
;put these lines  into output buffer now instead:
;	mov	bx,output_handle
;	mov	ah,40h
;	int	21h

	call	put_line

				;initialize line count
	mov	linecount,heading_lines
	mov	column,0	;and column counter
	ret

	public chk_ff
chk_ff:	cmp	ff_switch,-1	;see if	set
	je	ph2		;if set, jump back
	mov	dx,offset heading_buffer+1	;not set, skip lead FF on page 1
	mov	cx,heading_length-1
	jmp	ph3

print_heading endp


;----------------------------------------------------------
;		Write maybe--if chars in the output line buffer

write_maybe proc near		;transmit line to list device, if
				;output	buffer contains	anything.
	mov	ax,linput_ptr	;pointer is more than pg_offset if 
	cmp	ax,pg_offset	;characters are waiting in buffer.
;	or	ax,ax		;
	jz	write_maybe1	;nothing, jump to exit
	call	write_line	;something there, send it to printer
write_maybe1:
	ret
write_maybe endp

;----------------------------------------------------------
;		Write line buffer -- put line in output

write_line proc	near		;transmit contents of output
				;buffer	to the standard	list device.
	mov	al,lf		;append	line feed to string.
;	call	put_char	;insert code directly instead of call
	mov	bx,linput_ptr	
	mov	[line_buffer+bx],al
	inc	linput_ptr	;bump pointer into output line buffer
	mov	cx,linput_ptr	;CX contains length of string
				;DX:DX=buffer address
	mov	dx,offset line_buffer

	call	put_line	;put line into output buffer
;	mov	bx,output_handle;BX=handle for standard	list device is default
;	mov	ah,40h		;function 40h=write to device.
;	int	21h		;request service from DOS.


	inc	linecount	;count lines printed this page.
	mov	linput_ptr,pg_offset	;reset pointer to list device buffer
	ret
write_line endp

;----------------------------------------------------------
;		Put line into output buffer
;
;DX	ptr to line buffer
;CX	cnt of chars in line to be put

	public	put_line
put_line	proc	near
	
	cmp	cx,0		;anything to send?
	je	xit_putlin
put1:	mov	ax,output_ptr	;get current ptr into output block
	mov	bx,ax		;set index for destination
	add	ax,cx		;add the line size to be added
	cmp	ax,outblksize	;see if we can take it
	jbe	putl2		;if not, flush the block first
	call	flush_out
	jc	xit_putlin	;exit if carry (error writing block)
	jmp	put1		;recycle
	
putl2:	mov	output_ptr,ax	;save new ptr (a bit out of order, but available)
	mov	si,dx		;source into si
	mov	di,offset output_buffer
	add	di,bx		;dest into di
	cld			;increment pointers (clear direction flag: fwd)
	rep	movsb		;do your thing
	clc			;clear carry to indicate ok return

xit_putlin:	
	ret

	public	flush_out
flush_out	proc	near
	push	cx
	push	dx
	mov	cx,output_ptr		;bytes to write
	mov	dx,offset output_buffer	;source of bytes
	mov	bx,output_handle	;file to write them to
	mov	ah,40h			;DOS Write to File call
	int	21H			;the old 21H maneuver
	cmp	ax,cx			;written should equal requested
	jne	error_putlin
	mov	output_ptr,0		;zero the buffer counter
	clc
flush_xit:
	pop	dx			;restore registers
	pop	cx
	ret

	public	error_putlin
error_putlin	equ	$		;here if file write error
	mov	dx,offset msg4
	mov	cx,msg4_len
	mov	bx,std_error
	mov	ah,40h
	int	21h
	stc
	jmp	flush_xit

flush_out	endp

put_line	endp

;----------------------------------------------------------
;		Close input file

close_input proc near		;close input file
	mov	bx,input_handle	;BX=handle
	mov	ah,3eh
	int	21h
	ret
close_input endp

;----------------------------------------------------------
;		Close output file

close_output	proc	near	;close output file
	mov	bx,output_handle
	mov	ah,3eh
	int	21h
	ret
close_output	endp

;Move this to the end:
;cseg	ends

page
;===============================================================;
;		Data area					;

;disable data segment setup:
;data	segment	para public 'DATA'

		public	input_name
input_name	db	64 dup (0)	;buffer	for input filespec

		public	input_handle
input_handle	dw	0		;token from PCDOS for input file.
		public	output_handle
output_handle	dw	std_printer	;for printer or	std out
zzlst		db	'ZZ.SPL',0	;ASCIIZ	string for default output
zzlst_handle	dw	1		;std file output name, later reset

		public	input_ptr
input_ptr	dw	0		;pointer into input blocking buffer
		public	linput_ptr
linput_ptr	dw	pg_offset	;pointer into line blocking buffer
		public	output_ptr
output_ptr	dw	0		;ptr into output blocking buffer

column		dw	0		;column	count for tab processing
		public	linecount
linecount	dw	page8lpi	;line counter, current page.
					;(set to "pagesize" initially to
					;force first heading on	listing)
pagesize	dw	page8lpi	;initially at 8	lpi size
		public	pagecount
pagecount	dw	0		;current page number

compress_switch	dw	0		;set to	-1 if /C switch
					;found in command line tail.

comp_command	db	0fh		;command string	for compressed mode
comp_command_length equ	$-comp_command

norm_switch	dw	0		;set to	-1 if /N switch
norm_command	db	12h		;command string	for normal print
					;(actually: turn off compressed)
norm_command_length equ	$-norm_command

ate_lpi		dw	0		;set to	-1 if /8 switch
ate_lpi_cmd	db	1BH,'0'		;ESC 0
ate_lpi_cmd_len	equ	$-ate_lpi_cmd

sept_bits	dw	0		;set to -1 if /7 switch		

blank_sub	dw	0		;set to -1 if /b switch

six_lpi		dw	0		;set to	-1 if /6 switch
six_lpi_cmd	db	1BH,'2'		;ESC 2
six_lpi_cmd_len	equ	$-six_lpi_cmd

ff_switch	dw	0		;set to	-1 if /F switch	(lead FF)
s_switch	dw	0		;set to	-1 if /S switch	(std out)

msg1		db	cr,lf
		db	'PLIST: cannot find input file.'
		db	cr,lf,'$'
msg1_len	equ	$-msg1-1	;net of	trailing '$'

msg2		db	cr,lf
		db	'PLIST: missing file name.'
		db	cr,lf,'$'
msg2_len	equ	$-msg2-1

msg3		db	cr,lf
		db	'PLIST: requires PC-DOS version 2.0 or greater.'
		db	cr,lf,'$'
msg3_len	equ	$-msg3-1

msg4		db	cr,lf
		db	'PLIST: error writing output block.'
		db	cr,lf,'$'
msg4_len	equ	$-msg4-1

zzmsg		db	cr,lf
		db	'PLIST: error opening default file ZZ.SPL.'
		db	cr,lf,'$'
zzmsg_len	equ	$-zzmsg-1


hlpmsg		db	cr,lf
		db	'Syntax:  [d\p\]filename.ext ["title text"] [/8/6/b/7/n/c/f/s]',cr,lf
		db	cr,lf
		db	'       /8      print 8 lpi (default)',cr,lf
		db	'       /6      print 6 lpi (66 lines per page)',cr,lf
		db	'       /b      blank substitution for low ctrl chars (default: discard)',cr,lf
		db	'       /7      7-bits print (strip high bit)',cr,lf
		db	'       /c      compressed print (default)',cr,lf
		db	'       /n      non-compressed print (10 cpi)',cr,lf
		db	'       /f      leading Form Feeds added (no trailing in any case)',cr,lf
		db	'       /s      output to std out (screen), else file zz.spl default',cr,lf
		db	cr,lf
		db	'Notes:  no wildcards (*.*)  - use FOR expansion ',cr,lf
		db	'        output dumped into zz.spl on current path - 15,000 lpm on AT',cr,lf
		db	'        Version 1.2A 6.27.86',cr,lf
		db	cr,lf
		db	'Usage:  ',cr,lf,cr,lf
		db	'  C>for %1 in (*.sno) do plist %1 "6.4.86 Snobol4+ source        %1       "',cr,lf
		db	'  C>plist d:t.dta /s >tt',cr,lf
		db	'$'
		

hlpmsg_len	equ	$-hlpmsg-1	;not including the '$'


		public	line_buffer
line_buffer	db	pg_offset dup(' ')	;page offset blank pad
		db	linesize-pg_offset dup (?);buffer used to build	output
					;lines for list	device

		public		heading_buffer
heading_buffer	db	ff		;form feed control code
heading1	db	linesize-pg_offset-7 dup (' ')	;filled	in with	title from user
		db	'Page '				;7 chars in Page ##
heading2	db	'00',cr
		db	heading_lines dup (lf)
heading_length	equ	$-heading_buffer

;input_buffer	db	inblksize	dup ('x');deblocking buffer for	input file
		public	input_buffer
		even
end_code	equ	$		;end of code label
input_buffer	equ	$		;filled	above program, no cseg
					;space required	in .COM	file
;output_buffer	equ	$+inblksize	;output buffer space
;data segment disabled:
;data	ends

;disable code for stack	segment:
;stack	segment	para stack 'STACK'
;	db	64 dup (?)
;stack	ends

cseg	ends

	end	entry

[ RETURN TO DIRECTORY ]