home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1993 #2 / Image.iso / os2 / pmsw2.zip / CSOURCE / PMSW2 / MSKCHK.C < prev    next >
C/C++ Source or Header  |  1993-04-19  |  8KB  |  220 lines

  1. /*============================================================================
  2.   ┌──────────────────────────────────────────────────────────────────────┐
  3.   │ MSKCHK.C   (C) Copyright 1992 Bruce E. Högman.  All Rights Reserved. │
  4.   └──────────────────────────────────────────────────────────────────────┘
  5.   MSKCHK - Function to scan a given area for a match against a mask string
  6.   containing wild cards and constant characters.
  7.   This is an extension of the usual DOS wild-card filespec matching, as it
  8.   permits imbedded '*' and '?' and the mask is an arbitrary length.
  9.  
  10.   Input:  mask, mask_len, area, area_len, qmark, asterisk
  11.           'qmark' is single-wild-card char, 'asterisk' is 0 to n wild chars.
  12. ============================================================================*/
  13. #include <stddef.h>
  14. #include <stdio.h>
  15. #define ERROR  -1
  16. #define WARNING 4
  17. #define DONE   0x20 /* Whole mask is complete */
  18. #define MATCH  0x10 /* Whole mask is found/matched */
  19. #define FAIL   0x08 /* Whole mask is not found */
  20. #define FLTFND 0x04 /* Mask float substr found */
  21. #ifndef FALSE
  22. #define FALSE  0
  23. #endif
  24. #ifndef TRUE
  25. #define TRUE  ~FALSE
  26. #endif
  27.   unsigned long irc;
  28.   unsigned long iflg;
  29.   unsigned long iMaskOffset;
  30.   unsigned long iAreaOffset;
  31.   char *cMask;
  32.   unsigned long iMaskLen;
  33.   char *cArea;
  34.   unsigned long iAreaLen;
  35.   char *cQ;
  36.   char *cA;
  37.  
  38. /*=============
  39.   AString
  40.   Current mask character is "*" wild card.
  41.   (For "?" that appear after initial "*", process these.)
  42.   We must scan mask string for its terminator.
  43. =============*/
  44.   static void AString (void)
  45. { unsigned long ixMaskOffset,      /* ptr '*' 2 in      *XXX* */
  46.       iyMaskOffset;
  47.   unsigned long ixAreaOffset, iyAreaOffset;
  48.   unsigned long iMatchCount, iwMaskLen;
  49.   while (TRUE)                     /* Process '*' and '?' at start */
  50.   { if (iflg & DONE) break;
  51.  
  52.     if ((*cA != *(cMask+iMaskOffset))
  53.     &&  (*cQ != *(cMask+iMaskOffset))) break;
  54.  
  55.     while (*cA == *(cMask+iMaskOffset))
  56.     { iMaskOffset++;
  57.       if (iMaskOffset >= iMaskLen) { iflg |= DONE+MATCH; break;}
  58.     }
  59.     while (*cQ == *(cMask+iMaskOffset))
  60.     { if (iAreaOffset >= iAreaLen) { iflg |= DONE+FAIL; break;}
  61.       else iAreaOffset++;
  62.       if ((++iMaskOffset >= iMaskLen) && (iAreaOffset >= iAreaLen))
  63.       { iflg |= DONE+MATCH; break;}
  64.     }
  65.   }
  66.   if (iflg & DONE) return;
  67.  
  68.     /* Look for mask string terminator. */
  69.     /* if no  terminator:  mask ends:    '*' marks suffix */
  70.     /* if '*' terminator:  mask float:   process floating mask */
  71.  
  72.   ixMaskOffset=iMaskOffset;
  73.   while (++ixMaskOffset < iMaskLen)
  74.   { if (*cA == *(cMask+ixMaskOffset)) break;}
  75.   if (ixMaskOffset >= iMaskLen)         /* Mask is suffix */
  76.   { iyMaskOffset = ixMaskOffset-1;      /* ptr last char in mask */
  77.     iyAreaOffset = iAreaLen - 1;        /* ptr last char in area */
  78.     while (TRUE)
  79.     { if (iflg & DONE) break;
  80.       if (iyMaskOffset < iMaskOffset) iflg |= DONE+MATCH;
  81.       else
  82.       { if (iyAreaOffset < iAreaOffset) iflg |= DONE+FAIL;
  83.         else
  84.         { if (*(cMask+iyMaskOffset) != *(cArea+iyAreaOffset))
  85.           { if (*(cMask+iyMaskOffset) == *cQ)
  86.             {iyMaskOffset--; iyAreaOffset--;}
  87.             else iflg |= DONE+FAIL;
  88.           }
  89.         }
  90.       }
  91.       iyMaskOffset--; iyAreaOffset--;
  92.     }
  93.     goto AStringReturn;                 /* return from AString */
  94.   }
  95.  
  96.   /* We have case of imbedded *xxx* mask string */
  97.  
  98.   iwMaskLen=ixMaskOffset-iMaskOffset;   /* length of *xxx* string or zero */
  99.   ixAreaOffset=iAreaOffset;             /* save ptr area */
  100.   iMatchCount=0;                        /* count of matched chars */
  101.   while (ixAreaOffset < iAreaLen)       /* stop at end of area if not sooner */
  102.   { if (iwMaskLen <= 0) break;          /* no-op loop if length is zero */
  103.     if (iMatchCount > 0) break;         /* stop loop if here and not zero */
  104.     iyAreaOffset = ixAreaOffset;
  105.     iyMaskOffset = iMaskOffset;
  106.     while (iyMaskOffset < ixMaskOffset)
  107.     { if (iMatchCount >= iwMaskLen) break; /* stop if matches >= mask length */
  108.       if (*(cMask+iyMaskOffset) == *(cArea+iyAreaOffset))
  109.       { iyMaskOffset++; iyAreaOffset++; iMatchCount++; }
  110.       else
  111.       { if (*(cMask+iyMaskOffset) == *cQ)
  112.         { iMatchCount++; iyAreaOffset++; iyMaskOffset++; }
  113.         else { iMatchCount = 0; break; }
  114.       }
  115.     }
  116.     if (iMatchCount < iwMaskLen) iMatchCount = 0;
  117.     ixAreaOffset++;
  118.   }
  119.   if ((iMatchCount >= iwMaskLen) && (iwMaskLen > 0))
  120.   { iflg |= FLTFND;
  121.     iMaskOffset = ixMaskOffset; iAreaOffset = iyAreaOffset;
  122.     if (iMaskOffset >= iMaskLen) iflg |= DONE+MATCH;
  123.   }
  124. AStringReturn:
  125.   return;
  126. }
  127. /*=============
  128.   PrefixString
  129. =============*/
  130.   static void PrefixString (void)
  131. { unsigned long ipMaskOffset;
  132.   ipMaskOffset = iMaskOffset;
  133.   while (++ipMaskOffset < iMaskLen)
  134.   { if (*cA == *(cMask+ipMaskOffset)) break;}
  135.   if (ipMaskOffset > iAreaLen) { iflg |= DONE+FAIL; return;}
  136.   while (TRUE)
  137.   { if (iflg & DONE) break;
  138.     if (*cA == *(cMask+iMaskOffset)) break;
  139.     if (iAreaOffset >= iAreaLen)
  140.     { if (iMaskOffset >= iMaskLen) iflg |= DONE+MATCH; break;}
  141.     if (iMaskOffset >= iMaskLen)
  142.     { if (iAreaOffset >= iAreaLen) iflg |= DONE+MATCH;
  143.       else iflg |= DONE+FAIL; break;
  144.     }
  145.     if (*(cMask+iMaskOffset) != *(cArea+iAreaOffset))
  146.     { if (*cA != *(cMask+iMaskOffset))
  147.       { iflg |= DONE+FAIL; break;}
  148.     }
  149.     iMaskOffset++; iAreaOffset++;
  150.   }
  151.   return;
  152. }
  153.  
  154.  
  155. /*=============
  156.   mskchk
  157. =============*/
  158.  
  159.   unsigned long mskchk ( char *msk,     /* ptr mask string   */
  160.                 unsigned long msklen,   /* length of mask    */
  161.                char *achk,              /* ptr area string   */
  162.                unsigned long alen,      /* length of area    */
  163.                char *q,                 /* ptr qmark char    */
  164.                char *a )                /* ptr asterisk char */
  165.  
  166. { cMask=msk; iMaskLen=msklen; cArea=achk; iAreaLen=alen; cQ=q; cA=a;
  167.   irc=0; iflg=0; iMaskOffset=0; iAreaOffset = 0;
  168.   if (msk==NULL||achk==NULL||q==NULL||a==NULL||msklen<=0||alen<=0)
  169.   { return ERROR;}                      /* Error if null argument(s) */
  170.  
  171.   while (*(cArea+iAreaOffset) == ' ')   /* Scan for 1st non-blank */
  172.   { iAreaOffset++; if (iAreaOffset >= iAreaLen) return WARNING;}
  173.     /* Scan for last non-blank and non-null */
  174.   while (*(cArea+iAreaLen-1) == ' ' || *(cArea+iAreaLen-1) == '\0')
  175.   { iAreaLen--; if (iAreaLen <= iAreaOffset) return ERROR;}
  176.  
  177.   while (!(iflg & DONE))
  178.   { if (iMaskOffset >= iMaskLen) break;
  179.     while (*cQ == *(cMask+iMaskOffset)) /* while '?' in mask */
  180.     { if (iflg & DONE) break;
  181.       iMaskOffset++; iAreaOffset++;
  182.       if (iAreaOffset >= iAreaLen)          /* if area is exhausted */
  183.       { if (iMaskOffset >= iMaskLen)        /* and mask is exhausted */
  184.         { iflg |= DONE+MATCH;}               /* we're done and matched */
  185.         else
  186.         { if ((iMaskOffset+1>=iMaskLen) && (*cA == *(cMask+iMaskOffset+1)))
  187.           { iflg |= DONE+MATCH;}            /* if the last mask char is ast */
  188.           else                              /* we're matched */
  189.           { iflg |= DONE+FAIL;}             /* otherwise failed */
  190.         } break;
  191.       }
  192.       if (iMaskOffset >= iMaskLen)
  193.       { iflg |= DONE;
  194.         if (iAreaOffset < iAreaLen)
  195.         { if (*cQ == *(cMask+iMaskOffset-1)) iflg |= FAIL; }
  196.         break;
  197.       }
  198.     }
  199.     if (iflg & DONE) break;
  200.     if (*cA == *(cMask+iMaskOffset))    /* start of float str */
  201.     { iMaskOffset++;
  202.       if (iMaskOffset >= iMaskLen)          /* if mask is exhausted */
  203.       { iflg |= DONE;
  204.         if (iAreaOffset < iAreaLen)         /* but area is not      */
  205.         { if (*cA==*(cMask+iMaskOffset-1))  /* but last mask char is asterisk */
  206.           { iflg |= MATCH;}
  207.         }
  208.         else  iflg |= MATCH;           /* area is complete */
  209.         break;
  210.       }
  211.       AString();
  212.     }
  213.     else PrefixString();
  214.   }
  215.   if (iflg & FAIL) irc = 8;
  216.   else irc = 0;
  217.   /* printf("MSKCHKRC=%i\n",irc); */
  218.   return irc;
  219. }
  220.