home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PROGRAMS / UTILS / DOS_HELP / ADVMSDOS.ZIP / LIST.ASM < prev    next >
Encoding:
Assembly Source File  |  1987-08-23  |  18.5 KB  |  464 lines

  1.         name    list
  2.         page    55,132
  3.         title   'LIST --- Print text file'
  4.  
  5. ; Revisions:
  6. ; 8/23/87 - Added Prism 16cpi control code.
  7. ;         - Revised non-arg msg to show pgm usage.
  8. ;           OPR.
  9.  
  10. ; LIST --- a utility to print out text files with titles and page
  11. ; numbers on  the current list device.  The high bit of all
  12. ; characters is  stripped, so that raw Wordstar or other word
  13. ; processing files can  be listed. Embedded form feed codes are
  14. ; recognized, and tabs are  expanded.  Unknown control codes (such
  15. ; as the ^B and ^U codes found in Wordstar documents) are discarded.
  16. ; If using an Epson printer, compressed mode can be turned on with
  17. ; /C switch in command so that lines up to 128 characters long will
  18. ; fit on a normal page.  Requires PC-DOS 2.0 or MS-DOS 2.0.
  19. ;
  20. ; version 1.0   February 28, 1984
  21. ; Copyright (c) 1984 by Ray Duncan
  22. ;
  23. ; Used in the form:
  24. ;
  25. ;       A>LIST path\filename.ext  ["title text"]  [/C]
  26. ;
  27. ; (items in square brackets are optional)
  28. ;
  29. ; To assemble, link, and convert this program into
  30. ; an EXE file, follow these steps:
  31. ;
  32. ;       C>MASM LIST;
  33. ;       C>LINK LIST;
  34. ;
  35. PRISM   equ     1               ;Prism printer control code request if non-zero
  36. cr      equ     0dh             ;ASCII carriage return
  37. lf      equ     0ah             ;ASCII line feed
  38. ff      equ     0ch             ;ASCII form feed
  39. eof     equ     01ah            ;End of file marker
  40. tab     equ     09h             ;ASCII tab character
  41.  
  42. command equ     80h             ;buffer for command tail
  43.  
  44. blksize equ     1024            ;size of block reads from input file
  45. linesize equ    132             ;maximum length of output line
  46. pagesize equ    58              ;number of lines per page
  47. heading_lines equ 3             ;number of lines in page heading
  48.  
  49. output_handle equ 4             ;handle of standard list device
  50.  
  51. cseg    segment para public 'CODE'
  52.  
  53.         assume  cs:cseg,ds:data,es:data,ss:stack
  54.  
  55.  
  56. list    proc    far             ;entry point from PC-DOS
  57.  
  58.         push    ds              ;save DS:0000 for final
  59.         xor     ax,ax           ;return to PC-DOS
  60.         push    ax
  61.         mov     ax,data         ;make our data segment
  62.         mov     es,ax           ;addressable via ES register.
  63.         call    get_title       ;get listing title from
  64.                                 ;command line tail.
  65.         call    get_switch      ;look for /C switch if any
  66.         call    get_filename    ;get path and file spec. for
  67.                                 ;input file from command line tail.
  68.         mov     ax,es           ;set DS=ES for remainder
  69.         mov     ds,ax           ;of program.
  70.         jnc     list13          ;jump, got acceptable name.
  71.         mov     dx,offset msg2  ;missing or illegal filespec,
  72.         jmp     list9           ;print error message and exit.
  73.  
  74. list13:                         ;make sure we're running under DOS 2.0.
  75.         mov     ah,30h
  76.         int     21h
  77.         cmp     al,2
  78.         jae     list15          ;proceed, DOS 2.0 or greater
  79.         mov     dx,offset msg3  ;DOS 1.x --- print error message
  80.         jmp     list9
  81.  
  82. list15: call    open_input      ;now try to open input file
  83.         jnc     list2           ;jump,opened input ok
  84.         mov     dx,offset msg1  ;open of input file failed,
  85.         jmp     list9           ;print error msg and exit.
  86.  
  87. list2:
  88.         test    compress_switch,-1 ;was /C switch found?
  89.         jz      list25          ;no,jump
  90.         call    compress_on     ;yes,turn on compressed print mode
  91.  
  92. list25: call    init_buff       ;initialize input deblocking buffer
  93.  
  94.                                 ;file successfully opened,
  95. list3:                          ;now print it!
  96.         call    get_char        ;read 1 character from input.
  97.         and     al,07fh         ;strip off the high bit
  98.         cmp     al,20h          ;is it a control code?
  99.         jae     list4           ;no,write it to list device.
  100.                                 ;yes it is control code,
  101.         cmp     al,eof          ;is it end of file marker?
  102.         je      list8           ;yes,jump to close files.
  103.         cmp     al,tab          ;is it a tab command?
  104.         je      list5           ;yes,jump to special processing.
  105.         cmp     al,ff           ;is it a form feed?
  106.         je      list6           ;yes, jump to special processing.
  107.         cmp     al,lf           ;is it a line feed?
  108.         je      list7           ;yes,jump to special processing.
  109.         cmp     al,cr           ;if illegal control code,
  110.         jne     list3           ;discard it and get next char.
  111.         mov     column,0        ;if carriage return, store it into output
  112.         jmp     list45          ;string and initialize column count.
  113.  
  114. list4:                          ;count chars. sent on this line.
  115.         inc     column
  116.  
  117. list45:                         ;write this character into
  118.         call    put_char        ;forming output string.
  119.                                 ;is output buffer about to overflow?
  120.         cmp     output_ptr,linesize-1
  121.         je      list7           ;yes, force print of buffer.
  122.         jmp     list3           ;no, get next char. from input file.
  123.  
  124. list5:                          ;process tab character
  125.         mov     ax,column       ;let DX:AX=column count
  126.         cwd
  127.         mov     cx,8            ;divide it by eight...
  128.         idiv    cx
  129.         sub     cx,dx           ;remainder is in DX.
  130.         add     column,cx       ;update column pointer.
  131. list55:                         ;8 minus the remainder
  132.         push    cx              ;gives us the number of
  133.         mov     al,20h          ;spaces to send out to
  134.         call    put_char        ;move to the next tab position
  135.         pop     cx              ;restore space count
  136.         loop    list55
  137.         jmp     short list3     ;get next character
  138.  
  139. list6:                          ;form feed detected
  140.         call    write_maybe     ;if anything waiting in output
  141.                                 ;buffer, print it first
  142.         call    print_heading   ;new page and print title
  143.         jmp     list3           ;get next character from input
  144.  
  145. list7:                          ;line feed detected, interpreted
  146.                                 ;as print command.
  147.         call    heading_maybe   ;print heading if needed
  148.         call    write_line      ;print contents of text buffer
  149.         jmp     list3           ;get more from input file
  150.  
  151. list8:                          ;end of file detected,
  152.         call    write_maybe     ;print anything that's waiting
  153.                                 ;in output buffer.
  154.         mov     al,ff           ;send form feed to finish listing.
  155.         call    put_char
  156.         call    write_line
  157.         call    close_input     ;close input file.
  158.                                 ;turn off compressed print mode,
  159.                                 ;if it was enabled.
  160.         test    compress_switch,-1
  161.         jz      list85
  162.         call    compress_off
  163. list85: ret                     ;now return to PC-DOS.
  164.  
  165. list9:                          ;come here to print error message
  166.         mov     ah,9            ;and return control to PC-DOS
  167.         int     21h
  168.         ret
  169.  
  170. list    endp
  171.  
  172.  
  173. get_filename proc near          ;process name of input file
  174.                                 ;DS:SI <- addr command line
  175.         mov     si,offset command
  176.                                 ;ES:DI <- addr filespec buffer
  177.         mov     di,offset input_name
  178.         cld
  179.         lodsb                   ;any command line present?
  180.         or      al,al           ;return error status if not.
  181.         jz      get_filename4
  182. get_filename1:                  ;scan over leading blanks
  183.         lodsb                   ;to file name
  184.         cmp     al,cr           ;if we hit carriage return
  185.         je      get_filename4
  186.         cmp     al,'/'          ;or switch,
  187.         je      get_filename4
  188.         cmp     al,'"'          ;or quote mark, filename missing.
  189.         je      get_filename4   ;so go return error flag.
  190.         cmp     al,20h          ;is this a blank?
  191.         jz      get_filename1   ;if so keep scanning.
  192. get_filename2:                  ;found first char of name,
  193.         stosb                   ;move last char. to output
  194.                                 ;file name buffer.
  195.         lodsb                   ;check next character, found
  196.         cmp     al,cr           ;carriage return yet?
  197.         je      get_filename3   ;yes,exit with success code.
  198.         cmp     al,'"'          ;same if quote encountered.
  199.         je      get_filename3
  200.         cmp     al,20h          ;is this a blank?
  201.         jne     get_filename2   ;if not keep moving chars.
  202. get_filename3:                  ;exit with carry =0
  203.         clc                     ;for success flag
  204.         ret
  205. get_filename4:                  ;exit with carry =1
  206.         stc                     ;for error flag
  207.         ret
  208. get_filename endp
  209.  
  210.  
  211. get_title proc near             ;process title for listing
  212.                                 ;DS:SI <- addr command line
  213.         mov     si,offset command
  214.                                 ;ES:DI <- addr page heading buffer
  215.         mov     di,offset heading1
  216.         cld
  217.         lodsb                   ;any command line present?
  218.         or      al,al           ;no,exit
  219.         jz      get_title3
  220. get_title1:                     ;scan for leading <"> to find title.
  221.         lodsb
  222.         cmp     al,cr           ;if we hit carriage return,
  223.         je      get_title3      ;title text is missing.
  224.         cmp     al,'"'          ;found delimiter?
  225.         jne     get_title1      ;if so keep scanning.
  226. get_title2:                     ;get next char. of title.
  227.         lodsb
  228.         cmp     al,'"'          ;terminate if 2nd <"> delimiter
  229.         je      get_title3      ;or carriage return found
  230.         cmp     al,cr
  231.         je      get_title3
  232.         stosb                   ;store this char. into page heading buffer
  233.         jmp     get_title2      ;examine next char.
  234. get_title3:
  235.         ret
  236. get_title endp
  237.  
  238. get_switch proc near            ;Scan the input line for a "/"
  239.                                 ;delimiting a switch, then make
  240.                                 ;sure it is legal "/C" or "/c".
  241.                                 ;If legal switch found, set
  242.                                 ;variable COMPRESS_SWITCH true.
  243.         mov     si,offset command+1  ; DS:SI = addr of command line
  244. get_switch1:                    ;look for "/" character
  245.         lodsb
  246.         cmp     al,cr           ;if we run into a carriage return,
  247.         jz      get_switch2     ;switch missing so take normal exit.
  248.         cmp     al,'/'
  249.         jne     get_switch1     ;not '/' yet, keep looking.
  250.         lodsb                   ;found '/', pick up next char.
  251.         or      al,20h          ;and fold to lower case.
  252.         cmp     al,'c'          ;c=compress
  253.         jne     get_switch2     ;not c, jump
  254.                                 ;set compress switch
  255.         mov     es:compress_switch,-1
  256. get_switch2:
  257.         ret                     ;exit
  258. get_switch endp
  259.  
  260. open_input proc near            ;open input file
  261.                                 ;DS:DX=addr filename
  262.         mov     dx,offset input_name
  263.         mov     al,0            ;AL=0 for read only
  264.         mov     ah,3dh          ;function 3dh=open
  265.         int     21h             ;handle returned in AX,
  266.         mov     input_handle,ax ;save it for later.
  267.         ret                     ;CY is set if error
  268. open_input endp
  269.  
  270. close_input proc near           ;close input file
  271.         mov     bx,input_handle ;BX=handle
  272.         mov     ah,3eh
  273.         int     21h
  274.         ret
  275. close_input endp
  276.  
  277. get_char proc   near            ;get one character from input buffer
  278.         mov     bx,input_ptr    ;is pointer at end of buffer?
  279.         cmp     bx,blksize
  280.         jne     get_char1       ;no,jump
  281.                                 ;yes, buffer is exhausted,
  282.         call    read_block      ;new block must be read from disk.
  283.         mov     bx,0            ;initialize buffer pointer.
  284. get_char1:
  285.         mov     al,[input_buffer+bx]
  286.         inc     bx              ;bump input buffer pointer
  287.         mov     input_ptr,bx
  288.         ret
  289. get_char endp
  290.  
  291. put_char proc   near            ;put one character into output buffer
  292.         mov     bx,output_ptr
  293.         mov     [output_buffer+bx],al
  294.         inc     output_ptr      ;bump pointer to output string
  295.         ret
  296. put_char endp
  297.  
  298. read_block proc near            ;read block of data from input file.
  299.         mov     bx,input_handle
  300.         mov     cx,blksize
  301.         mov     dx,offset input_buffer
  302.         mov     ah,3fh
  303.         int     21h
  304.         jnc     read_block1     ;jump if no error status
  305.         mov     ax,0            ;simulate a zero length read if error
  306. read_block1:
  307.         cmp     ax,blksize      ;was full buffer read in?
  308.         je      read_block2     ;yes,jump
  309.         mov     bx,ax           ;no, store End-of-File mark
  310.         mov     byte ptr [input_buffer+bx],eof
  311. read_block2:
  312.         mov     input_ptr,0     ;initialize pointer to input buffer.
  313.         ret
  314. read_block endp
  315.  
  316. write_maybe proc near           ;transmit line to list device, if
  317.                                 ;output buffer contains anything.
  318.         mov     ax,output_ptr   ;pointer is non-zero if characters
  319.         or      ax,ax           ;are waiting in buffer.
  320.         jz      write_maybe1    ;nothing, jump to exit
  321.         call    write_line      ;something there, send it to printer
  322. write_maybe1:
  323.         ret
  324. write_maybe endp
  325.  
  326. write_line proc near            ;transmit contents of output
  327.                                 ;buffer to the standard list device.
  328.         mov     al,lf           ;append line feed to string.
  329.         call    put_char
  330.         mov     cx,output_ptr   ;CX contains length of string
  331.                                 ;DX:DX=buffer address
  332.         mov     dx,offset output_buffer
  333.         mov     bx,output_handle;BX=handle for standard list device.
  334.         mov     ah,40h          ;function 40h=write to device.
  335.         int     21h             ;request service from DOS.
  336.         inc     linecount       ;count lines printed this page.
  337.         mov     output_ptr,0    ;reset pointer to list device buffer
  338.         ret
  339. write_line endp
  340.  
  341. heading_maybe proc near         ;print heading if the line
  342.                                 ;count justifies it
  343.         cmp     linecount,pagesize
  344.         jl      heading_maybe2  ;jump,page not full yet
  345.         call    print_heading   ;form feed and print title
  346. heading_maybe2:
  347.         ret
  348. heading_maybe endp
  349.  
  350. print_heading proc near         ;print form feed, title, and page no.
  351.         inc     pagecount       ;bump page number,
  352.         mov     ax,pagecount    ;load it,
  353.         aam                     ;and turn it into ASCII,
  354.         add     ax,'00'
  355.         mov     heading2,ah     ;then store into heading string.
  356.         mov     heading2+1,al
  357.                                 ;now print the heading string.
  358.         mov     dx,offset heading_buffer
  359.         mov     cx,heading_length
  360.         mov     bx,output_handle
  361.         mov     ah,40h
  362.         int     21h
  363.                                 ;initialize line count
  364.         mov     linecount,heading_lines
  365.         mov     column,0        ;and column counter
  366.         ret
  367. print_heading endp
  368.  
  369. init_buff proc near             ;initialize i/o buffers
  370.         call    read_block      ;read 1st block of input file
  371.         mov     output_ptr,0    ;initialize pointer to output string
  372.         ret
  373. init_buff endp
  374.  
  375. compress_on proc near           ;turn on compressed printing mode
  376.                                 ;by sending command string.
  377.         mov     cx,comp_command_length
  378.         mov     bx,output_handle
  379.         mov     dx,offset comp_command
  380.         mov     ah,40h
  381.         int     21h
  382.         ret
  383. compress_on endp
  384.  
  385. compress_off proc near          ;turn off compressed printing mode
  386.                                 ;by sending command string.
  387.         mov     cx,norm_command_length
  388.         mov     bx,output_handle
  389.         mov     dx,offset norm_command
  390.         mov     ah,40h
  391.         int     21h
  392.         ret
  393. compress_off endp
  394.  
  395. cseg    ends
  396.  
  397.  
  398. data    segment para public 'DATA'
  399.  
  400. input_name      db      64 dup (0)      ;buffer for input filespec
  401.  
  402. input_handle    dw      0               ;token from PCDOS for input file.
  403.  
  404. input_ptr       dw      0               ;pointer to input blocking buffer
  405. output_ptr      dw      0               ;pointer to output blocking buffer
  406.  
  407. column          dw      0               ;column count for tab processing
  408. linecount       dw      pagesize        ;line counter, current page.
  409.                                         ;(set to "pagesize" initially to
  410.                                         ;force first heading on listing)
  411. pagecount       dw      0               ;current page number
  412.  
  413. compress_switch dw      0               ;set to -1 if /C switch
  414.                                         ;found in command line tail.
  415.  
  416. ; Alternate Prism Compressed Mode command added - OPR 8/23/87
  417. IF PRISM
  418. comp_command    db      1fh             ;Prism command string for 16 cpi mode
  419. ELSE
  420. comp_command    db      0fh             ;Epson command string for 16 cpi mode
  421. ENDIF
  422. comp_command_length equ $-comp_command
  423.  
  424. norm_command    db      12h             ;command string for normal print
  425. norm_command_length equ $-norm_command
  426.  
  427. msg1            db      cr,lf
  428.                 db      'Cannot find input file.'
  429.                 db      cr,lf,'$'
  430.  
  431. msg2            db      cr,lf
  432.                 db      'Usage: LIST  [path\]filename ["Title"] [/C]'
  433.                 db      cr,lf
  434.                 db      '       Items in brackets are optional.'
  435.                 db      cr,lf
  436.                 db      '       /C flag shifts printer to compact mode.'
  437.                 db      cr,lf,'$'
  438.  
  439. msg3            db      cr,lf
  440.                 db      'Requires PC-DOS version 2 or greater.'
  441.                 db      cr,lf,'$'
  442.  
  443. input_buffer    db      blksize dup (?) ;deblocking buffer for input file
  444.  
  445. output_buffer   db      linesize dup (?);buffer used to build output
  446.                                         ;lines for list device
  447.  
  448. heading_buffer  db      ff              ;form feed control code
  449. heading1        db      60 dup (' ')    ;filled in with title from user
  450.                 db      'Page '
  451. heading2        db      '00',cr
  452.                 db      heading_lines dup (lf)
  453. heading_length  equ     $-heading_buffer
  454.  
  455.  
  456. data    ends
  457.  
  458.  
  459. stack   segment para stack 'STACK'
  460.         db      64 dup (?)
  461. stack   ends
  462.  
  463.         end     list
  464.