home *** CD-ROM | disk | FTP | other *** search
/ Compendium Deluxe 1 / LSD Compendium Deluxe 1.iso / a / programming / assembly / talinasm.lha / pmatch.asm < prev    next >
Encoding:
Assembly Source File  |  1991-09-12  |  20.5 KB  |  760 lines

  1. * ========================================================================
  2. * pmatch.asm -- routines to emulate AmigaDOS 2.0 pattern matcher 
  3. * ©1991 by Talin / Sylvan Technical Arts
  4. * ========================================================================
  5.  
  6. ; register usage:
  7. ;    d0 - scratch
  8. ;    d1 - next opcode
  9. ;    d2 - scratch
  10. ;    d3 - IsWild
  11. ;    d4 - stack limit
  12. ;    d5 - 'all' flag
  13.  
  14. ;    a0 - scratch
  15. ;    a1 - scratch
  16. ;    a2 - pattern
  17. ;    a3 - out
  18. ;    a4 - outlimit
  19. ;    a5 - start of opcode / save
  20.  
  21. PMATCH_EOS        equ        $00
  22. PMATCH_NULL     equ        $10
  23. PMATCH_NOT        equ        $20
  24. PMATCH_WILD     equ        $30
  25. PMATCH_POUND    equ        $40
  26. PMATCH_CLASS     equ        $50
  27. PMATCH_NCLASS    equ        $60
  28. PMATCH_STRING     equ        $70
  29. PMATCH_CHOICE    equ        $80
  30. PMATCH_SKIP        equ        $90
  31.  
  32. TICK            equ        0x27
  33.  
  34.             xref    ToEnglish
  35.             far        code
  36.  
  37. patch_zeroop:
  38.             moveq    #0,d0                        ; op size = 0
  39. patch_op:        ; (a5 = loc, d1 = op, d0 = size )
  40.             move.b    d0,1(a5)                    ; loc[1] = size;
  41.             lsr.w    #8,d0                        ; size >>= 8
  42.             and.w    #$0f,d0                        ; size &= 0x0f
  43.             or.w    d1,d0                        ; size += op
  44.             move.b    d0,(a5)                        ; loc[0] = size;
  45.             rts
  46.  
  47. opheader:    move.l    a3,d0                        ; get output pointer
  48.             addq.l    #2,d0                        ; add sizeof opcode
  49.             sub.l    a4,d0                        ; subtract output limit
  50.             bpl.s    1$                            ; if over, then do nothing
  51.             addq.w    #2,a3                        ; add sizeof opcode to output ptr
  52. 1$            rts                                    ; return
  53.  
  54. opdata:        move.l    a3,d2                        ; get output pointer
  55.             addq.l    #1,d2                        ; add sizeof byte
  56.             sub.l    a4,d2                        ; subtract output limit
  57.             bpl.s    1$                            ; if over, then do nothing
  58.             move.b    d1,(a3)+                    ; write data to output buffer
  59. 1$            rts                                    ; return
  60.  
  61. ppregs        reg        d2-d5/a2-a5
  62.  
  63.             xdef    _PatternParse,PatternParse
  64.  
  65. _PatternParse
  66.             movem.l    ppregs,-(sp)                ; save registers
  67.             move.l    32+4(sp),a2                    ; get pattern address
  68.             move.l    32+8(sp),a3                    ; output buffer address
  69.             move.l    32+12(sp),d0                ; size of output buffer
  70.             bra.s    pp1                            ; go to C entry point
  71.  
  72. PatternParse:            ; (a2 = pattern, a3 = output buffer, d0 = limit)
  73.             movem.l    ppregs,-(sp)                ; save registers
  74. pp1:        move.l    a3,a4                        ; a4 <-- output buffer
  75.             add.l    d0,a4                        ; add size of buffer to get out limit
  76.             moveq    #0,d3                        ; set IsWild to zero
  77.             moveq    #-1,d5                        ; set ALL to TRUE
  78.  
  79.             move.l    sp,d4                        ; d4 <-- stack pointer
  80.             sub.l    #400,d4                        ; d4 <-- lower limit of stack
  81.  
  82.             bsr        parse_pattern                ; call recursive routine
  83.             beq.s    1$                            ; if failed, return normally
  84.             move.b    (a2),d0                        ; get last character looked at
  85.             bne.s    2$                            ; if not zero, then failed.
  86.  
  87.             move.l    a3,d0                        ; get output pointer
  88.             addq.l    #2,d0                        ; add 2
  89.             sub.l    a4,d0                        ; subtract output limit
  90.             bpl.s    2$                            ; if over the end, then error
  91.  
  92.             moveq    #0,d1                        ; terminate buffer
  93.             bsr        opdata                        ; write out opcode
  94.             bsr        opdata                        ; and opdata
  95.  
  96.             move.l    d3,d0                        ; return IsWild
  97.             movem.l    (sp)+,ppregs                ; restore registers
  98.             rts                                    ; return
  99.  
  100. 2$            moveq    #-1,d0                        ; failed because of match error
  101. 1$            movem.l    (sp)+,ppregs                ; restore registers
  102.             rts                                    ; return
  103.  
  104. ;---------- recursive pattern parsing subroutine
  105.  
  106. parse_pattern:
  107.  
  108. ;---------- save a5 on the stack, and check to make sure stack is not too deep
  109.  
  110.             move.l    a5,-(sp)                    ; save starting point
  111.             cmp.l    sp,d4                        ; compare stack ptr to stack limit
  112.             bhs        parse_fail                    ; if d4 is higher, then stack too deep
  113.  
  114. *int parse_pattern(void)
  115. *{
  116.  
  117. ;---------- a pattern or sub-pattern cannot start with a termination character
  118. ;            such as ')' or '|'
  119.  
  120. *        /* pattern or pattern substring can't start with closing delimiter */
  121. *
  122. *    if (*pat == '|' || *pat == ')')
  123. *    {    goto fail;
  124. *    }
  125.  
  126.             move.b    (a2),d0                        ; d0 <-- current pattern character
  127.  
  128.             cmp.b    #'|',d0                        ; if '|' character (or)
  129.             beq        parse_fail                    ; goto fail
  130.             cmp.b    #')',d0                        ; if close paren
  131.             beq        parse_fail                    ; goto fail
  132.  
  133. ;---------- loop through the characters in the pattern, and take action based
  134. ;            on the character seen.
  135.  
  136. *    while (*pat)
  137. *    {    char            *start = out;
  138. *        if (*pat == ')' || *pat == '|') return TRUE;
  139.  
  140. loop1:        move.b    (a2),d0                        ; d0 <-- *pat
  141.             beq        parse_succeed                ; if character == '\0' then success
  142.  
  143.             move.l    a3,a5                        ; a5 <-- start of next output opcode
  144.  
  145.             cmp.b    #'|',d0                        ; if '|' character (or)
  146.             beq        parse_succeed                ; end of pattern, pop a level
  147.             cmp.b    #')',d0                        ; if close paren
  148.             beq        parse_succeed                ; end of pattern, pop a level
  149.  
  150.             addq    #1,a2                        ; skip over character parsed
  151.  
  152. ;---------- parse '#' (repeat) symbol
  153.  
  154. *        else if (*pat == '#')
  155. *        {    pat++;
  156. *            opheader();
  157. *            unless (parse_pattern()) goto fail;
  158. *            patch_op(PMATCH_POUND,start,out-start-2);
  159.  
  160.             cmp.b    #'#',d0                        ; if '#' character (repeat)
  161.             bne.s    10$                            ; then
  162.  
  163.             bsr        opheader                    ; reserve space for op header
  164.             move.w    d5,-(sp)                    ; save ALL flag
  165.             moveq    #0,d5                        ; ALL = false
  166.             bsr        parse_pattern                ; call parse_pattern recursively
  167.             move.w    (sp)+,d5                    ; restore ALL flag
  168.             tst.w    d0                            ; return
  169.             beq        parse_fail                    ; if failed, then also fail
  170.  
  171. 4$            moveq    #PMATCH_POUND,d1            ; op = PMATCH_POUND
  172.  
  173. 5$            move.l    a3,d0                        ; d0 <-- out
  174.             sub.l    a5,d0                        ; d0 <-- out - start
  175.             subq.l    #2,d0                        ; d0 <-- out - start - 2 (size of op)
  176.             bsr        patch_op                    ; patch in the opcode.
  177.  
  178.             moveq    #1,d3                        ; IsWild = 1 (wildcards present)
  179.             bra        loop1                        ; next character
  180.  
  181. ;---------- parse '*' (star) symbol
  182.  
  183. *        else if (*pat == '*')
  184. *        {    pat++;
  185. *            opheader();
  186. *            opheader();
  187. *            patch_op(PMATCH_WILD,start+2,0);
  188. *            patch_op(PMATCH_POUND,start,out-start-2);
  189.  
  190. 10$            cmp.b    #'*',d0                        ; if '*' character (star)
  191.             bne.s    20$                            ; then
  192.  
  193.             bsr        opheader                    ; reserve space for POUND op header
  194.             bsr        opheader                    ; reserve space for WILDCARD op header
  195.  
  196.             addq    #2,a5                        ; start += 2
  197.             moveq    #PMATCH_WILD,d1                ; op = PMATCH_WILD
  198.             bsr        patch_zeroop                ; patch op with no data field
  199.             subq    #2,a5                        ; start -= 2
  200.  
  201. ;            moveq    #PMATCH_POUND,d1            ; op = PMATCH
  202.             bra.s    4$                            ; do nstd_patch
  203.  
  204. ;---------- parse '~' (negate) symbol
  205.  
  206. *        else if (*pat == '~')
  207. *        {    pat++;
  208. *            opheader();
  209. *            patch_op(PMATCH_NOT,start,0);
  210.  
  211. 20$            cmp.b    #'~',d0                        ; if '~' character (negate)
  212.             bne.s    30$                            ; then
  213.             moveq    #PMATCH_NOT,d1                ; op = PMATCH_NOT
  214.             bsr        opheader                    ; reserve space for op header
  215.             bsr        patch_zeroop                ; patch op with no data field
  216.             moveq    #1,d3                        ; IsWild = 1 (wildcards present)
  217.             bra.s    loop1                        ; get next character
  218.  
  219. ;---------- parse '%' (null) symbol
  220.  
  221. *        else if (*pat == '%')
  222. *        {    pat++;
  223. *            opheader();
  224. *            patch_op(PMATCH_NULL,start,0);
  225.  
  226. 30$            cmp.b    #'%',d0                        ; if '%' character (null)
  227.             bne.s    40$                            ; then
  228.             moveq    #PMATCH_NULL,d1                ; op = PMATCH_NULL
  229.             bra        std_patch                    ; finish up op
  230.  
  231. ;---------- parse '?' (wildcard) symbol
  232.  
  233. *        else if (*pat == '?')
  234. *        {    pat++;
  235. *            opheader();
  236. *            patch_op(PMATCH_WILD,start,0);
  237.  
  238. 40$            cmp.b    #'?',d0                        ; if '?' character (wildcard)
  239.             bne.s    50$                            ; then
  240.             moveq    #PMATCH_WILD,d1                ; op = PMATCH_WILD
  241.             bra        std_patch                    ; finish up op
  242.  
  243. ;---------- parse '[' (class) symbol
  244.  
  245. *        else if (*pat == '[')
  246.  
  247. 50$            cmp.b    #'[',d0                        ; if '[' character (class)
  248.             bne.s    60$                            ; then
  249.  
  250. *        {    int                op = PMATCH_CLASS;
  251.  
  252.             move.w    #PMATCH_CLASS,-(sp)            ; save PMATCH_CLASS on stack
  253.  
  254. *            pat++;
  255. *            opheader();
  256.  
  257.             bsr        opheader                    ; reserve space for op header
  258.  
  259. *            if (*pat == '~')
  260. *            {    pat++;
  261. *                op = PMATCH_NCLASS;
  262. *            }
  263.  
  264.             cmp.b    #'~',(a2)                    ; if it's a negative class
  265.             bne.s    51$                            ; then
  266.             addq    #1,a2                        ; skip over that character
  267.             move.w    #PMATCH_NCLASS,(sp)            ; store PMATCH_NCLASS on stack
  268. 51$:
  269.  
  270. *            for (;;)
  271. *            {    if (*pat == '\0') goto fail;
  272. *                if (*pat == ']') break;
  273. *                if (*pat == TICK) pat++;
  274. *                opdata(ToEnglish(*pat++));
  275. *            }
  276.  
  277. 52$            move.b    (a2)+,d0                    ; get next character
  278.             beq.s    59$                            ; if no closing bracket, fail
  279.  
  280.             cmp.b    #']',d0                        ; if it's a closing bracket
  281.             beq.s    58$                            ; then exit the loop
  282.  
  283.             cmp.b    #TICK,d0                    ; if it's a tick mark
  284.             bne.s    55$                            ; then
  285.             move.b    (a2)+,d0                    ; bump pointer
  286.  
  287. 55$            jsr        ToEnglish                    ; convert to english
  288.             move.w    d0,d1                        ; to d1
  289.             bsr        opdata                        ; write it out
  290.             bra.s    52$                            ; next character in char class
  291.  
  292. *            if (*pat != ']') return FALSE;        (not needed now)
  293. *            pat++;
  294. *            patch_op(op,start,out-start-2);
  295.  
  296. 58$            move.w    (sp)+,d1                    ; d1 <-- PMATCH_(N)CLASS
  297.             bra        5$                            ; do nstd_patch
  298.  
  299. 59$            addq    #2,sp                        ; clean up stack
  300.             bra        parse_fail                    ; return failure
  301.  
  302. ;---------- parse '(' (group) symbol
  303.  
  304. *        else if (*pat == '(')
  305.  
  306. 60$            cmp.b    #'(',d0                        ; if '(' character (group)
  307.             bne        70$                            ; then
  308.  
  309. *        {    UBYTE            *last_goto = NULL;
  310. *            pat++;
  311.  
  312.             clr.l    -(sp)                        ; push last_goto on stack (zero now)
  313.             move.b    (a2),d0                        ; get next character, don't bump
  314.  
  315. *            for (;;)
  316. *            {    start = out;
  317.  
  318. 61$            move.l    a3,a5                        ; save current out address
  319.  
  320. *                opheader();
  321. *                unless (parse_pattern()) return FALSE;
  322.  
  323.             bsr        opheader                    ; reserve space for opcode header
  324.             bsr        parse_pattern                ; get sub-pattern
  325.             beq.s    69$                            ; if failed, then leave
  326.  
  327. *                patch_op(0, out, last_goto ? out - last_goto : 0);
  328.  
  329.             moveq    #0,d0                        ; size = 0
  330.             tst.l    (sp)                        ; if last_goto is nonzero
  331.             beq.s    62$                            ; then size is still zero
  332.             move.l    a3,d0                        ; size = out
  333.             sub.l    (sp),d0                        ; size = out - last_goto
  334.  
  335. 62$            move.l    a5,a0                        ; save start in a0
  336.             move.l    a3,a5                        ; write opcode to out, not start
  337.             moveq    #0,d1                        ; opcode = 0 for now
  338.             bsr        patch_op                    ; patch in what we have
  339.  
  340.             move.l    a0,a5                        ; restore start ptr
  341.  
  342. *                last_goto = out;
  343.  
  344.             move.l    a3,(sp)                        ; last_goto <-- out
  345.  
  346. *                opheader();                            /* location of goto                */
  347.  
  348.             bsr        opheader                    ; reserve space for opcode
  349.  
  350. *                if (*pat == ')') break;
  351.  
  352.             move.b    (a2)+,d0                    ; get next character
  353.             cmp.b    #')',d0                        ; if close paren
  354.             beq.s    63$                            ; break loop
  355.  
  356. *                if (*pat != '|') return FALSE;
  357.  
  358.             cmp.b    #'|',d0                        ; if not OR
  359.             bne.s    69$                            ; goto failure
  360.  
  361. *                patch_op(PMATCH_CHOICE,start,out-start-2);
  362.  
  363.             move.l    a3,d0                        ; d0 <-- out
  364.             sub.l    a5,d0                        ; d0 <-- out - start
  365.             subq.l    #2,d0                        ; d0 <-- out - start - 2
  366.             moveq    #PMATCH_CHOICE,d1            ; d1 = choice op
  367.             bsr        patch_op
  368.  
  369.             moveq    #1,d3                        ; IsWild = 1
  370.             bra.s    61$                            ; do next part of group
  371.  
  372. *                pat++;
  373. *            }
  374. *            patch_op(PMATCH_NULL,start,out-start-2);
  375.  
  376. 63$
  377.             move.l    a3,d0                        ; d0 <-- out
  378.             sub.l    a5,d0                        ; d0 <-- out - start
  379.             subq.l    #2,d0                        ; d0 <-- out - start - 2
  380.             moveq    #PMATCH_NULL,d1                ; d1 = null op
  381.             bsr        patch_op
  382.  
  383. *            pat++;
  384. *            for (;;)
  385. *            {    int        offset;
  386. *                offset = (last_goto[0]<< 8) + last_goto[1];
  387.  
  388.             move.l    (sp)+,a1                    ; a1 <-- last_goto (also clean up stack)
  389.  
  390. 64$            move.b    (a1),d2                        ; d2 <-- offset part 1
  391.             lsl.w    #8,d2                        ; shifted over 8
  392.             move.b    1(a1),d2                    ; d2 <-- offset
  393.  
  394. *                patch_op(PMATCH_SKIP,last_goto,out-last_goto-2);
  395.  
  396.             move.l    a1,a5                        ; a3 <-- last_goto
  397.             move.l    a3,d0                        ; d0 <-- out
  398.             sub.l    a1,d0                        ; d0 <-- out - last_goto
  399.             subq.l    #2,d0                        ; d0 <-- out - last_goto - 2
  400.             moveq    #PMATCH_SKIP,d1                ; d1 = skip op
  401.             bsr        patch_op                    ; patch in opcode
  402.  
  403. *                if (offset == 0) break;
  404. *                last_goto -= offset;
  405.  
  406.             tst.w    d2                            ; if last in chain
  407.             beq        endloop                        ; then parse next op
  408.  
  409.             sub.w    d2,a1                        ; last_goto -= offset
  410.             bra.s    64$                            ; loop
  411.  
  412. 69$            addq    #4,sp                        ; clean up stack
  413.             bra        parse_fail
  414.  
  415. ;---------- parse "'" (tick) symbol
  416.  
  417. *        {    if (*pat == TICK)                    /* skip over tick character        */
  418. *            {    pat++;
  419. *                if (*pat=='\0') return FALSE;    /* can't tick end of string        */
  420. *            }
  421. *            opdata(PMATCH_STRING);                /* STRING match op                */
  422. *            opdata(ToEnglish(*pat++));            /* character to match            */
  423.  
  424. 70$            cmp.b    #TICK,d0                    ; if "'" character (tick)
  425.             bne.s    75$                            ; then do
  426.  
  427.             move.b    (a2)+,d0                    ; get next character
  428.             beq        parse_fail                    ; can't tick the end of string
  429.  
  430. ;---------- parse normal character
  431.  
  432. 75$            moveq    #PMATCH_STRING,d1            ; put out a PMATCH_STRING opcode
  433.             bsr        opdata                        ; write to output buffer
  434.  
  435.             bsr        ToEnglish                    ; put out normal character
  436.             move.w    d0,d1                        ; d0 <-- data to write
  437.             bsr        opdata                        ; write character to output buffer
  438.  
  439. endloop:    tst.w    d5
  440.             beq.s    parse_succeed
  441.  
  442.             bra        loop1                        ; next character
  443.  
  444. ;---------- finish up simple ops
  445.  
  446. std_patch:    bsr        opheader                    ; reserve space for op header
  447.             bsr        patch_zeroop                ; patch op with no data field
  448.             moveq    #1,d3                        ; IsWild = 1 (wildcards present)
  449.             tst.w    d5                            ; if ALL is true
  450.             bne.s    loop1                        ; get next character
  451.  
  452. ;---------- return success
  453.  
  454. parse_succeed:
  455.             move.l    (sp)+,a5                    ; restore starting point
  456.             moveq    #-1,d0                        ; return failure code
  457.             rts                                    ; return
  458.  
  459. ;---------- return failure
  460.  
  461. parse_fail:    move.l    (sp)+,a5                    ; restore starting point
  462.             moveq    #0,d0                        ; return success code
  463.             rts                                    ; return
  464.  
  465. ; register usage
  466. ; d0 - scratch
  467. ; d1 - current opcode
  468. ; d2 - length of op
  469. ; d4 - stack depth limit
  470. ; d5 - incomplete flag
  471.  
  472. ; a0 - scratch
  473. ; a2 - name
  474. ; a3 - pattern
  475. ; a4 - pattern end
  476.  
  477.             xdef    _PatternMatch,PatternMatch
  478.  
  479. pmreg        reg        d2-d5/a2-a4
  480.  
  481. _PatternMatch:            ; (pat, name)
  482.             movem.l    pmreg,-(sp)                    ; save regs
  483.             move.l    28+4(sp),a3                    ; get pat
  484.             move.l    28+8(sp),a2                    ; get name
  485.             bra.s    pm1                            ; go to C entry point
  486. PatternMatch:            ; (pat: a3, name:a2)
  487.             movem.l    pmreg,-(sp)                    ; save regs
  488. pm1:        move.l    sp,d4                        ; d4 <-- stack pointer
  489.             sub.l    #1200,d4                    ; d4 <-- lower limit of stack
  490.             moveq    #0,d5                        ; set incomplete to FALSE
  491.             move.l    a3,a4                        ; a4 <-- pat
  492.             add.l    #1000,a4                    ; a4 <-- pat end (lots for now)
  493.             bsr        interpret_pattern            ; call recursive match routine
  494.             movem.l    (sp)+,pmreg                    ; restore registers
  495.             rts
  496.  
  497. * int interpret_pattern(char *pat,int plength,int incomplete_ok)
  498. *{    char                *save = name,
  499. *                        *save2;
  500.  
  501. interpret_pattern:
  502.             movem.l    a3,-(sp)                    ; save pattern address on stack
  503.             movem.l    a2,-(sp)                    ; save name address on stack
  504.  
  505.             cmp.l    sp,d4                        ; compare stack ptr to stack limit
  506.             bhs        match_fail                    ; if d4 is higher, then stack too deep
  507.  
  508. *    if (plength == 0) return (*name == '\0');
  509.  
  510.             cmp.l    a3,a4                        ; if we're at end of pattern
  511.             bhi.s    loop2                        ; then
  512.             tst.b    (a2)                        ; if no more characters
  513.             beq        match_succeed                ; then we succeeded
  514.             bra        match_fail                    ; else we failed
  515.  
  516. *    while (plength > 0)
  517.  
  518. loop2:        cmp.l    a3,a4                        ; while there's pattern left
  519.             bls        match_succeed
  520.  
  521. *    {    WORD            length,
  522. *                        code;
  523. *        code = *pat & 0xf0;
  524. *        length = ((pat[0] & 0x0f)<<8) + pat[1];
  525. *        plength -= 2;
  526. *        pat += 2;
  527.     
  528.             move.b    (a3)+,d1                    ; get code byte
  529.             move.b    d1,d2                        ; move to length
  530.             and.w    #$f,d2                        ; extract length
  531.             lsl.w    #8,d2                        ; times 256
  532.             move.b    (a3)+,d2                    ; get lower byte of length
  533.  
  534. *        switch (code) {
  535.  
  536.             lea        jump_table(pc),a0
  537.             lsr.w    #2,d1
  538.             and.w    #$003c,d1
  539.             move.l    (a0,d1.w),a0
  540.             jmp        (a0)
  541.  
  542. jump_table:    dc.l    match_eos                    ; 0x00
  543.             dc.l    match_null                    ; 0x10
  544.             dc.l    match_not                    ; 0x20
  545.             dc.l    match_wild                    ; 0x30
  546.             dc.l    match_pound                    ; 0x40
  547.             dc.l    match_class                    ; 0x50
  548.             dc.l    match_nclass                ; 0x60
  549.             dc.l    match_string                ; 0x70
  550.             dc.l    match_choice                ; 0x80
  551.             dc.l    match_skip                    ; 0x90
  552.             dc.l    match_error                    ; 0xA0
  553.             dc.l    match_error                    ; 0xB0
  554.             dc.l    match_error                    ; 0xC0
  555.             dc.l    match_error                    ; 0xD0
  556.             dc.l    match_error                    ; 0xE0
  557.             dc.l    match_error                    ; 0xF0
  558.  
  559. *        case PMATCH_WILD:
  560. *            if (*name == '\0') goto fail;
  561. *            name++;
  562. *            break;
  563.  
  564. match_wild:
  565.             tst.b    (a2)+                        ; can't wildcard end of string
  566.             beq        match_fail                    ; so that fails
  567.             bra        loop2                        ; else it succeeds
  568.  
  569. *        case PMATCH_NULL:
  570. *            break;
  571.  
  572. match_null:    bra        loop2                        ; do nothing at all
  573.  
  574. *        case PMATCH_EOS:
  575. *            if (incomplete_ok || *name == '\0') return TRUE;
  576. *            goto fail;
  577.  
  578. match_eos:    tst.w    d5                            ; if incomplete is OK
  579.             bne        match_succeed                ; then we succeed
  580.             tst.b    (a2)                        ; if end of string
  581.             beq        match_succeed                ; then we succeed
  582.             bra        match_fail                    ; else we fail
  583.  
  584. *        case PMATCH_NOT:
  585. *            if (interpret_pattern(pat,plength,incomplete_ok) && *name == '\0') goto fail;
  586. *            return TRUE;
  587. *            break;
  588.  
  589. match_not:    bsr        interpret_pattern            ; call interpret_pattern
  590.             beq        match_succeed                ; if test failed, then it succeeded
  591.             tst.b    (a2)                        ; if not end of string
  592.             bne        match_succeed                ; then test also failed, but succeeded
  593.             bra        match_fail                    ; else we fail for real
  594.  
  595. *        case PMATCH_SKIP:
  596. *            pat += length;
  597. *            break;
  598.  
  599. match_skip:    add.w    d2,a3                        ; add length to pattern
  600.             bra        loop2                        ; do next char
  601.  
  602. *        case PMATCH_CHOICE:
  603. *            save2 = name;
  604. *            if (interpret_pattern(pat,length + plength + 2,incomplete_ok)) return TRUE;
  605. *            name = save2;
  606. *            pat += length;
  607. *            break;
  608.  
  609. match_choice:
  610.             add.w    d2,a3                        ; add length of op to pat
  611.             move.l    a3,-(sp)                    ; save next op addr on stack
  612.             sub.w    d2,a3                        ; restore address to this op
  613.             bsr        interpret_pattern            ; call interpret
  614.             bne.s    10$                            ; if succeeded, then ok
  615.             move.l    (sp)+,a3                    ; restore next op addr from stack
  616.             bra        loop2                        ; do next op
  617.  
  618. 10$            addq    #4,sp                        ; don't restore op addr from stack
  619.             bra        match_succeed                ; and succeed
  620.  
  621. *        case PMATCH_NCLASS:
  622. *        case PMATCH_CLASS:
  623. *            plength -= length;
  624. *            while (length--)
  625. *            {    if (length > 1 && pat[1] == '-')
  626. *                {    if (ToEnglish(*name) >= pat[0] &&
  627. *                        ToEnglish(*name) <= pat[2])
  628. *                            break;
  629. *                    else { pat += 3; length -= 2; }
  630. *                }
  631. *                else
  632. *                {    if (*pat == ToEnglish(*name)) break;
  633. *                    pat++;
  634. *                }
  635. *            }
  636. *            pat += length + 1;
  637. *            if (code == PMATCH_NCLASS)
  638. *            {    if (length >= 0) goto fail;
  639. *            }
  640. *            else
  641. *            {    if (length < 0) goto fail;
  642. *            }
  643. *            name++;
  644.  
  645. match_class:
  646. match_nclass:
  647.             move.b    (a2),d0                        ; get character in question
  648.             jsr        ToEnglish                    ; convert to UC english
  649.  
  650.             move.l    a3,a1                        ; a1 <-- pattern
  651.             add.w    d2,a1                        ; a1 <-- next opcode (pattern + length)
  652.  
  653. 20$            tst.w    d2                            ; check length
  654.             beq.s    70$                            ; if length is zero
  655.             bmi.s    70$                            ; or negative
  656.  
  657.             cmp.w    #1,d2                        ; if enough room for a range
  658.             bls.s    50$                            ; then see if there's a dash
  659.             cmp.b    #'-',1(a3)                    ; if it's a dash
  660.             bne.s    50$                            ; then check if character in range
  661.  
  662.             cmp.b    0(a3),d0                    ; compare with first part of class
  663.             blo.s    45$                            ; if lower, then not in range
  664.             cmp.b    2(a3),d0                    ; compare with 2nd part of class
  665.             bls.s    80$                            ; if lower or same, then in class
  666.  
  667. 45$            addq    #3,a3                        ; skip range definition
  668.             subq    #3,d2                        ; subtract 3 from length
  669.             bra.s    20$                            ; check next member of class
  670.  
  671. 50$            cmp.b    (a3),d0                        ; compare name byte with class byte
  672.             beq.s    80$                            ; if match, then go to "in class"
  673.  
  674. 55$            addq    #1,a3                        ; next class character
  675.             subq    #1,d2                        ; subtract 1 from length
  676.             bra.s    20$                            ; check next member of class
  677.  
  678. ;---------- code to execute if character not in class
  679.  
  680. 70$            cmp.b    #PMATCH_CLASS/4,d1            ; if it's match class
  681.             beq.s    match_fail
  682.             addq    #1,a2                        ; add 1 to name
  683.             move.l    a1,a3                        ; next opode
  684.             bra        loop2
  685.  
  686. ;---------- code to execute if character in class
  687.  
  688. 80$            cmp.b    #PMATCH_NCLASS/4,d1            ; if it's match nclass
  689.             beq.s    match_fail
  690.             addq    #1,a2                        ; add 1 to name
  691.             move.l    a1,a3                        ; next opode
  692.             bra        loop2
  693.  
  694. *            break;
  695. *        case PMATCH_POUND:
  696. *            for (;;)
  697. *            {    if (interpret_pattern(pat+length,plength-length,incomplete_ok)) return TRUE;
  698. *                else if (!interpret_pattern(pat,length,TRUE)) goto fail;
  699. *            }
  700.  
  701. match_pound:
  702.             move.w    d2,-(sp)                    ; save length on stack
  703.             add.w    d2,a3                        ; add op length to pat, giving op end
  704.             bsr        interpret_pattern            ; interpret the pattern after this op
  705.             bne.s    10$                            ; if succeed, then return true
  706.             move.w    (sp),d2                        ; get length of op again from stack
  707.             movem.l    d5/a4,-(sp)                    ; save pattern end and incomplete flg.
  708.             move.l    a3,a4                        ; pattern end <-- pattern + pength
  709.             sub.w    d2,a3                        ; pat <-- original pat
  710.             moveq    #-1,d5                        ; set incomplete_ok to TRUE
  711.             bsr        interpret_pattern            ; interpret op contents
  712.             beq.s    20$                            ; if no match then fail
  713.             movem.l    (sp)+,d5/a4                    ; restore pattern end and incmplt.
  714.             move.w    (sp)+,d2                    ; restore length from stack
  715.             bra.s    match_pound                    ; try another match.
  716.  
  717. 10$            addq    #2,sp                        ; clean up stack
  718.             bra        match_succeed                ; and succeed
  719.  
  720. 20$            lea        10(sp),sp                    ; clean up stack
  721.             bra        match_fail                    ; and fail
  722.  
  723. *        case PMATCH_STRING:
  724. *            if (ToEnglish(*name++) != (length & 0x0ff)) goto fail;
  725. *            break;
  726.  
  727. match_string:
  728.             move.b    (a2)+,d0                    ; get next character in name
  729.             jsr        ToEnglish                    ; convert to english upper case
  730.             cmp.b    d0,d2                        ; if not the same as pat
  731.             bne        match_fail                    ; fail
  732.             bra        loop2                        ; else next char
  733.  
  734. *        default:
  735. *            Printf("Interpreter error!\n");
  736. *            return FALSE;
  737.  
  738. match_error:
  739.             bra.s    match_fail                    ; just fail
  740.  
  741. *    return MATCH;
  742.  
  743. match_succeed:
  744.             addq    #4,sp                        ; don't restore name
  745.             move.l    (sp)+,a3                    ; restore pat address from stack
  746.             moveq    #-1,d0                        ; return success
  747.             rts
  748.  
  749.  
  750. *fail:
  751. *    name = save;
  752. *    return FALSE;
  753.  
  754. match_fail:
  755.             move.l    (sp)+,a2                    ; restore name address from stack
  756.             move.l    (sp)+,a3                    ; restore pat address from stack
  757.             moveq    #0,d0                        ; return failure
  758.             rts
  759.  
  760.