home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / assemblr / library / lphp / lp16.asm next >
Assembly Source File  |  1986-06-19  |  14KB  |  665 lines

  1.     Page    75,132
  2.     Title    LP - Print File With Pagination
  3.  
  4.     Comment |
  5.  
  6. LP Command
  7. ________________
  8.  
  9. Purpose:  To print an ASCII file on the standard printer
  10.       device at either 66 or 88 lines per page. A title
  11.       is printed at the top of each page which contains
  12.       the file name, creation date, and page number.
  13.  
  14. Syntax:   LP [d][path]filename[.ext]    [/6][/8]
  15.                     [/L1][/L2]
  16.                     [/10][/12][/17]
  17.  
  18. Remarks:
  19.     Written by Vernon Buerg for the IBM PC using
  20.     DOS 2.0 or later. For public domain use. Not
  21.     for sale or hire.
  22.  
  23.     Version 1.1, April 27, 1984.
  24.     Version 1.2, Sept 12, 1984.
  25.     Version 1.4, Aug 8, 1985.
  26.         - account for TABs and long lines
  27.         - remove Int 17h due to bad spoolers
  28.     Version 1.5, June 13, 1986.
  29.         - minimal changes for HP LaserJet
  30.     Version 1.6, June 19, 1986
  31.         - expand tabs and use HP LJ printer codes
  32.         - fine tune cpi and lpi
  33.         - use Int 17h for quicker printing
  34. ________________                            |
  35.  
  36. Cseg    Segment Public Para 'CODE'
  37.     Assume    CS:Cseg, DS:Cseg
  38.     Org    100h
  39.  
  40. LP    Proc    Far
  41.     Jmp    Start            ; Put usage data up front
  42.     Page
  43. ;
  44. ;    Constants and Data Areas
  45.  
  46. BEL    Equ    07
  47. BS    Equ    08
  48. TAB    Equ    09
  49. LF    Equ    10
  50. FF    Equ    12
  51. CR    Equ    13
  52. EOF    Equ    26
  53. ESC    Equ    27
  54. Stopper    Equ    '$'            ; Ends text message strings
  55.  
  56. Dater    Record    Yr:7,Mo:4,Dy:5
  57.  
  58.     Db    BS,BS,BS
  59. Version Db    CR,LF,'LP - Version 1.6l - V.Buerg',CR,LF,Stopper,BS,BS
  60.     Db    CR,LF,'Usage:'
  61.     Db    CR,LF,'    LP [d:][\path]filename[.ext]'
  62.     Db    CR,LF,'       [/6][/8]  [/L1][/L2] [/10][/12][/17]'
  63.     Db    CR,LF,EOF
  64.  
  65. AlocMsg Db    CR,LF
  66.     Db    'Not enough memory',CR,LF,BEL,Stopper
  67. ErrMsg    Db    CR,LF
  68.     Db    'Invalid command option(s)',CR,LF,BEL,Stopper
  69. Sorry    Db    CR,LF
  70.     Db    'Sorry, PC DOS 2.0 or later required',CR,LF,BEL,Stopper
  71.  
  72. EofMsg    Db    CR,LF
  73.     Db    'End of file.',CR,LF,Stopper
  74.  
  75. Buflen    Dw    0            ;I/O buffer size (variable)
  76. Stk_Top Dw    0            ;Stack ptr at entry
  77.  
  78. LPTn    Dw    0            ;Printer port
  79. Errlvl    Db    0            ;Error level returned
  80.  
  81. Heading Db    ESC,'&a0C'        ;Top line title
  82.     Db    ESC,'&dD'               ; underlined
  83.     Db    ESC,'(s3B'              ; bold (if available) title
  84. FileNm    Db    60 Dup (' ')
  85. Date    Db    'mm-dd-yy','    '
  86.     Db    'Page  '
  87. Pageno    Db    '1'
  88.     Db    LF,ESC,'(s0B'           ; medium data
  89.     Db    ESC,'&d@'               ; no more underlining
  90.     Db    CR,LF
  91.  
  92. Len_H    Equ    This Byte - Heading
  93.     Page
  94. ;
  95. ;    Printer intialization set-up commands
  96.  
  97. Lcnt    Db    0            ; Line counter
  98. Ccnt    Db    0            ; Chars in current line
  99.  
  100. Cpp    Db    80            ; Max chars per page
  101. LPP    Db    61            ; Max lines per page
  102.  
  103. Reset    Db    ESC,'E'                 ; Printer initialization codes
  104. Margin    Db    ESC,'&a0L'              ; Left margin of 1
  105. Wrap    Db    ESC,'&s0C'        ; Enable line wrapping
  106. Perf    Db    ESC,'&l0L'        ; Perforation skip mode off
  107.  
  108.     Db    ESC,'&l2E'              ; Top margin
  109.     Db    ESC,'&l'
  110. PL    Db    '62F'                   ; Page length
  111.  
  112.     Db    ESC,'&l'
  113. Lpi    Db    '6','D'                 ; Lines per inch
  114.  
  115.     Db    ESC,'&k'
  116. Cpi    Db    '0S'                    ; Chars per inch
  117.  
  118. Reset_L Equ    $-Reset         ; Length of initial string
  119.     Page
  120. ;
  121. ;    File variables and messages
  122.  
  123. MsgIn    Db    CR,LF,'Enter INPUT filename  $'
  124. Msg1    Db    CR,LF,'Unable to open input'
  125. InKey    Db    32,32            ; Keyboard buffer
  126. Input    Db    76 Dup (0),Stopper      ; Drive:path\name.ext
  127. IHandle Dw    0            ; Input file handle
  128. Ilen    Dw    0            ; Input block length
  129. Iptr    Dw    Offset Buffer        ; Offset to next char
  130.  
  131. Msg2    Db    CR,LF,'Unable to open LPT'
  132. Msg2a    Db    '1$'
  133. Output    Db    'LPT1:',0,Stopper       ;Printer name
  134. OHandle Dw    0            ;Output file handle
  135. Olen    Dw    0            ;Output block length
  136. Optr    Dw    0            ;Offset to next char
  137. OutPtr    Dw    0            ;Offset to output buffer
  138.  
  139. OutChar Db    0
  140.     Page
  141. ;
  142. ;    Program initialization and main sequence
  143.  
  144. Start:
  145.     Mov    SP,Offset CS:Lstack    ;Use local stack
  146.  
  147.     Push    DS            ;For DOS return
  148.     Sub    AX,AX
  149.     Push    AX
  150.     Mov    Stk_Top,SP
  151.  
  152.     Call    Ver            ; Check DOS version
  153.  
  154.     Call    Alloc            ; Allocate memory
  155.  
  156.     Call    GetFile         ; Get file name
  157.  
  158.     Call    Opens            ; Open input
  159.  
  160.     Call    InitLPT         ; Initialize printer
  161.  
  162.     Call    GetName         ; Format title line
  163.  
  164.     Call    Titles            ; and print it
  165.  
  166.     Call    List            ; Print the file
  167.  
  168.     Call    Flush            ; Drain the output buffer
  169.  
  170. Eod:    Mov    DX,Offset EofMsg    ; Say END-OF-FILE
  171.     Jmp    Fini
  172.  
  173. Error:    Mov    CS:Errlvl,1
  174. Fini:    Mov    AX,CS            ; Insure final seg regs
  175.     Mov    DS,AX
  176.     Mov    SP,Stk_Top        ; and stack
  177.  
  178.     Mov    AH,9            ; Print error message
  179.     Int    21h
  180.  
  181.     Mov    BX,IHandle        ; Close input
  182.     Mov    AH,3Eh
  183.     Int    21h
  184.  
  185. Exit:
  186.     Mov    AL,Errlvl        ; Set ERROR LEVEL
  187.     Mov    AH,4Ch            ; and Exit
  188.     Int    21h
  189.     Page
  190. ;
  191. ;    Copy file to printer
  192.  
  193. List    Proc    Near
  194.  
  195. List1:    Call    Read            ; Get one character
  196.     And    AL,7FH            ;  and hi-order bit (?)
  197.  
  198.     Cmp    AL,FF            ; Is it form feed?
  199.     Je    Eject
  200.  
  201.     Cmp    AL,LF            ; Pass line feed
  202.     Je    Passit
  203.  
  204.     Cmp    AL,CR            ; Pass carriage return
  205.     Je    Passit
  206.  
  207.     Cmp    AL,BS            ; Pass back space
  208.     Je    PassBS
  209.  
  210.     Cmp    AL,TAB            ; Expand tab chars
  211.     Je    PassTAB
  212.     Inc    Ccnt            ; Incr count of chars in line
  213.  
  214.     Cmp    AL,EOF            ; End of file?
  215.     Jne    Check32
  216.     Jmp    Done
  217. Check32:
  218.     Cmp    AL,32            ; Other control char?
  219.     Jns    Passit
  220.     Jmp    CtlChr
  221.  
  222. PassTAB:Mov    DL,Ccnt         ; Current column count
  223.     Sub    DH,DH
  224.     Add    Ccnt,8            ; Round up to TAB column
  225.     And    Ccnt,0F8h
  226.     Mov    CL,CCnt
  227.     Sub    CH,CH
  228.     Sub    CX,DX            ; Blanks to fill
  229.     Mov    AL,' '
  230.     Jcxz    Check_Wrap
  231. PassTabs:
  232.     Call    PutChar
  233.     Loop    PassTabs
  234.     Jmp    Check_Wrap
  235.  
  236. PassBS: Dec    Ccnt            ;Account for backspace
  237.     Jns    Passit
  238.     Mov    Ccnt,0
  239.  
  240. Passit: Call    PutChar
  241.  
  242. Check_Wrap:
  243.     Mov    AH,Cpp            ; Max chars per line
  244.     Cmp    Ccnt,AH         ;  filled up a line?
  245.     Ja    Check_Wrap2
  246.     Cmp    AL,LF            ; Is it line feed?
  247.     Jne    List1            ; no, get next char
  248.  
  249. Check_Wrap2:
  250.     Inc    Lcnt            ; yes, incr line count
  251.     Mov    Ccnt,0
  252.     Mov    AL,Lcnt
  253.     Cmp    AL,LPP            ; End of page?
  254.     Jbe    List1            ; no, get next char
  255.  
  256. Eject:    Mov    Ccnt,0            ; Reset char count in line
  257.     Cmp    Lcnt,2            ; Printed any lines yet?
  258.     Ja    Eject1
  259.     Jmp    List1            ; no, ignore form feed
  260.  
  261. Eject1:
  262.     Call    NewPage
  263.     Jmp    List1            ;Get next record
  264.  
  265. CtlChr: Cmp    AL,0            ; Null char?
  266.     Je    Blanks            ; yes, make it a space
  267.     Push    AX
  268.     Mov    AL,'^'                  ; Indicate a control char
  269.     Call    PutChar
  270.     Inc    Ccnt
  271.     Pop    AX            ; Get char again
  272. Blanks: Add    AL,20H            ; Make it printable
  273.     Jmp    Passit
  274.  
  275. Done:    Ret
  276. List    Endp
  277.     Page
  278. ;
  279. ;    Process end of page
  280.  
  281. NewPage Proc    Near
  282.     Cmp    Lcnt,2            ; Is it title line?
  283.     Je    Titles            ; yes, skip rest
  284.     Mov    AL,FF            ;        and send form feed
  285.     Call    PutChar
  286.     Mov    Lcnt,0            ; Reset line counter
  287.  
  288.     Push    DI            ; Format new page number
  289.     Mov    DI,Offset Pageno
  290.     Mov    AX,3A30h
  291. Next:    Inc    Byte Ptr [DI]        ; Incr page number
  292.     Cmp    [DI],AL         ; End in zero?
  293.     Js    Set1            ; yes, make it a one
  294.     Cmp    [DI],AH         ; Over nine?
  295.     Jne    PgSet            ; no, have good number
  296.     Mov    [DI],AL         ; yes, make last digit zero
  297.     Dec    DI            ;      and incr hi-order
  298.     Jmp    Next
  299.  
  300. Set1:    Mov    Byte Ptr [DI],'1'
  301. PgSet:    Pop    DI
  302.  
  303. ;
  304. ;    Print top line titles
  305.  
  306. Titles: Mov    SI,Offset Heading    ; Print title line
  307.     Mov    CX,Len_H
  308. Next1:    Lodsb
  309.     Cmp    AL,0            ; Replace nulls in filename
  310.     Jne    Next2            ;  with spaces
  311.     Mov    AL,' '
  312. Next2:    Call    PutChar
  313.     Loop    Next1
  314.     Mov    Lcnt,2            ; Reset line counter
  315.     Ret
  316.  
  317. ;
  318. ;    Initialize the printer
  319.  
  320. InitLPT Proc    Near            ;Initialize the printer
  321. Init1:    Mov    CX,Reset_L        ; Length of
  322.     Mov    SI,Offset Reset     ;   initial codes
  323. Init2:    Call    Next1
  324.     Ret
  325. InitLPT Endp
  326.  
  327. NewPage Endp
  328.     Page
  329. ;
  330. ;    Format title line
  331.  
  332. GetName Proc    Near            ; Format title line
  333.     Mov    SI,Offset Input     ; Copy file name
  334.     Mov    DI,Offset Filenm    ;   to heading
  335.     Mov    CX,42            ; Max for title
  336.     Cld
  337.     Repz    Movsb
  338.  
  339.     Mov    AX,5700h        ; Return file's date and time
  340.     Mov    BX,IHandle        ; Input handle
  341.     Int    21h
  342.  
  343.     Mov    DI,Offset Date        ; Date field in title
  344.  
  345.     Mov    AX,DX            ; Get month part
  346.     And    AX,Mask Mo
  347.     Mov    CL,Mo
  348.     Call    Format
  349.     Stosw
  350.     Inc    DI            ; Add delimiter
  351.  
  352.     Mov    AX,DX            ; Get day part
  353.     And    AX,Mask Dy
  354.     Mov    CL,Dy
  355.     Call    Format
  356.     Stosw
  357.     Inc    DI            ; Add delimiter
  358.  
  359.     Mov    AX,DX            ; Get year part
  360.     And    AX,Mask Yr
  361.     Mov    CL,Yr
  362.     Call    Format
  363.     Or    AL,'8'
  364.     Stosw
  365.     Ret
  366. GetName Endp
  367.  
  368. Format    Proc    Near            ; Convert binary to ASCII
  369.     Shr    AX,CL
  370.     Aam
  371.     Or    AX,'00'
  372.     Xchg    AH,AL
  373.     Ret
  374. Format    Endp
  375.     Page
  376. ;
  377. ;    Extract one char from record
  378.  
  379. Read    Proc    Near            ; Read char into AL
  380. Read1:    Cmp    Ilen,0            ; Any in buffer?
  381.     Je    Read2            ;  no, read next block
  382.     Mov    SI,Iptr         ;  yes, get offset in buf
  383.     Lodsb
  384.     Inc    Iptr            ; Offset for next one
  385.     Dec    Ilen            ; Decr buffer size left
  386.     Ret                ;   and return
  387.  
  388. Read2:    Mov    BX,IHandle        ; Read input
  389.     Mov    CX,BufLen
  390.     Mov    DX,Offset Buffer    ; Set up DS:DX
  391.     Mov    AH,3Fh
  392.     Int    21h            ; Read a block
  393.  
  394.     Mov    DX,Offset Buffer
  395.     Mov    Iptr,DX         ; Reset buffer ptr
  396.     Mov    Ilen,AX         ;   and length
  397.     Jc    Read8
  398.     Or    AX,AX            ; Anything read?
  399.     Jnz    Read1            ;  yes, pick it up
  400.     Mov    AL,EOF            ;  no, return EOF
  401.     Ret
  402.  
  403. Read8:    Mov    DX,Offset Msg3        ;Say I/O ERROR
  404.     Jmp    Error
  405.  
  406. Msg3    Db    CR,LF,'I/O error',CR,LF,BEL,Stopper
  407. Read    Endp
  408.  
  409. ;
  410. ;    Use Int 17h to print a character
  411.  
  412. PutChar Proc    Near            ;Write from AL
  413.     Push    AX
  414.     Push    DX
  415. PutCh1:
  416.     Mov    DX,LPTn        ; Printer port number
  417.     Mov    AH,0        ; Print one char
  418.     Int    17h        ;  via BIOS
  419.  
  420.     Test    AH,025h        ; Successful?
  421.     Jnz    PutCh1        ; no, wait for printer
  422.  
  423.     Pop    DX        ; Recover registers
  424.     Pop    AX
  425.     Ret
  426.  
  427. Flush:    Mov    AL,FF        ; Eject last page
  428.     Call    PutChar
  429.     Ret
  430.  
  431. PutChar Endp
  432.     Page
  433. ;
  434. ;    Get file names from parm
  435.  
  436. GetFile Proc    Near            ;Get file name(s)
  437.     Mov    SI,80h            ;Point to command line
  438.     Sub    CX,CX            ;Clear length reg
  439.     Or    CL,Byte Ptr [SI]    ;Get command tail length
  440.     Jz    GetF8            ; none, ask for them
  441.     Mov    DI,Offset Input     ;Point fname target
  442.     Inc    SI            ;Bump command ptr
  443.  
  444. GetF1:    Lodsb                ;Get next char
  445.     Cmp    AL,' '                  ;Skip leading blanks
  446.     Jne    GetF2
  447.     Loope    GetF1
  448.     Jcxz    GetF8            ; all blank
  449.  
  450. GetF2:    Cmp    AL,CR            ;End of parm?
  451.     Je    GetF7            ; yes, terminate fname
  452.     Cmp    AL,' '                  ;Delimiter?
  453.     Je    GetF4            ; yes, look for swithes
  454.     Cmp    AL,'/'                  ;Switch char?
  455.     Je    GetF5
  456.     Stosb                ;Save fname char
  457.     Lodsb
  458.     Loop    GetF2
  459.     Jmp    GetF7
  460.  
  461. GetF4:    Dec    CX
  462.     Jz    GetF8
  463. GetF4a: Lodsb
  464.     Cmp    AL,' '                  ;Skip intervening blanks
  465.     Jne    GetF4b
  466.     Loope    GetF4a
  467.     Jcxz    GetF7            ; just trailing blanks
  468. GetF4b: Cmp    AL,CR            ;End of parm?
  469.     Je    GetF7            ; yes, no switches
  470.     Jmp    Short GetF5b
  471.  
  472. GetF5:    Dec    CX
  473.     Jz    GetF7
  474. GetF5a: Lodsb
  475. GetF5b: Cmp    AL,'/'                  ;Switch char?
  476.     Jne    GetFx            ; no, invalid
  477.     Dec    SI            ; yes, back up to it
  478.     Call    GetParm         ; and set switches
  479.  
  480. GetF7:
  481. GetF8:    Cmp    Input,0         ;Any input name?
  482.     Jne    GetF9            ; no, ask for it
  483.     Call    AskIn
  484. GetF9:    Ret
  485.  
  486. GetFx:    Mov    DX,Offset ErrMsg
  487.     Jmp    Error
  488.     Page
  489. ;
  490. ;    Determine switch parameters
  491.  
  492. GetParm Proc    Near
  493.     Push    DI
  494.     Push    SI            ;Offset to parm string
  495.     Push    CX            ;Length of string
  496.  
  497.     Mov    DI,SI            ;Save string ptr
  498.     Add    DI,CX            ; ending offset
  499. GetP0:    Cmp    SI,DI            ;Any left?
  500.     Jb    GetP1
  501.     Jmp    GetP9            ; no, done
  502.  
  503. GetP1:    Lodsb
  504.     Cmp    AL,'/'                  ;Switch char?
  505.     Je    GetP2
  506.     Jmp    Short GetP0
  507.  
  508. GetP2:    Cmp    SI,DI            ;Any string left?
  509.     Jae    GetPx            ; no, invalid option
  510. GetP2a: Lodsb
  511.     Cmp    AL,'L'                  ;Printer port?
  512.     Je    GetPl
  513.     Cmp    AL,'l'
  514.     Je    GetPl
  515.     Cmp    AL,'6'                  ; for 6 lpi?
  516.     Je    GetP6
  517.     Cmp    AL,'8'                  ; for 8 lpi?
  518.     Je    GetP8
  519.     Cmp    AL,'1'                  ; for cpi?
  520.     Je    GetPc
  521.  
  522. GetPx:    Mov    DX,Offset ErrMsg    ; no, say INVALID OPTIONS
  523.     Jmp    Error
  524.  
  525. GetPl:    Cmp    SI,DI            ;Have next char?
  526.     Jae    GetPx
  527.     Lodsb
  528.     Cmp    AL,'1'                  ;Valid printer?
  529.     Jb    GetPx
  530.     Cmp    AL,'2'
  531.     Ja    GetPx
  532.     Mov    Msg2a,AL        ; Put 'n' into message
  533.     Mov    Output+3,AL        ;  and into file name
  534.     Sub    AL,'1'                  ; Form port address
  535.     Sub    AH,AH
  536.     Mov    LPTn,AX
  537.     Jmp    GetP0            ; try next field
  538.  
  539. GetP6:    Mov    LPP,61            ; Set 6 lpi
  540.     Mov    Lpi,'6'
  541.     Mov    Word Ptr PL,'36'
  542.     Jmp    GetP0
  543.  
  544. GetP8:    Mov    LPP,81            ; Set 8 lpi
  545.     Mov    Lpi,'8'
  546.     Mov    Word Ptr PL,'48'
  547.     Jmp    GetP0
  548.  
  549. GetPc:    Cmp    SI,DI            ; Any string left?
  550.     Jae    GetPx            ; no, invalid
  551.     Lodsb
  552. GetPc12:
  553.     Cmp    AL,'2'                  ; Is it /12?
  554.     Jne    GetPc17
  555.     Mov    Cpp,96            ; chars per line
  556.     Mov    Cpi,'1'                 ; printer control code
  557.     Jmp    GetPc2
  558. GetPc17:
  559.     Cmp    AL,'7'                  ; Is it /17?
  560.     Jne    GetPc10
  561.     Mov    Cpp,136
  562.     Mov    Byte Ptr Cpi,'2'        ; Compressed for cpi
  563.     Jmp    Short GetPc2
  564. GetPc10:
  565.     Cmp    AL,'0'                  ;Is it 10?
  566.     Jne    GetPx            ; none of the above
  567.     Mov    Cpp,80
  568.     Mov    Cpi,'0'                 ; Default font cpi
  569.  
  570. GetPc2:
  571.     Jmp    GetP0            ; and try next switch
  572.  
  573. GetP9:    Pop    CX
  574.     Pop    SI
  575.     Pop    DI
  576.     Ret
  577. GetParm Endp
  578.     Page
  579. ;
  580. ;    Ask for input file name
  581.  
  582. AskIn    Proc    Near
  583. Ask:    Mov    DX,Offset MsgIn     ;Prompt msg for input
  584.     Mov    AH,9            ;Print string
  585.     Int    21h
  586.  
  587.     Mov    InKey,64
  588.     Mov    DX,Offset InKey     ;Ptr to keyboard buffer
  589.     Mov    AH,10            ;Buffered keyboard input
  590.     Int    21h
  591.     Sub    BX,BX            ;Clear for insert
  592.     Add    BL,InKey+1        ;Get length read
  593.     Jz    Ask            ;If nothing read
  594.     Mov    Byte Ptr Input[BX],0    ;Set ASCIIZ stopper
  595.     Mov    Word Ptr InKey,' :'     ;Clear error message part
  596.     Ret
  597. AskIn    Endp
  598.  
  599. GetFile Endp
  600.     Page
  601. ;
  602. ;    Open files
  603.  
  604. Opens    Proc    Near
  605.     Mov    DX,Offset Input
  606.     Mov    AX,3D00h        ; Open for input
  607.     Int    21h
  608.     Jnc    Openi
  609.     Mov    DX,Offset Msg1
  610.     Jmp    Error
  611.  
  612. Openi:    Mov    IHandle,AX        ; Return input handle
  613.     Ret
  614. Opens    Endp
  615.  
  616. ;
  617. ;    Check DOS version
  618.  
  619. Ver    Proc    Near
  620.     Mov    AH,30h            ;Get DOS version
  621.     Int    21h
  622.     Cmp    AL,2            ;Rel 2 or later?
  623.     Jae    Ver1            ; if not
  624.     Mov    DX,Offset Sorry
  625.     Jmp    Error
  626.  
  627. Ver1:    Mov    DX,Offset Version
  628.     Mov    AH,9            ;Display title
  629.     Int    21h
  630.     Ret
  631.  
  632. Ver    Endp
  633.     Page
  634. ;
  635. ;    Allocate up to 64K for read buffer
  636.  
  637. Alloc    Proc    Near            ; Allocate storage
  638.     Mov    BX,Word Ptr DS:6    ; Highest segment address
  639.     Mov    CX,CS            ; Program starting seg addr
  640.     Sub    BX,CX            ; Size of program segment
  641.     Sub    BX,Pgmsize        ;  less size of code
  642.  
  643.     Sub    BX,MinSize        ; Minimum buffer request size
  644.     Cmp    BX,MinSize        ; Have enough?
  645.     Jb    Alloc9
  646.  
  647.     Mov    CL,4            ; Convert paras
  648.     Shl    BX,CL            ;  to bytes available
  649.     Mov    Buflen,BX
  650.     Ret
  651.  
  652. Alloc9: Mov    DX,Offset AlocMsg
  653.     Jmp    Error
  654. Alloc    Endp
  655.  
  656. LP    Endp
  657.  
  658. Lstack    Equ    $+128            ; End of local stack
  659. Minsize    Equ    256            ; Require 4k minimum
  660. Buffer    Equ    Lstack + 128        ; Input buffer
  661. PgmSize    Equ    ($-Cseg+1024) / 16    ; Program size in paragraphs
  662.  
  663. Cseg    Ends
  664.     End    LP
  665.