home *** CD-ROM | disk | FTP | other *** search
/ Frostbyte's 1980s DOS Shareware Collection / floppyshareware.zip / floppyshareware / APOG / ASM5.ZIP / PTF.ASM < prev    next >
Assembly Source File  |  1989-01-07  |  20KB  |  326 lines

  1. page ,132
  2. title ptf ( print text file ) as of 01/24/87 - 02:00 pm
  3. ;
  4. ;
  5. CSEG    segment para public 'CODE'
  6.         assume cs:cseg,ds:cseg,ss:cseg,es:cseg
  7.         org     100h                    ; .COM file format
  8. BEGIN:  jmp     PR_MAIN                 ; Skip around data declarations
  9.         COPYRIGHT       db      'PRint (C) 1985, Dickinson Associates Inc.'
  10.                         db      13,10,'$'
  11.         VALID_IN        db      '/abcdefghijklmnopqrstuvwxyz,;=',9
  12.         VALID_OUT       db      '\ABCDEFGHIJKLMNOPQRSTUVWXYZ',4 dup(32)
  13.         VALID_NUM       equ     $ - VALID_OUT + 1
  14.         FN_AREA         db      77 dup (0)
  15.         FN_LOC          dw      offset FN_AREA  ; Initialize at FN_AREA
  16.         PRN             equ     4               ; PC-DOS printer device handle
  17.         MAX_LINES       equ     55
  18.         MAX_CHARS       equ     80
  19.         FILE_HANDLE     dw      0
  20.         READ_LENGTH     equ     256
  21.         READ_BUFFER     db      READ_LENGTH dup (0),0
  22.         READ_PTR        dw      offset READ_BUFFER
  23.         PRINT_LENGTH    equ     256
  24.         PRINT_BUFFER    db      PRINT_LENGTH dup (0)
  25.         PRINT_PTR       dw      offset PRINT_BUFFER
  26.         EOF_FOUND       db      0
  27.         CHAR_COUNT      dw      0
  28.         LINE_COUNT      db      0
  29.         PAGE_COUNT      db      0
  30.         BIN_ASC         db      10
  31.         HEAD_1          db      13,10,13,10,'*',78 dup ('-'),'*',13,10
  32.         HEAD_2A         db      '|  File: '
  33.         HEAD_2B         db      70 dup (' '),'|',13,10
  34.         HEAD_3A         db      '| Saved: '
  35.         HEAD_3B         db      '00-00-00 at '
  36.         HEAD_3C         db      '00:00:00 '
  37.         HEAD_3D         db      '0m',39 dup (' '),'Page '
  38.         HEAD_3E         db      '00 |',13,10
  39.         HEAD_4          db      '*',78 dup ('-'),'*',13,10,13,10
  40.         HEAD_LGTH       dw      $ - HEAD_1
  41.         ERR_HEAD        db      10,13,'PRint Error - $'
  42.         NO_FILE         db      'Correct Syntax is:',13,10,10
  43.                         db      'PR [d:][path]filename[.ext]$'
  44.         FILE_NOT_FOUND  db      'File Not Found$'
  45.         OPEN_FAILURE    db      'File Open Failure$'
  46.         READ_FAILURE    db      'File Read Failure$'
  47.         ERR_TAIL        db      10,10,13,' . . . Aborting',10,13,13,'$'
  48. ;
  49. PR_MAIN         proc    near            ; PR's main program
  50.         lea     dx,COPYRIGHT                                        ; Display copyright notice
  51.         mov     ah,9h                   ; Request display string
  52.         int     21h                     ; Call PC-DOS
  53.         mov     si,80h                  ; Point SI to beginning of PSP parm area
  54.         lea     di,FN_AREA              ; Point SI to internal file name area
  55.         mov     cl,byte ptr [si]        ; Get byte count to AL
  56.         xor     ch,ch                   ; Zero CH
  57.         jcxz    NONE                    ; If CX is zero, no parameters passed
  58.         cld                             ; Set direction flag to forward
  59.         inc     si                      ; Adjust SI to beginning of parms
  60.         mov     dx,0                    ; Use DX for leading blanks flag
  61. CLEAN:  lodsb                           ; Load each character to AL
  62.         push    di                      ; Save DI on stack
  63.         mov     di,offset VALID_IN      ; Point to table of valid inputs
  64.         push    cx                      ; Save CX on stack
  65.         mov     cx,VALID_NUM            ; Set CX to number of inputs to look for
  66. repne   scasb                           ; See if any are in AL
  67.         jcxz    CLEAND                  ; If not, change nothing
  68.         mov     bx,VALID_NUM            ; Set up BX to point to valid output
  69.         sub     bx,cx                   ; This will leave BX one off
  70.         mov     al,VALID_OUT [bx - 1]   ; Load the valid output (adj BX) to AL
  71. CLEAND: pop     cx                      ; Restore CX
  72.         pop     di                      ; Restore DI
  73.         cmp     dx,1                    ; If leading blanks have been stripped,
  74.         je      CLEANC                  ; go check for colons & other things
  75.         cmp     al,' '                  ; Is AL a leading blank?
  76.         je      CLEANX                  ; Yes, ignore it & don't store it
  77. CLEANC: mov     dx,1                    ; If here, leading blanks are stripped
  78.         cmp     al,':'                  ; Is AL a colon?
  79.         je      DELIM                   ; Yes, it's a potential FN delimiter
  80.         cmp     al,'\'                  ; Is AL a backslash?
  81.         jne     DELIMX                  ; Yes, it's a potential FN delimiter
  82. DELIM:  mov     FN_LOC,di               ; Set FN_LOC at current DI + 1
  83.         inc     FN_LOC                  ; -- last one set will be correct
  84. DELIMX: stosb                           ; Store modified AL back to PSP
  85. CLEANX: loop    CLEAN                   ; Loop until CX is zero
  86.         jmp     FINDF                   ; Go see if file exists
  87. NONE:   lea     dx,NO_FILE              ; Exit with error if no parameter
  88.         jmp     EREXIT                  ; passed
  89. FINDF:  mov     ah,4eh                  ; Request find 1st file
  90.         mov     cx,0                    ; Set CX for normal files
  91.         lea     dx,FN_AREA              ; Point DX to internal file name area
  92.         int     21h                     ; Call PC-DOS
  93.         jnc     FOUNDF                  ; Ok, found the 1st file
  94.         lea     dx,FILE_NOT_FOUND       ; If 1st file not found, exit
  95.         jmp     EREXIT                  ; with error
  96. FOUNDF: mov     EOF_FOUND,0             ; Initialize end of file flag
  97.         mov     PAGE_COUNT,0            ; Initialize page counter
  98.         mov     FILE_HANDLE,0           ; Initialize file handle
  99.         mov     di,FN_LOC               ; DI points to end of path
  100.         mov     si,9eh                  ; SI points to file name in default DTA
  101.         mov     cx,13                   ; DTA file name has 13 bytes
  102. rep     movsb                           ; Move bytes to FN_LOC (in FN_AREA)
  103.         mov     ah,3dh                  ; Request open file pointed to by DX
  104.         mov     al,0                    ; Read permission requested
  105.         lea     dx,FN_AREA              ; Internal File Name Area
  106.         int     21h                     ; Call PC-DOS
  107.         mov     FILE_HANDLE,ax          ; Save File Handle contained in AX
  108.         jnc     DO_PR                   ; No carry means successfully opened
  109.         lea     dx,OPEN_FAILURE         ; Open file failed, exit
  110.         jmp     EREXIT                  ; with error message
  111. DO_PR:  call    STAMP                   ; Set file name, date & time stamps
  112.         call    PAGE_HEAD               ; Print page header
  113.         mov     di,PRINT_PTR            ; Initialize DI to PRINT_BUFFER
  114. PRLOOP: call    READ_FILE               ; Read data to buffer
  115.         jc      EREXIT                  ; Exit if error
  116.         jcxz    FINISH                  ; If CX is zero, end of file was reached
  117.         call    PRINT                   ; Format and print buffered data
  118.         cmp     EOF_FOUND,0             ; Was end of file flag set?
  119.         je      PRLOOP                  ; No, keep going
  120. FINISH: call    NEW_PAGE                ; Yes, print page feed
  121.         call    CLOSE_FILE              ; Close file
  122.         mov     ah,4fh                  ; Request find next file
  123.         mov     cx,0                    ; Set CX for normal files
  124.         int     21h                     ; Call PC-DOS
  125.         jnc     FOUNDF                  ; If no carry then found the next file
  126. EXIT:   ret                             ; If carry, exit to  PC-DOS
  127. EREXIT: push    dx                      ; Save error message pointer on stack
  128.         mov     dx,offset ERR_HEAD      ; Display error header
  129.         mov     ah,9                    ; Request display string
  130.         int     21h                     ; Call PC-DOS
  131.         pop     dx                      ; Restore error message pointer
  132.         mov     ah,9                    ; Request display string
  133.         int     21h                     ; Call PC-DOS
  134.         mov     dx,offset ERR_TAIL      ; Display error tail
  135.         mov     ah,9                    ; Request display string
  136.         int     21h                     ; Call PC-DOS
  137.         call    CLOSE_FILE              ; Close any open file
  138.         jmp     EXIT                    ; Go exit to PC-DOS (all errors fatal)
  139. PR_MAIN         endp
  140. ;
  141. READ_FILE       proc     near           ; Load CX bytes to read buffer
  142.         mov     bx,FILE_HANDLE          ; Set BX to current File Handle
  143.         mov     dx,READ_PTR             ; Point DX to read buffer
  144.         mov     cx,READ_LENGTH          ; Set CX to read buffer length
  145.         mov     ah,3fh                  ; Request read file
  146.         int     21h                     ; Call PC-DOS
  147.         jnc     RD_OK                   ; No carry, then read was Ok
  148.         lea     DX,READ_FAILURE         ; Can't imagine what error occurred
  149.         jmp     EX_RD                   ; unless coding error in file handle
  150. RD_OK:  cmp     cx,ax                   ; If CX chars were read (noted in AX)
  151.         je      NO_EOF                  ; then not at end of file (CF clears)
  152.         mov     EOF_FOUND,1             ; Otherwise, end of file reached
  153. NO_EOF: mov     cx,ax                   ; Refresh CX in case end of file reached
  154. EX_RD:  ret                             ; Return to caller
  155. READ_FILE        endp
  156. ;
  157. PRINT   proc     near                   ; Format and print output buffer
  158.         mov      si,READ_PTR            ; Set SI to read buffer
  159. FORMAT: cmp      LINE_COUNT,MAX_LINES   ; Is page full?
  160.         jb       LOAD                   ; No, go get next character
  161.         call     NEW_PAGE               ; Yes, print end of page / new page
  162.         call     PAGE_HEAD              ; Print page header
  163. LOAD:   lodsb                           ; Get character to AL
  164.         cmp      al,26                  ; Check for EOF character
  165.         je       AGAIN                  ; Ignore it
  166.         cmp      al,9                   ; Is AL a Tab?
  167.         jne      PUT_IT                 ; No, put char in print buffer
  168.         mov      al,32                  ; Load AL with blank to expand Tab
  169. TAB_X:  stosb                           ; Move AL to print buffer
  170.         inc      CHAR_COUNT             ; Increment line character counter
  171.         test     CHAR_COUNT,7           ; Is Tab expanded? (this does mod 8)
  172.         jnz      TAB_X                  ; No, keep loading blanks
  173.         jmp      WDTH                   ; Go check current line width
  174. PUT_IT: stosb                           ; Move AL to print buffer
  175.         inc      CHAR_COUNT             ; Increment line character counter
  176.         cmp      al,13                  ; Is AL a CR?
  177.         je       AGAIN                  ; Yes, go force next character
  178.         cmp      al,10                  ; Is AL a LF?
  179.         jne      FF                     ; No, check for Form Feed
  180.         call     PRINT_LINE             ; Yes, print current output buffer
  181.         jmp      AGAIN                  ; Go get next character
  182. FF:     cmp      al,12                  ; Is AL a Form Feed?
  183.         jne      WDTH                   ; No, check current width
  184.         call     NEW_PAGE               ; Yes, print end of page / new page
  185.         call     PAGE_HEAD              ; Print page header
  186.         jmp      AGAIN                  ; Re-start loop
  187. WDTH:   cmp      CHAR_COUNT,MAX_CHARS   ; Is buffer full?
  188.         jb       AGAIN                  ; No, go get next character
  189.         cmp      byte ptr [si],13       ; Yes, see if CR is next character
  190.         je       AGAIN                  ; Yes, then go get it and continue
  191.         mov      ah,10                  ; No, force CR,LF sequence
  192.         mov      al,13                  ; into print buffer
  193.         stosw                           ; Move AX to print buffer
  194.         add      CHAR_COUNT,2           ; Add two bytes to character counter
  195.         call     PRINT_LINE             ; Print the line
  196. AGAIN:  loop     FORMAT                 ; Loop bottom
  197.         ret                             ; Return to caller
  198. PRINT   endp
  199. ;
  200. PRINT_LINE       proc    near           ; Print a full or complete line
  201.         push     ax                     ; Save affected registers
  202.         push     cx                     ; currently in use
  203.         mov      dx,PRINT_PTR           ; Set DX to point to buffer
  204.         mov      cx,CHAR_COUNT          ; Print CHAR_COUNT characters
  205.         mov      bx,PRN                 ; PC-DOS printer device
  206.         mov      ah,40h                 ; Request write to device
  207.         int      21h                    ; Call PC-DOS - error unlikely here
  208.         mov      di,PRINT_PTR           ; Refresh DI
  209.         mov      CHAR_COUNT,0           ; Refresh CHAR_COUNT
  210.         inc      LINE_COUNT             ; Increment line counter
  211.         pop      cx                     ; Restore registers
  212.         pop      ax
  213.         ret                             ; Return to caller
  214. PRINT_LINE       endp
  215. ;
  216. NEW_PAGE         proc     near          ; Print end of page / new page
  217.         cmp      al,12                  ; Does AL have a form feed?
  218.         je       FF_OK                  ; Yes, so it's in the buffer
  219.         mov      al,12                  ; No, put one in the buffer
  220.         stosb                           ; Store AL in the buffer
  221.         inc      CHAR_COUNT             ; Increment character counter
  222. FF_OK:  call     PRINT_LINE             ; Print current buffer
  223.         mov      LINE_COUNT,0           ; Refresh line counter
  224.         ret                             ; Return to caller
  225. NEW_PAGE         endp
  226. ;
  227. PAGE_HEAD        proc     near          ; Format and print page header
  228.         push     di                     ; Save DI on stack
  229.         inc      PAGE_COUNT             ; Increase page counter
  230.         mov      al,PAGE_COUNT          ; Set up to convert page
  231.         lea      di,HEAD_3E             ; counter to ASCII
  232.         call     BIN_2_ASC              ; Convert to ASCII
  233.         pop      di                     ; Restore DI
  234.         cmp      HEAD_3E[0],'0'         ; Does page counter have leading 0?
  235.         jne      NOT_0                  ; No, don't do anything to it
  236.         mov      HEAD_3E[0],' '         ; Yes, make it a blank
  237. NOT_0:  push     cx                     ; Save CX on stack
  238.         mov      ah,40h                 ; Request write to device
  239.         mov      bx,PRN                 ; Request PC-DOS printer device
  240.         lea      dx,HEAD_1              ; Point to page header
  241.         mov      cx,HEAD_LGTH           ; Write all bytes in page header
  242.         int      21h                    ; Call PC-DOS
  243.         pop      cx                     ; Restore CX
  244.         ret                             ; Return to caller
  245. PAGE_HEAD        endp
  246. ;
  247. STAMP   proc     near       ; Move file name, date & time stamps to page header
  248.         lea      si,FN_AREA             ; Internal file name
  249.         lea      di,HEAD_2B             ; Location of file name in page header
  250.         mov      cx,70                  ; Load up to 70 chars in file name field
  251. LD_FN1: lodsb                           ; Get character to AL
  252.         cmp      al,0                   ; Is it the terminating zero?
  253.         je       LD_FN2                 ; Yes, go fill remainder with blanks
  254.         stosb                           ; No, store to page header field
  255.         loop     LD_FN1                 ; Loop until 0 found or CX zero
  256.         jcxz     DATE                   ; If out of room in page header, quit
  257. LD_FN2: mov      al,32                  ; Load rest of field with blanks
  258. rep     stosb
  259. DATE:   mov      si,98h                 ; Date position in default DTA
  260.         lea      di,HEAD_3B             ; Month position in page header
  261.         lodsw                           ; Packed word field
  262.         mov      bx,ax                  ; Make a copy in BX
  263.         and      ax,01e0h               ; Isolate month field
  264.         mov      cl,5                   ; Align to AL register
  265.         shr      ax,cl                  ; by shifting right 5 bits
  266.         call     BIN_2_ASC              ; Convert binary month to ASCII
  267.         mov      ax,bx                  ; Restore AX from BX
  268.         and      ax,1fh                 ; Isolate day field
  269.         inc      di                     ; Day position in page header
  270.         call     BIN_2_ASC              ; Convert binary day to ASCII
  271.         mov      ax,bx                  ; Restore AX from BX
  272.         and      ax,0fe00h              ; Isolate year field
  273.         shr      ah,1                   ; Shift right to align
  274.         add      ah,80                  ; AH is years since 1980
  275.         mov      al,ah                  ; Move to AL for division
  276.         inc      di                     ; Year position in page header
  277.         call     BIN_2_ASC              ; Convert binary year to ASCII
  278. TIME:   mov      si,96h                 ; Time position in default DTA
  279.         lea      di,HEAD_3C             ; Hours position in page header
  280.         lodsw                           ; Packed word field
  281.         mov      bx,ax                  ; Make a copy in BX
  282.         and      ax,0f800h              ; Isolate hours field
  283.         mov      cl,11                  ; Align to AL register
  284.         shr      ax,cl                  ; by shifting right 11 bits
  285.         mov      HEAD_3D[0],'a'         ; Assume it's an 'am' time
  286.         cmp      al,12                  ; Check for noon
  287.         jb       AM_OK                  ; If less, it's AM
  288.         je       PM_OK                  ; If equal, it's 12 PM
  289.         sub      al,12                  ; If more, it's after 12 PM
  290. PM_OK:  mov      HEAD_3D[0],'p'         ; Change 'am' to 'pm'
  291. AM_OK:  call     BIN_2_ASC              ; Convert binary hours to ASCII
  292.         mov      ax,bx                  ; Restore AX from BX
  293.         and      ax,7e0h                ; Isolate minutes field
  294.         mov      cl,5                   ; Align to AL register
  295.         shr      ax,cl                  ; by shifting right 5 bits
  296.         inc      di                     ; Minutes position in page header
  297.         call     BIN_2_ASC              ; Convert binary minutes to ASCII
  298.         mov      ax,bx                  ; Restore AX from BX
  299.         and      ax,1fh                 ; Isolate seconds field
  300.         inc      di                     ; Seconds position in page header
  301.         call     BIN_2_ASC              ; Convert binary seconds to ASCII
  302.         ret                             ; Return to caller
  303. STAMP   endp
  304. ;
  305. BIN_2_ASC        proc    near           ; Convert binary number to 2-digit ASCII
  306.         cbw                             ; Convert AL to word for division
  307.         div      BIN_ASC                ; Divide AL by BIN_ASC (contains a 10)
  308.         add      al,48                  ; Convert quotient (in AL) to ASCII
  309.         stosb                           ; Store to location pointed to by DI
  310.         add      ah,48                  ; Convert remainder (in AH) to ASCII
  311.         mov      al,ah                  ; Move to AL for store
  312.         stosb                           ; Store to location pointed to by DI
  313.         ret                             ; Return to caller
  314. BIN_2_ASC        endp
  315. ;
  316. CLOSE_FILE       proc    near           ; Close file handle
  317.         cmp      FILE_HANDLE,0          ; If 0, no file open
  318.         je       CLOSEX                 ; Do nothing
  319.         mov      bx,FILE_HANDLE         ; Move file handle to BX
  320.         mov      ah,3eh                 ; Request close file
  321.         int      21h                    ; Call PC-DOS
  322. CLOSEX: ret                             ; Return to caller
  323. CLOSE_FILE       endp
  324. CSEG    ends
  325.         end      BEGIN
  326.