home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / assemblr / library / edit / fremacsr / mintprim.asm < prev    next >
Assembly Source File  |  1987-02-15  |  28KB  |  1,254 lines

  1. ;History:1016,24
  2.     page    ,132
  3.  
  4.     .xlist
  5.     include    mintdefs.asm
  6.  
  7. code    segment    byte public
  8. code    ends
  9.  
  10. data    segment byte public
  11.  
  12.     extrn    next_ids: word
  13.     extrn    formb:    word
  14.     extrn    forme:    word
  15.     extrn    fbgn:    word
  16.     extrn    fend:    word
  17.     extrn    actptr:    word
  18.  
  19.     extrn    filename: byte
  20.  
  21. size_buf    dw    ?
  22.  
  23.     public    save_stack
  24. save_stack    dw    ?
  25.  
  26.     public    read_errors
  27. read_errors    dw    read_error_1
  28.     dw    read_error_2
  29.     dw    read_error_3
  30.     dw    read_error_4
  31.     dw    read_error_5
  32.  
  33.     public    write_errors
  34. write_errors    dw    write_error_1
  35.     dw    write_error_2
  36.     dw    write_error_3
  37.     dw    write_error_4
  38.  
  39. read_error_1    label    byte
  40. read_error_2    db    'File too large'
  41. read_error_3    db    'File not found'
  42. read_error_4    db    'End of file'
  43. read_error_5    label    byte
  44.  
  45. write_error_1    label    byte
  46. write_error_2    db    'Disk full'
  47. write_error_3    db    'Directory full or bad filename'
  48. write_error_4    label    byte
  49.  
  50.  
  51. environ_name    db    'env.'
  52. environ_name_len    equ    $-environ_name
  53.         db    'RUNLINE'
  54. runline_len    equ    $-environ_name
  55.  
  56. switchar_name    db    'env.SWITCHAR'
  57. switchar_len    equ    $-switchar_name
  58.  
  59.  
  60. form_prefix_len    dw    ?        ;for use by ln prim
  61. form_prefix_ptr    dw    ?        ;...
  62.  
  63. out_of_memory_msg    db    'Not enough memory.$'
  64.  
  65. break_state    db    ?        ;=state of break checking flag.
  66.  
  67.     extrn    stackp: byte
  68.  
  69.     public    phd_seg
  70. phd_seg    dw    ?
  71.  
  72. data    ends
  73.  
  74. code    segment byte public
  75.     assume    cs:code, ds:data, es:data
  76.  
  77. ;starting address of program.
  78. init:
  79.     mov    ax,data
  80.     mov    ds,ax
  81.     mov    phd_seg,es
  82.     mov    es,ax
  83.     cli
  84.     mov    ss,ax
  85.     mov    sp,offset stackp
  86.     sti
  87.  
  88.     push    ds
  89.     mov    ds,phd_seg
  90.     mov    bx,ds:[2]
  91.     pop    ds
  92.     mov    dx,bx
  93.     sub    dx,ax            ;compute memory between data and end.
  94.     cmp    dx,1000h        ;more than 64k?
  95.     jb    init_exit        ;no - not enough memory.
  96.     add    ax,1000h        ;start buffers at the next segment up.
  97.     call    mint_init
  98.     jc    init_exit        ;no memory.
  99.     call    init_entry
  100.     call    init_screen
  101.     call    pick_init
  102.     call    paint_screen
  103.     mov    ax,0ffffh        ;start at the end of memory.
  104.     mov    formb,ax        ;delete all forms.
  105.     mov    forme,ax
  106.  
  107.     push    ds            ;set the fatal error address.
  108.     push    cs
  109.     pop    ds
  110.     mov    dx,offset abort_fatal
  111.     mov    ax,2524h
  112.     int    21h
  113.     pop    ds
  114.  
  115.     mov    ax,33h*256+0        ;get the break state.
  116.     int    21h
  117.     mov    break_state,dl
  118.     mov    ax,33h*256+1        ;turn break checking off.
  119.     mov    dl,0
  120.     int    21h
  121.  
  122.     jmp    init_ids
  123. init_exit:
  124.     mov    dx,offset out_of_memory_msg
  125.     mov    ah,9
  126.     int    21h
  127.     mov    ax,4c01h
  128.     int    21h            ;halt because of no memory.
  129.  
  130.     extrn    lastcode: byte
  131.  
  132.     extrn    init_screen: near
  133.     extrn    pick_init: near
  134.     extrn    init_ids: near        ;restart mint interpreter
  135.     extrn    abort_fatal: near    ;fatal error handler
  136.     extrn    mint_init: near        ;perform any special mint initing.
  137.     extrn    return_null: near
  138.     extrn    paint_screen: near    ;start with the screen unpainted.
  139.  
  140. ;The following two externs init and uninit anything that's machine specific.
  141.     extrn    init_entry: near
  142.     extrn    uninit_exit: near
  143.  
  144.     extrn    set_form_pointer: near
  145. ;set_form_pointer updates the form pointer.  It does the dirty work
  146. ;    for return_form.
  147.  
  148.     extrn    return_form: near
  149. ;return_form updates the form pointer and jumps to return_tos
  150.  
  151.     extrn    return_arg: near
  152.     extrn    return_arg_active: near
  153. ;return_arg and return_arg_active return the argument whose number is given
  154. ;    in cx.  return_arg_active always returns the argument as active.
  155.  
  156.     extrn    return_string: near
  157. ;return_string returns the ALth string out of the table pointed to by bx.
  158.  
  159.     extrn    return_sicx: near
  160. ;return_sicx returns the string pointed to by si.  The length of the
  161. ;    string is given in cx.
  162.  
  163.     extrn    return_tos: near
  164. ;return_tos returns the string pointed to by the top of the stack.
  165. ;    The length of the string is the difference between di and the
  166. ;    beginning of the stirng.
  167.  
  168.     extrn    nomem: near
  169.  
  170. ;primitives here
  171.  
  172. hl_prim:
  173.     call    get_decimal_arg1    ;get the return code.
  174.     push    ax
  175.     mov    ax,33h*256+1        ;set the break state.
  176.     mov    dl,break_state
  177.     int    21h
  178.     call    uninit_exit
  179.     pop    ax
  180.     mov    ah,4ch
  181.     int    21h
  182.  
  183.  
  184. eq_prim:
  185.     call    getarg1        ;get the first argument
  186.     mov    dx,cx        ;save size of first argument
  187.     mov    di,si        ;save pointer to first argument
  188.     mov    cx,2        ;get second argument
  189.     call    getarg
  190.     cmp    cx,dx        ;lengths equal?
  191.     jne    eq_prim_1    ;no, return 4th
  192.     repe    cmpsb        ;strings equal?
  193.     jne    eq_prim_1    ;no, return 4th.
  194.     mov    cx,3
  195.     jmp    return_arg
  196. eq_prim_1:
  197.     mov    cx,4
  198.     jmp    return_arg
  199.  
  200.  
  201. nc_prim:
  202.     call    getarg1
  203.     di_points_fbgn
  204.     mov    ax,cx
  205.     jmp    return_number
  206.  
  207.  
  208. sc_prim:
  209. bc_prim:
  210.     mov    cx,2        ;get 'from' argument.
  211.     call    getarg
  212.     mov    dl,'a'        ;default to ASCII
  213.     jcxz    bc_prim_1
  214.     mov    dl,[si]        ;get from type.
  215. bc_prim_1:
  216.     mov    cx,3        ;get 'to' argument.
  217.     call    getarg
  218.     mov    dh,'d'        ;default to decimal
  219.     jcxz    bc_prim_2
  220.     mov    dh,[si]
  221. bc_prim_2:
  222.     call    getarg1
  223.     call    bc_prim_base    ;get the source base.
  224.     or    bx,bx        ;ASCII?
  225.     jnz    bc_prim_4    ;no.
  226.     lodsb
  227.     mov    ah,0
  228.     jmp    bc_prim_3
  229. bc_prim_4:
  230.     push    dx        ;preserve dx.
  231.     call    get_number
  232.     pop    dx
  233. bc_prim_3:
  234. ;we now have the number in ax.
  235.     mov    dl,dh
  236.     call    bc_prim_base
  237.     di_points_fbgn
  238.     or    bx,bx
  239.     jnz    bc_prim_5
  240.     stosb
  241.     jmp    return_tos
  242. bc_prim_5:
  243.     mov    cx,0        ;use only as many digits as are needed.
  244.     call    put_number
  245.     jmp    return_tos
  246.  
  247. ;private subroutine, used only bc_prim.
  248. bc_prim_base:
  249. ;enter with dl=base character.
  250. ;exit with bx=base if number; bx=0 if ASCII.
  251.     or    dl,20h        ;convert UPPER case to lower case.
  252.     cmp    dl,'d'
  253.     jne    bc_prim_base_1
  254.     mov    bx,10
  255.     ret
  256. bc_prim_base_1:
  257.     cmp    dl,'o'
  258.     jne    bc_prim_base_2
  259.     mov    bx,8
  260.     ret
  261. bc_prim_base_2:
  262.     cmp    dl,'h'
  263.     jne    bc_prim_base_3
  264.     mov    bx,16
  265.     ret
  266. bc_prim_base_3:
  267.     cmp    dl,'c'
  268.     jne    bc_prim_base_4
  269.     mov    bx,0
  270.     ret
  271. bc_prim_base_4:
  272.     cmp    dl,'a'        ;a alias character.
  273.     jne    bc_prim_base_5
  274.     mov    bx,0
  275.     ret
  276. bc_prim_base_5:
  277.     cmp    dl,'b'
  278.     jne    bc_prim_base_6
  279.     mov    bx,2
  280.     ret
  281. bc_prim_base_6:
  282.     ret
  283.  
  284.  
  285.  
  286. db_prim:
  287.     int    3
  288.     jmp    return_null
  289.  
  290.  
  291. dt_prim:
  292.     di_points_fbgn
  293.     mov    ah,2ah
  294.     int    21h
  295.     mov    bx,10        ;do all conversions in decimal.
  296.     push    cx
  297.     push    dx
  298.     mov    al,dh        ;get month
  299.     mov    ah,0
  300.     mov    cx,2
  301.     call    put_number
  302.     mov    al,"-"
  303.     stosb
  304.     pop    ax        ;pushed as dx (get date)
  305.     mov    ah,0
  306.     mov    cx,2
  307.     call    put_number
  308.     mov    al,"-"
  309.     stosb
  310.     pop    ax        ;pushed as cx (get year)
  311.     sub    ax,1900        ;only output the last two digits.
  312.     mov    cx,2
  313.     call    put_number
  314.     jmp    return_tos
  315.  
  316.  
  317. tm_prim:
  318.     di_points_fbgn
  319.     mov    ah,2ch
  320.     int    21h
  321.     mov    bx,10        ;do all conversions in decimal.
  322.     push    dx
  323.     push    cx
  324.     mov    al,ch        ;get hours
  325.     mov    ah,0
  326.     mov    cx,2
  327.     call    put_number
  328.     mov    al,":"
  329.     stosb
  330.     pop    ax        ;pushed as cx (get minutes)
  331.     mov    ah,0
  332.     mov    cx,2
  333.     call    put_number
  334.     mov    al,":"
  335.     stosb
  336.     pop    dx        ;get seconds
  337.     mov    al,dh
  338.     mov    ah,0
  339.     mov    cx,2
  340.     call    put_number
  341.     jmp    return_tos
  342.  
  343. ;form primitives
  344.  
  345.  
  346. ds_prim:
  347.     mov    cx,2        ;get data first.
  348.     call    getarg
  349.     mov    dx,cx
  350.     mov    di,si
  351.     call    getarg1
  352.     mov    bx,0        ;reset form pointer.
  353.     call    define_form
  354.     jmp    return_null
  355.  
  356.  
  357. ss_prim:
  358.     call    find_arg1
  359.     jnc    ss_prim_3
  360.     mov    dx,[bx].data_length    ;save the count of the form in dx.
  361.     lea    di,[bx].name_offset
  362.     add    di,[bx].name_length    ;save the pointer to the form in di.
  363.     mov    si,fbgn        ;point si at the zeroth arg.
  364.     mov    si,[si]        ;point si at the form name.
  365.     mov    si,[si]        ;point si at the first argument.
  366.     mov    ah,sgap+1    ;start with sgap 1.
  367. ss_prim_1:
  368.     cmp    si,[si]        ;are we pointing at fend?
  369.     je    ss_prim_3
  370.     push    si        ;save pointer to args.
  371.     mov    cx,[si]        ;compute length of this arg.
  372.     sub    cx,si
  373.     sub    cx,mark_overhead
  374.     add    si,mark_overhead-1    ;make si=> text of argument.
  375. ;at this point, si,cx => arg; di,dx => form.
  376.     push    di
  377.     push    dx
  378.     jcxz    ss_prim_5    ;ignore null strings.
  379. ss_prim_4:
  380.     call    string_search
  381.     jc    ss_prim_5    ;not found.  Done with this arg.
  382. ;at this point, we have found a string.  We proceed to replace it by
  383. ;the appropriate segment gap.  We have already ensured that the string
  384. ;is at least one character long.
  385.     push    cx        ;preserve cx
  386.     mov    al,ah        ;get the sgap.
  387.     stosb            ;store it.
  388. ;by the way, at this point, the relation (cx <= dx) is always true.
  389.     sub    dx,cx        ;count it, and the ones we're getting rid of.
  390.     dec    cx        ;one less to get rid of.
  391.     mov    al,sgap        ;get rid of the rest of the chars.
  392.     rep    stosb        ;cx may be zero, but it doesn't hurt.
  393.     pop    cx
  394.     jmp    ss_prim_4
  395. ss_prim_5:
  396.     pop    dx
  397.     pop    di
  398.     pop    si        ;restore pointer to args.
  399.     mov    si,[si]        ;make it point to next arg.
  400.     inc    ah        ;increment sgap to next arg.
  401.     jmp    ss_prim_1
  402. ss_prim_3:
  403.     jmp    return_null
  404.  
  405.  
  406. nb_prim:
  407.     call    find_arg1
  408.     mov    cx,3
  409.     jnc    nb_prim_1
  410.     mov    cx,2
  411. nb_prim_1:
  412.     jmp    return_arg
  413.  
  414.  
  415. ;default primitive is the same as the cl primitive, only we start counting
  416. ;  arguments from zero, not one.
  417. dflt:
  418.     mov    bp,0
  419.     jmp    cl_prim_entry
  420. cl_prim:
  421.     mov    bp,1
  422. cl_prim_entry:
  423.     mov    cx,bp        ;get the number of the form name arg.
  424.     di_points_fend
  425.     call    find_arg
  426.     jnc    cl_prim_1
  427.     jcxz    cl_prim_1    ;if no characters, return null.
  428.     or    bp,bp        ;is this dflt or cl?
  429.     jne    cl_prim_2    ;cl - use specified args.
  430.     dec    bp        ;make bp+1 be the number of the form name arg.
  431. cl_prim_2:
  432.     lodsb            ;get char
  433.     or    al,al        ;test it for sgapness
  434.     jge    cl_prim_3    ;go if not sgap
  435.     sub    al,sgap        ;which sgap?
  436.     jz    cl_prim_4    ;ignore sgap0's
  437.     cbw            ;we're going to be counting off ax
  438.     add    ax,bp        ;add in the first arg number.
  439.     push    si        ;preserve pointer, count of the form
  440.     push    cx
  441.     mov    cx,ax
  442.     call    getarg
  443.     chk_actptr_cnt
  444.     rep    movsb
  445.     pop    cx        ;restore pointer, count of the form
  446.     pop    si
  447.     jmp    cl_prim_4
  448. cl_prim_3:
  449.     chk_actptr
  450.     stosb
  451. cl_prim_4:
  452.     loop    cl_prim_2
  453. cl_prim_1:
  454.     jmp    return_tos
  455.  
  456.  
  457. cc_prim:
  458.     call    find_arg1
  459.     jnc    cc_prim_1    ;form not found.
  460.     jcxz    cc_prim_2    ;no chars left.
  461.     di_points_fbgn
  462.     movsb            ;no need to check for collision with actptr.
  463.     dec    cx
  464.     jmp    return_form
  465. cc_prim_2:
  466.     mov    cx,2
  467.     jmp    return_arg_active
  468. cc_prim_1:
  469.     jmp    return_null
  470.  
  471.  
  472. cr_prim:
  473.     call    find_arg1
  474.     jnc    cr_prim_1
  475.     mov    [bx].form_pointer,0
  476. cr_prim_1:
  477.     jmp    return_null
  478.  
  479.  
  480. cn_prim:
  481.     call    find_arg1
  482.     jnc    cn_prim_1
  483.     jcxz    cn_prim_2
  484.     push    si        ;save pointer, count to form.
  485.     push    cx
  486.     push    bx
  487.     mov    cx,2        ;get number of chars to call.
  488.     call    get_decimal_arg
  489.     mov    dx,ax        ;save in dx.
  490.     pop    bx
  491.     pop    cx
  492.     pop    si
  493.     di_points_fbgn
  494.     cmp    dx,cx        ;are we trying to get more than exists?
  495.     jbe    cn_prim_3    ;no - move the requested amount.
  496.     mov    dx,cx        ;yes - truncate to the amount that exists.
  497. cn_prim_3:
  498.     xchg    dx,cx        ;swap the count remaining and the get count.
  499.     sub    dx,cx        ;dec the count remaining by the get count.
  500.     chk_actptr_cnt        ;check for collision
  501.     rep    movsb        ;move all the chars.
  502.     mov    cx,dx        ;return the count remaining in cx.
  503.     jmp    return_form
  504. cn_prim_2:
  505.     mov    cx,3
  506.     jmp    return_arg_active
  507. cn_prim_1:
  508.     jmp    return_null
  509.  
  510.  
  511.  
  512. in_prim:
  513.     call    find_arg1
  514.     jnc    in_prim_1    ;if form not found, return null.
  515.     jcxz    in_prim_2    ;if nothing to search, return two.
  516.     push    si
  517.     mov    di,si
  518.     mov    dx,cx
  519.     mov    cx,2
  520.     call    getarg
  521. ;now si,cx => short string, di,dx => long string.
  522.     call    string_search
  523.     jc    in_prim_3    ;if it's not found, just return arg 3.
  524. ;what we want to do now is to return the string from [tos] to [di],
  525. ;  and advance the form pointer to point after the found string.
  526.     sub    dx,cx        ;dx gets long length - short length.
  527.     pop    si
  528.     mov    cx,di        ;get the number of characters before
  529.     sub    cx,si        ;  the search string.
  530.     di_points_fbgn        ;prepare to return a string.
  531.     chk_actptr_cnt        ;make sure we have enough room.
  532.     rep    movsb
  533.     mov    cx,dx        ;return_form expects the count in cx.
  534.     jmp    return_form
  535. in_prim_3:
  536.     add    sp,2        ;get rid of the pointer to the search string.
  537. in_prim_2:
  538.     mov    cx,3
  539.     jmp    return_arg_active
  540. in_prim_1:
  541.     jmp    return_null
  542.  
  543.  
  544. ev_prim:
  545.     xor    si,si            ;start at the beginning of the environ.
  546. ev_prim_1:
  547.     mov    di,fbgn
  548.  
  549.     push    si            ;copy in the environ name.
  550.     mov    si,offset environ_name
  551.     mov    cx,environ_name_len
  552.     rep    movsb
  553.     pop    si
  554.  
  555.     push    ds
  556.     mov    ds,phd_seg
  557.     mov    ds,ds:[2ch]
  558.     mov    cx,environ_name_len    ;start with what we've got already.
  559. ev_prim_2:
  560.     inc    cx
  561.     lodsb
  562.     stosb
  563.     or    al,al
  564.     jne    ev_prim_2
  565.     pop    ds
  566.     dec    cx            ;don't count the null.
  567.  
  568.     cmp    cx,environ_name_len    ;did we get any at all?
  569.     je    ev_prim_3        ;if none, we're done.
  570.  
  571.     push    si            ;remember the environment pointer.
  572.     mov    di,fbgn            ;make di->entire name.
  573.     mov    si,di            ;make si -> the name.
  574.     mov    al,'='            ;look for the name/data separator.
  575.     repne    scasb
  576.     mov    dx,cx            ;dx (data length) is number of chars left.
  577.     mov    cx,di            ;compute the name length.
  578.     sub    cx,si
  579.     dec    cx            ;don't count the '='.
  580.  
  581. ;define a form.  Enter with:
  582. ;    si => name
  583. ;    cx = name length
  584. ;    di => data
  585. ;    dx = data length
  586. ;    bx = form pointer.
  587.  
  588.     xor    bx,bx
  589.     call    define_form
  590.     pop    si
  591.     jmp    ev_prim_1
  592. ev_prim_3:
  593.     mov    di,fbgn
  594.     mov    si,80h
  595.     push    ds
  596.     mov    ds,phd_seg
  597.     lodsb                ;get the line length.
  598.     mov    dl,al
  599.     mov    dh,0
  600.     mov    cx,dx            ;put it where movs can destroy it.
  601.     rep    movsb
  602.     pop    ds
  603.  
  604.     mov    di,fbgn            ;restore di again.
  605.     mov    si,offset environ_name
  606.     mov    cx,offset runline_len
  607.     xor    bx,bx
  608.     call    define_form
  609.  
  610.     mov    ax,3700h        ;get the switchar.
  611.     int    21h
  612.  
  613.     mov    di,fbgn
  614.     mov    [di],dl            ;store the switchar.
  615.     mov    dx,1            ;set the data length.
  616.  
  617.     mov    si,offset switchar_name
  618.     mov    cx,offset switchar_len
  619.     xor    bx,bx
  620.     call    define_form
  621.  
  622.     jmp    return_null
  623.  
  624.   if 0
  625. pa_prim:
  626. ;#(ps,prefix, seperator, arguments)
  627.     di_points_fend
  628.     call    getarg1            ;get seperator and save it.
  629.     mov    bp,si            ;store the pointer to arg1 in bp
  630.     mov    dx,cx            ;store the size of arg1 in dx
  631.     mov    cx,2            ;get the form prefix.
  632.     call    getarg
  633.     mov    form_prefix_len,cx
  634.     mov    form_prefix_ptr,si
  635.     mov    si,fbgn            ;point si at the zeroth arg.
  636.     mov    si,[si]            ;point si at the prefix
  637.     mov    si,[si]            ;point si at the seperator.
  638.     mov    si,[si]            ;point si at the arguments.
  639. pa_prim_1:
  640.     cmp    si,[si]            ;are we pointing at fend?
  641.     je    pa_prim_2        ;yes, exit.
  642.     push    si            ;save pointer to args.
  643.     mov    cx,[si]            ;compute length of this arg.
  644.     sub    cx,si
  645.     sub    cx,mark_overhead
  646.     add    si,mark_overhead-1    ;make si=> text of argument.
  647. ;at this point, si,cx => arg
  648.     cmp    cx,dx            ;is argument length < prefix length?
  649.     jb    pa_prim_4        ;yes - prefix can't match.
  650.     push    di            ;save the source pointers.
  651.     push    si
  652.     push    cx
  653.     mov    di,bp
  654.     mov    cx,dx
  655.     repe    cmpsb            ;compare the prefix to the form name.
  656.     pop    cx
  657.     pop    si
  658.     pop    di
  659.     jne    pa_prim_4        ;the prefixes didn't match - ignore it.
  660. pa_prim_3:
  661.     chk_actptr_cnt
  662.     rep    movsb            ;move the name in.
  663.     mov    si,form_prefix_ptr    ;get the seperator ptr, count.
  664.     mov    cx,form_prefix_len
  665.     chk_actptr_cnt
  666.     rep    movsb            ;move it in.
  667. pa_prim_4:
  668.     pop    si            ;get the argument pointer back.
  669.     mov    si,[si]            ;get the next argument.
  670.     jmp    pa_prim_1        ;and continue.
  671. pa_prim_2:
  672.     jmp    return_tos
  673.   endif
  674.  
  675. ln_prim:
  676.     mov    bx,formb        ;get pointer to forms.
  677.     di_points_fend
  678.     call    getarg1            ;get seperator and save it.
  679.     mov    bp,si            ;store the pointer to arg1 in bp
  680.     mov    dx,cx            ;store the size of arg1 in dx
  681.     mov    cx,2            ;get the form prefix.
  682.     call    getarg
  683.     mov    form_prefix_len,cx
  684.     mov    form_prefix_ptr,si
  685. ln_prim_1:
  686.     cmp    bx,forme        ;at end?
  687.     je    ln_prim_2        ;yes, exit.
  688.     lea    si,[bx].name_offset    ;get the name pointer.
  689.     mov    cx,form_prefix_len
  690.     jcxz    ln_prim_3        ;zero prefixes match anything.
  691.     cmp    cx,[bx].name_length    ;is prefix length>name length?
  692.     ja    ln_prim_4        ;yes - prefix can't match.
  693.     push    di            ;save the source pointers.
  694.     push    si
  695.     mov    di,form_prefix_ptr
  696.     repe    cmpsb            ;compare the prefix to the form name.
  697.     pop    si
  698.     pop    di
  699.     jne    ln_prim_4        ;the prefixes didn't match - ignore it.
  700. ln_prim_3:
  701.     mov    cx,[bx].name_length    ;get the name length
  702.     chk_actptr_cnt
  703.     rep    movsb            ;move the name in.
  704.     mov    si,bp            ;get the pointer to arg1.
  705.     mov    cx,dx            ;get the size of arg1.
  706.     chk_actptr_cnt
  707.     rep    movsb            ;move it in.
  708. ln_prim_4:
  709.     add    bx,[bx].form_length    ;point to next form.
  710.     jmp    ln_prim_1        ;and continue.
  711. ln_prim_2:
  712.     jmp    return_tos
  713.  
  714.  
  715. dd_prim:
  716.     mov    si,fbgn        ;point si at "dd".
  717.     mov    si,[si]        ;point si at the first arg.
  718. dd_prim_1:
  719.     cmp    si,[si]        ;are we pointing at fend?
  720.     je    dd_prim_3
  721.     push    si        ;save pointer to args.
  722.     mov    cx,[si]        ;compute length of this arg.
  723.     sub    cx,si
  724.     sub    cx,mark_overhead
  725.     add    si,mark_overhead-1    ;make si=> text of argument.
  726.     call    find_form    ;try to find this form.
  727.     jnc    dd_prim_2    ;go if it didn't exist.
  728.     call    delete_form    ;delete the form if it did exist.
  729. dd_prim_2:
  730.     pop    si        ;restore pointer to args.
  731.     mov    si,[si]        ;make it point to next arg.
  732.     jmp    dd_prim_1
  733. dd_prim_3:
  734.     jmp    return_null
  735.  
  736.  
  737. sb_prim:
  738.     call    getarg1_filename
  739.     mov    dx,si
  740.     mov    cx,0
  741.     mov    ah,3ch            ;create file.
  742.     int    21h
  743.     mov    bx,ax            ;remember the handle.
  744.     mov    al,2
  745.     jc    sb_prim_4
  746.     mov    si,fbgn            ;point si at the zeroth arg.
  747.     mov    si,[si]            ;point si at the form name.
  748.     mov    si,[si]            ;point si at the first search string.
  749. sb_prim_1:
  750.     cmp    si,[si]            ;are we pointing at fend?
  751.     je    sb_prim_3
  752.     push    si            ;save pointer to args.
  753.     mov    cx,[si]            ;compute length of this arg.
  754.     sub    cx,si
  755.     sub    cx,mark_overhead
  756.     add    si,mark_overhead-1    ;make si=> text of argument.
  757.     push    bx
  758.     call    find_form
  759.     mov    di,bx            ;remember where the form is.
  760.     pop    bx
  761.     jnc    sb_prim_2        ;go if it isn't there.
  762.     mov    cx,[di].form_length
  763.     mov    dx,di
  764.     mov    ah,40h            ;write to a file
  765.     int    21h
  766.     jnc    sb_prim_2        ;no problem.
  767.     mov    ah,3eh            ;disk full - close the file.
  768.     int    21h
  769.     mov    dx,offset filename    ;delete the file.
  770.     mov    ah,41h
  771.     int    21h
  772.     mov    al,1
  773.     jmp    short sb_prim_4
  774. sb_prim_2:
  775.     pop    si        ;restore pointer to args.
  776.     mov    si,[si]        ;make it point to next arg.
  777.     jmp    sb_prim_1
  778. sb_prim_3:
  779.     mov    ah,3eh        ;close the file.
  780.     int    21h
  781.     mov    al,0        ;no problem.
  782. sb_prim_4:
  783.     mov    bx,offset write_errors
  784.     jmp    return_string
  785.  
  786.  
  787. fb_prim:
  788. ;Note that information about the structure 'form' is hard-coded into the
  789. ;  next routine.  We assume that 'form_length' is only two bytes long,
  790. ;  and occurs at the beginning of the structure.
  791.     call    getarg1_filename
  792.     mov    dx,si
  793.     mov    ax,3d00h        ;open file for reading.
  794.     int    21h
  795.     mov    bx,ax            ;remember the handle.
  796.     mov    al,2
  797.     jc    fb_prim_4_j_1
  798.     mov    ax,forme        ;anything loaded yet?
  799.     cmp    ax,formb
  800.     jne    fb_prim_1        ;yes - load one by one.
  801.  
  802.     mov    cx,0
  803.     mov    dx,cx
  804.     mov    ax,4202h        ;seek to the end of the file.
  805.     int    21h
  806.  
  807.     push    ax            ;remember the file size.
  808.     mov    dx,cx            ;zero out dx again.
  809.     mov    ax,4200h
  810.     int    21h
  811.     pop    cx            ;get the file size back again.
  812.  
  813.     mov    ax,forme        ;no - do a bulk load.
  814.     sub    ax,cx            ;see if there is enough room.
  815.     jb    fb_prim_3_j        ;can't possibly be.
  816.     mov    dx,ax
  817.     sub    ax,free_space        ;free_space is the working room.
  818.     cmp    ax,fend
  819.     jb    fb_prim_3_j        ;there isn't.
  820.  
  821.     mov    cx,formb        ;compute size of active string.
  822.     sub    cx,actptr
  823.     mov    si,actptr        ;->active string.
  824.     mov    di,dx            ;->new formb.
  825.     sub    di,cx            ;leave room for the active string.
  826.     mov    actptr,di
  827.     rep    movsb
  828.     mov    formb,dx
  829.  
  830.     mov    cx,-1            ;read the whole file in.
  831.     mov    ah,3fh            ;read from a file.
  832.     int    21h
  833.     jc    fb_prim_5        ;trouble reading...
  834.     push    bx            ;preserve handle.
  835.     call    rehash            ;reconstruct the hash links.
  836.     pop    bx
  837. fb_prim_6:
  838.     mov    ah,3eh            ;close the file.
  839.     int    21h
  840.     mov    al,0            ;all ok.
  841.     jmp    fb_prim_4        ;we destroyed the active string.
  842. fb_prim_5:
  843.     mov    ah,3eh            ;close the file.
  844.     int    21h
  845.     mov    al,3            ;read error.
  846. fb_prim_4_j_1:
  847.                     ;we get here if we can't open the file.
  848.     jmp    fb_prim_4        ;we destroyed the active string.
  849. fb_prim_3_j:
  850.     jmp    fb_prim_3
  851. fb_prim_1:
  852.     mov    dx,offset size_buf    ;set disk transfer address
  853.     mov    cx,2
  854.     mov    ah,3fh            ;read from a file.
  855.     int    21h
  856.     jc    fb_prim_5        ;close the file - trouble reading.
  857.  
  858.     cmp    ax,0            ;did we read no bytes at all?
  859.     je    fb_prim_6        ;close and exit.
  860.  
  861.     mov    ax,size_buf        ;we need twice as much memory
  862.     shl    ax,1            ;  as in size_buf.
  863.     add    ax,fend            ;see if there is enough room.
  864.     add    ax,free_space
  865.     cmp    ax,actptr
  866.     jae    fb_prim_3
  867.  
  868.     mov    dx,fend
  869.     add    dx,2
  870.     mov    cx,size_buf
  871.     sub    cx,2            ;transfer two less bytes.
  872.     mov    ah,3fh            ;read from a file.
  873.     int    21h
  874.     jc    fb_prim_5
  875.     cmp    ax,cx
  876.     jne    fb_prim_5        ;trouble reading...
  877.  
  878.     push    bx
  879.     mov    bx,fend            ;don't add 2 like we did before because
  880.     mov    cx,[bx].name_length    ;  we already read form_length.
  881.     mov    dx,[bx].data_length
  882.     lea    si,[bx].name_offset
  883.     mov    di,si
  884.     add    di,cx        ;or [bx].name_length, but cx is cheaper.
  885.     mov    bx,[bx].form_pointer
  886.     call    define_form
  887.     pop    bx
  888.  
  889.     jmp    fb_prim_1
  890. fb_prim_3:
  891.     mov    ah,3eh            ;close the file.
  892.     int    21h
  893.     jmp    nomem
  894. fb_prim_4:
  895.     mov    bx,offset read_errors
  896.     jmp    return_string
  897.  
  898.  
  899. ad_prim:
  900.     call    get_math
  901.     add    ax,bx
  902.     push    si
  903.     jmp    return_number
  904.  
  905.  
  906. su_prim:
  907.     call    get_math
  908.     sub    ax,bx
  909.     push    si
  910.     jmp    return_number
  911.  
  912.  
  913. ml_prim:
  914.     call    get_math
  915.     imul    bx
  916.     push    si
  917.     jmp    return_number
  918.  
  919.  
  920. dv_prim:
  921.     call    get_math
  922.     or    bx,bx
  923.     je    dv_prim_1
  924.     cwd
  925.     idiv    bx
  926. dv_prim_1:
  927.     push    si
  928.     jmp    return_number
  929.  
  930.  
  931. md_prim:
  932.     call    get_math
  933.     or    bx,bx
  934.     je    md_prim_1
  935.     cwd
  936.     idiv    bx
  937.     mov    ax,dx
  938. md_prim_1:
  939.     push    si
  940.     jmp    return_number
  941.  
  942.  
  943. gr_prim:
  944.     call    get_math
  945.     mov    cx,3
  946.     cmp    ax,bx
  947.     jg    gr_prim_1
  948.     mov    cx,4
  949. gr_prim_1:
  950.     jmp    return_arg
  951.  
  952.  
  953. ;primitive externals
  954.     public    dflt
  955.     public    hl_prim
  956.     public    eq_prim
  957.     public    nc_prim
  958.     public    sc_prim
  959.     public    db_prim
  960.     public    dt_prim
  961.     public    tm_prim
  962. ;forms
  963.     public    ds_prim
  964.     public    ss_prim
  965.     public    cl_prim
  966.     public    cc_prim
  967.     public    cn_prim
  968.     public    cr_prim
  969.     public    in_prim
  970.     public    ev_prim
  971.     public    ln_prim
  972.     public    dd_prim
  973.     public    sb_prim
  974.     public    fb_prim
  975.     public    nb_prim
  976. ;math
  977.     public    ad_prim
  978.     public    su_prim
  979.     public    ml_prim
  980.     public    dv_prim
  981.     public    md_prim
  982.     public    gr_prim
  983.  
  984. ;form subroutines
  985.     extrn    define_form: near
  986.     extrn    delete_form: near
  987. ;delete_form deletes the form pointed to by bx.
  988.  
  989.     extrn    rehash: near
  990. ;rehash rebuilds the hashing links.  Used only when a file is bulk loaded.
  991.  
  992.     extrn    find_form: near
  993. ;find_form returns bx pointing to the form whose name is pointed to by si.
  994. ;    The length of the form name is given in cx.
  995. ;    If the form doesn't exist, cy is set, otherwise cy is clear.
  996. ;    di points to the form data after the form pointer, and cx is the
  997. ;    number of chars after the form pointer.
  998.  
  999.     extrn    find_arg1: near
  1000. ;find_arg1 returns bx pointing to the form whose name is given in
  1001. ;    arg1.  If the form doesn't exist, cy is set, otherwise cy is clear.
  1002. ;    di points to the form data after the form pointer, and cx is the
  1003. ;    number of chars after the form pointer.
  1004.  
  1005.     extrn    find_arg: near
  1006. ;find_arg returns bx pointing to the form whose name is given in
  1007. ;    the arg specified by cx.  If the form doesn't exist, cy is
  1008. ;    set, otherwise cy is clear.  di points to the form data
  1009. ;    after the form pointer, and cx is the number of chars after
  1010. ;    the form pointer.
  1011.  
  1012.  
  1013. ;utility subroutines
  1014.  
  1015.  
  1016.     public    get_math
  1017. get_math:
  1018. ;exit with ax=first number, bx=second number, si->first arg, di->first number.
  1019.     mov    cx,2
  1020.     call    get_decimal_arg
  1021.     push    ax
  1022.     call    getarg1
  1023.     push    si
  1024.     call    get_decimal
  1025.     mov    di,si
  1026.     pop    si
  1027.     pop    bx        ;pushed as ax
  1028.     ret
  1029.  
  1030.  
  1031.     public    get_decimal_arg1
  1032. get_decimal_arg1:
  1033.     mov    cx,1
  1034. ;fall through
  1035.     public    get_decimal_arg
  1036. get_decimal_arg:
  1037.     call    getarg
  1038. ;fall through
  1039.     public    get_decimal
  1040. get_decimal:
  1041.     mov    bx,10
  1042. ;fall through
  1043.     public    get_number
  1044. get_number:
  1045. ;enter with si,cx => string containing trailing number, bx=base to convert
  1046. ;  number in.  Return number in ax, si => start of digit string.
  1047.     add    si,cx
  1048.     push    cx
  1049. get_number_1:
  1050.     dec    si
  1051.     mov    al,[si]
  1052.     sub    al,"0"        ;between 0 and "9"?
  1053.     jb    get_number_2    ;no - can't be a digit.
  1054.     cmp    al,"9"-"0"    ;between "0" and "9"?
  1055.     jbe    get_number_6    ;yes - must be a digit.
  1056.     cmp    al,"a"-"0"
  1057.     jb    get_number_8
  1058.     sub    al,"a"-"A"
  1059. get_number_8:
  1060.     cmp    al,"A"-"0"    ;between "A" and "9"?
  1061.     jb    get_number_2    ;yes - can't be a digit.
  1062.     sub    al,"A"-("0"+10)    ;convert "A" to 10
  1063. get_number_6:
  1064.     cmp    al,bl        ;a legal digit in the desired base?
  1065.     jae    get_number_2    ;no.
  1066.     loop    get_number_1
  1067.     dec    si        ;setup for pre-increment.
  1068. get_number_2:
  1069.     mov    dx,cx
  1070.     pop    cx        ;restore count.
  1071.     sub    cx,dx        ;get the actual count of chars into cx.
  1072.     inc    si
  1073.     push    si        ;save a copy of the start of the number.
  1074.     mov    ax,0        ;initially zero.
  1075. ;at this point, si => first digit, cx = count of digits to convert.
  1076.     jcxz    get_number_4    ;if no more chars, we're done.
  1077. get_number_3:
  1078.     mul    bx
  1079.     mov    dx,ax
  1080.     lodsb            ;ax = new ASCII digit.
  1081.     sub    al,"0"        ;make it a number.
  1082.     cmp    al,"9"-"0"
  1083.     jbe    get_number_7
  1084.     cmp    al,"a"-"0"
  1085.     jb    get_number_9
  1086.     sub    al,"a"-"A"
  1087. get_number_9:
  1088.     sub    al,"A"-("0"+10)
  1089. get_number_7:
  1090.     cbw            ;make it a word.
  1091.     add    ax,dx        ;and add in the old value.
  1092.     loop    get_number_3
  1093. get_number_4:
  1094.     pop    si
  1095.     cmp    byte ptr -1[si],"-"
  1096.     jne    get_number_5
  1097.     dec    si
  1098.     neg    ax
  1099. get_number_5:
  1100.     ret
  1101.  
  1102.  
  1103.     public    return_number
  1104. return_number:
  1105. ;enter with di => place to put string, tos => start of string,
  1106. ;  ax=number.
  1107.     mov    cx,0        ;use only as many digits as is needed.
  1108.     mov    bx,10
  1109.     call    put_number
  1110.     jmp    return_tos
  1111.  
  1112.  
  1113.     public    put_number
  1114. put_number:
  1115. ;enter with di => place to put string, ax = number, cx=minimum number of digits
  1116. ;  bx=base to convert number to.
  1117.     or    ax,ax
  1118.     jge    put_number_1
  1119.     neg    ax
  1120.     mov    byte ptr [di],"-"
  1121.     inc    di
  1122. put_number_1:
  1123.     call    one_digit
  1124.     ret
  1125.  
  1126.  
  1127. one_digit:
  1128.     jcxz    one_digit_3
  1129.     dec    cx
  1130. one_digit_3:
  1131.     cwd
  1132.     div    bx
  1133.     push    dx
  1134.     or    ax,ax
  1135.     jnz    one_digit_1    ;if more digits, do them.
  1136.     jcxz    one_digit_2    ;if count is zero, don't do next digit.
  1137. ;we get here if we have more digits to do, or we have more leading
  1138. ; zeroes to place.
  1139. one_digit_1:
  1140.     call    one_digit
  1141. one_digit_2:
  1142.     pop    ax        ;pushed as dx
  1143.     add    al,"0"
  1144.     cmp    al,"9"
  1145.     jbe    one_digit_4
  1146.     add    al,"A"-("9"+1)    ;the digit above "9" becomes an "A".
  1147. one_digit_4:
  1148.     chk_actptr
  1149.     stosb
  1150.     ret
  1151.  
  1152.  
  1153. string_search:
  1154.  
  1155.     if    1
  1156.  
  1157. ;enter with si,cx => short string, di,dx => long string.
  1158. ;exit with nc if string was found, di,dx => position found.
  1159. ;exit with cy if string was not found.
  1160.     jcxz    string_search_3    ;zero length strings are found immediately
  1161. ;we can get into trouble if cx = 0 after this point.
  1162. string_search_1:
  1163.     cmp    dx,cx
  1164.     jb    string_search_2
  1165.     push    si    ;preserve all the registers.
  1166.     push    di
  1167.     push    cx
  1168.     repe    cmpsb
  1169.     pop    cx
  1170.     pop    di
  1171.     pop    si
  1172.     je    string_search_3
  1173.     dec    dx
  1174.     inc    di
  1175.     jmp    string_search_1
  1176. string_search_3:
  1177.     clc
  1178.     ret
  1179. string_search_2:
  1180.     stc
  1181.     ret
  1182.  
  1183.     else
  1184.  
  1185. ;enter with si,cx => short string, di,dx => long string.
  1186. ;exit with nc if string was found, di,dx => position found.
  1187. ;exit with cy if string was not found.
  1188. ;preserve si,cx, ah.
  1189.     jcxz    string_search_1        ;zero length strings are found immediately
  1190.     mov    bx,cx            ;save search string length.
  1191.     mov    cx,dx            ;get target string length.
  1192.     mov    dx,si            ;save search string pointer.
  1193.     dec    bx
  1194.     sub    cx,bx            ;this many fewer chars to look at.
  1195.     jb    string_search_5        ;string is shorter than search.
  1196. string_search_3:
  1197.     jcxz    string_search_5        ;no chars to look at.
  1198.     mov    si,dx
  1199.     lodsb                ;get the first char.
  1200. string_search_4:
  1201.     scasb                ;look for the first char.
  1202.     loopnz    string_search_4        ;keep looking until we find it.
  1203.     jnz    string_search_5        ;we didn't
  1204.     xchg    cx,bx            ;set the count to the string length.
  1205.     push    cx            ;save the string length
  1206.     push    di            ;save the source position
  1207.     repe    cmpsb            ;is this it?
  1208.     mov    cx,bx            ;restore the search length
  1209.     pop    di            ;restore the source position
  1210.     pop    bx            ;restore the string length
  1211.     jne    string_search_3        ;no match - try at next position.
  1212.     mov    si,dx            ;restore search pointer
  1213.     dec    di            ;make di point to the first char again.
  1214.     mov    dx,cx            ;return the remaining count in dx.
  1215.     mov    cx,bx            ;restore search count
  1216.     inc    cx            ;restore count's original value.
  1217. string_search_1:
  1218.     clc
  1219.     jmp    short string_search_2
  1220. string_search_5:
  1221.     stc
  1222. string_search_2:
  1223.     ret
  1224.  
  1225.     endif
  1226.  
  1227.  
  1228.     public    getarg1_filename
  1229. getarg1_filename:
  1230.     mov    cx,1
  1231.     public    getarg_filename
  1232. getarg_filename:
  1233.     call    getarg
  1234.     mov    di,offset filename
  1235.     rep    movsb
  1236.     xor    al,al
  1237.     stosb
  1238.     mov    si,offset filename
  1239.     ret
  1240.  
  1241.  
  1242.     extrn    getarg1: near
  1243. ;getarg1 returns si -> the first argument.  cx is set to the size
  1244. ;    of the first argument.
  1245.  
  1246.     extrn    getarg: near
  1247. ;getarg returns si -> the argument given in cx.  cx is set to the size
  1248. ;    of the argument.
  1249.  
  1250. code    ends
  1251.  
  1252.     end    init
  1253.  
  1254.