home *** CD-ROM | disk | FTP | other *** search
/ Aminet 18 / aminetcdnumber181997.iso / Aminet / misc / emu / AROSdev.lha / AROS / rom / dos / matchpattern.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-27  |  8.9 KB  |  319 lines

  1. /*
  2.     (C) 1995-96 AROS - The Amiga Replacement OS
  3.     $Id: matchpattern.c,v 1.4 1997/01/27 00:36:25 ldp Exp $
  4.     $Log: matchpattern.c,v $
  5.     Revision 1.4  1997/01/27 00:36:25  ldp
  6.     Polish
  7.  
  8.     Revision 1.3  1996/12/09 13:53:34  aros
  9.     Added empty templates for all missing functions
  10.  
  11.     Moved #include's into first column
  12.  
  13.     Revision 1.2  1996/10/24 15:50:32  aros
  14.     Use the official AROS macros over the __AROS versions.
  15.  
  16.     Revision 1.1  1996/09/11 12:54:46  digulla
  17.     A couple of new DOS functions from M. Fleischer
  18.  
  19.     Desc:
  20.     Lang: english
  21. */
  22. #include <exec/memory.h>
  23. #include <proto/exec.h>
  24. #include <dos/dosextens.h>
  25. #include "dos_intern.h"
  26.  
  27. /*****************************************************************************
  28.  
  29.     NAME */
  30. #include <proto/dos.h>
  31.  
  32.     AROS_LH2(BOOL, MatchPattern,
  33.  
  34. /*  SYNOPSIS */
  35.     AROS_LHA(STRPTR, pat, D1),
  36.     AROS_LHA(STRPTR, str, D2),
  37.  
  38. /*  LOCATION */
  39.     struct DosLibrary *, DOSBase, 141, Dos)
  40.  
  41. /*  FUNCTION
  42.  
  43.     INPUTS
  44.  
  45.     RESULT
  46.  
  47.     NOTES
  48.  
  49.     EXAMPLE
  50.  
  51.     BUGS
  52.  
  53.     SEE ALSO
  54.  
  55.     INTERNALS
  56.  
  57.     HISTORY
  58.     29-10-95    digulla automatically created from
  59.                 dos_lib.fd and clib/dos_protos.h
  60.  
  61. *****************************************************************************/
  62. {
  63.     AROS_LIBFUNC_INIT
  64.     AROS_LIBBASE_EXT_DECL(struct DosLibrary *,DOSBase)
  65.  
  66.     /*
  67.         A simple method for pattern matching with multiple wildcards:
  68.         I use markers that consist of both a pointer into the string
  69.         and one into the pattern. The marker simply follows the string
  70.         and everytime it hits a wildcard it's split into two new markers
  71.         (one to assume that the wildcard match has ended and one to assume
  72.          that it continues). If a marker doesn't fit any longer it's
  73.         removed and if all of them are gone the pattern mismatches.
  74.         OTOH if any of the markers reaches the end of both the string
  75.         and the pattern simultaneously the pattern matches the string.
  76.     */
  77.     STRPTR s;
  78.     LONG match=0;
  79.     struct markerarray ma, *macur=&ma, *cur2;
  80.     LONG macnt=0, cnt2;
  81.     ULONG level;
  82.     UBYTE a, b, c, t;
  83.     LONG error;
  84. #define ERROR(a) { error=(a); goto end; }
  85.  
  86.     ma.next=ma.prev=NULL;
  87.     for(;;)
  88.         switch(*pat)
  89.         {
  90.             case MP_MULT: /* _#(_a) */
  91.                 /* Split the marker */
  92.                 PUSH(0,++pat,str);
  93.                 level=1;
  94.                 for(;;)
  95.                 {
  96.                     c=*pat++;
  97.                     if(c==MP_MULT)
  98.                         level++;
  99.                     else if(c==MP_MULT_END)
  100.                         if(!--level)
  101.                             break;
  102.                 }
  103.                 break;
  104.             case MP_MULT_END: /* #(a_)_ */
  105.                 /* Go back to the start of the block */
  106.                 level=1;
  107.                 for(;;)
  108.                 {
  109.                     c=*--pat;
  110.                     if(c==MP_MULT_END)
  111.                         level++;
  112.                     else if(c==MP_MULT)
  113.                         if(!--level)
  114.                             break;
  115.                 }
  116.                 break;
  117.             case MP_NOT: /* _~(_a) */
  118.                 s=++pat;
  119.                 level=1;
  120.                 for(;;)
  121.                 {
  122.                     c=*s++;
  123.                     if(c==MP_NOT)
  124.                         level++;
  125.                     else if(c==MP_NOT_END)
  126.                         if(!--level)
  127.                             break;
  128.                 }
  129.                 PUSH(1,s,str);
  130.                 break;
  131.             case MP_NOT_END: /* ~(a_)_ */
  132.                 cnt2=macnt;
  133.                 cur2=macur;
  134.                 do
  135.                 {
  136.                     cnt2--;
  137.                     if(cnt2<0)
  138.                     {
  139.                         cnt2=127;
  140.                         cur2=cur2->prev;
  141.                     }
  142.                 }while(!cur2->marker[cnt2].type);
  143.                 if(!*str++)
  144.                 {
  145.                     macnt=cnt2;
  146.                     macur=cur2;
  147.                 }else
  148.                     if(str>cur2->marker[cnt2].str)
  149.                         cur2->marker[cnt2].str=str;
  150.                 POP(t,pat,str);
  151.                 if(t&&*str)
  152.                 { PUSH(1,pat,str+1); }
  153.                 break;
  154.             case MP_OR: /* ( */
  155.                 s=++pat;
  156.                 level=1;
  157.                 for(;;)
  158.                 {
  159.                     c=*s++;
  160.                     if(c==MP_OR)
  161.                         level++;
  162.                     else if(c==MP_OR_NEXT)
  163.                     {
  164.                         if(level==1)
  165.                         { PUSH(0,s,str); }
  166.                     }else if(c==MP_OR_END)
  167.                         if(!--level)
  168.                             break;
  169.                 }
  170.                 break;
  171.             case MP_OR_NEXT: /* | */
  172.                 pat++;
  173.                 level=1;
  174.                 for(;;)
  175.                 {
  176.                     c=*pat++;
  177.                     if(c==MP_OR)
  178.                         level++;
  179.                     else if(c==MP_OR_END)
  180.                         if(!--level)
  181.                             break;
  182.                 }
  183.                 break;
  184.             case MP_OR_END: /* ) */
  185.                 pat++;
  186.                 break;
  187.             case MP_SINGLE: /* ? */
  188.                 pat++;
  189.                 if(*str)
  190.                     str++;
  191.                 else
  192.                 {
  193.                     POP(t,pat,str);
  194.                     if(t&&*str)
  195.                     { PUSH(1,pat,str+1); }
  196.                 }
  197.                 break;
  198.             case MP_SET: /* [ */
  199.                 pat++;
  200.                 for(;;)
  201.                 {
  202.                     a=b=*pat++;
  203.                     if(a==MP_SET_END)
  204.                     {
  205.                         POP(t,pat,str);
  206.                         if(t&&*str)
  207.                         { PUSH(1,pat,str+1); }
  208.                         break;
  209.                     }
  210.                     if(a==MP_ESCAPE)
  211.                         a=b=*pat++ +0x80;
  212.                     else if(a==MP_DASH)
  213.                     {
  214.                         a=*pat++;
  215.                         if(a==MP_ESCAPE)
  216.                             a=*pat++ +0x80;
  217.                         b=*pat++;
  218.                         if(b==MP_ESCAPE)
  219.                             b=*pat++ +0x80;
  220.                     }
  221.                     if(*str>=a&&*str<=b)
  222.                     {
  223.                         str++;
  224.                         while(*pat++!=MP_SET_END)
  225.                             ;
  226.                         break;
  227.                     }
  228.                 }
  229.                 break;
  230.             case MP_NOT_SET: /* [~ */
  231.                 if(!*str)
  232.                 {
  233.                     POP(t,pat,str);
  234.                     if(t&&*str)
  235.                     { PUSH(1,pat,str+1); }
  236.                     break;
  237.                 }
  238.                 pat++;
  239.                 for(;;)
  240.                 {
  241.                     a=b=*pat++;
  242.                     if(a==MP_SET_END)
  243.                     {
  244.                         str++;
  245.                         break;
  246.                     }
  247.                     if(a==MP_ESCAPE)
  248.                         a=b=*pat++ +0x80;
  249.                     else if(a==MP_DASH)
  250.                     {
  251.                         a=*pat++;
  252.                         if(a==MP_ESCAPE)
  253.                             a=*pat++ +0x80;
  254.                         b=*pat++;
  255.                         if(b==MP_ESCAPE)
  256.                             b=*pat++ +0x80;
  257.                     }
  258.                     if(*str>=a&&*str<=b)
  259.                     {
  260.                         POP(t,pat,str);
  261.                         if(t&&*str)
  262.                         { PUSH(1,pat,str+1); }
  263.                         break;
  264.                     }
  265.                 }
  266.                 break;
  267.             case MP_ALL: /* #? */
  268.                 /* This often used pattern has extra treatment to be faster */
  269.                 if(*str)
  270.                 { PUSH(0,pat,str+1); }
  271.                 pat++;
  272.                 break;
  273.             case 0:
  274.                 if(!*str)
  275.                 {
  276.                     match=1;
  277.                     ERROR(0);
  278.                 }else
  279.                 {
  280.                     POP(t,pat,str);
  281.                     if(t&&*str)
  282.                     { PUSH(1,pat,str+1); }
  283.                 }
  284.                 break;
  285.             case MP_ESCAPE:
  286.                 pat++;
  287.                 if(0x80+*pat++==*str)
  288.                     str++;
  289.                 else
  290.                 {
  291.                     POP(t,pat,str);
  292.                     if(t&&*str)
  293.                     { PUSH(1,pat,str+1); }
  294.                 }
  295.                 break;
  296.             default:
  297.                 if(*pat++==*str)
  298.                     str++;
  299.                 else
  300.                 {
  301.                     POP(t,pat,str);
  302.                     if(t&&*str)
  303.                     { PUSH(1,pat,str+1); }
  304.                 }
  305.                 break;
  306.         }
  307. end:
  308.     macur=ma.next;
  309.     while(macur!=NULL)
  310.     {
  311.         struct markerarray *next=macur->next;
  312.         FreeMem(macur,sizeof(struct markerarray));
  313.         macur=next;
  314.     }
  315.     ((struct Process *)FindTask(NULL))->pr_Result2=error;
  316.     return match;
  317.     AROS_LIBFUNC_EXIT
  318. } /* MatchPattern */
  319.