home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / lib / xp / xp_reg.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  8.2 KB  |  307 lines

  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. /* *
  20.  * 
  21.  *
  22.  * shexp.c: shell-like wildcard match routines
  23.  *
  24.  * See shexp.h for public documentation.
  25.  *
  26.  * Rob McCool
  27.  * 
  28.  */
  29.  
  30. #include "xp_reg.h"
  31. #include "xp.h"
  32.  
  33.  
  34. /* ----------------------------- shexp_valid ------------------------------ */
  35.  
  36.  
  37. PRIVATE int 
  38. _valid_subexp(char *exp, char stop) 
  39. {
  40.     register int x,y,t;
  41.     int nsc,np,tld;
  42.  
  43.     x=0;nsc=0;tld=0;
  44.  
  45.     while(exp[x] && (exp[x] != stop)) {
  46.         switch(exp[x]) {
  47.           case '~':
  48.             if(tld) return INVALID_SXP;
  49.             else ++tld;
  50.           case '*':
  51.           case '?':
  52.           case '^':
  53.           case '$':
  54.             ++nsc;
  55.             break;
  56.           case '[':
  57.             ++nsc;
  58.             if((!exp[++x]) || (exp[x] == ']'))
  59.                 return INVALID_SXP;
  60.             for(++x;exp[x] && (exp[x] != ']');++x)
  61.                 if(exp[x] == '\\')
  62.                     if(!exp[++x])
  63.                         return INVALID_SXP;
  64.             if(!exp[x])
  65.                 return INVALID_SXP;
  66.             break;
  67.           case '(':
  68.             ++nsc;np = 0;
  69.             while(1) {
  70.                 if(exp[++x] == ')')
  71.                     return INVALID_SXP;
  72.                 for(y=x;(exp[y]) && (exp[y] != '|') && (exp[y] != ')');++y)
  73.                     if(exp[y] == '\\')
  74.                         if(!exp[++y])
  75.                             return INVALID_SXP;
  76.                 if(!exp[y])
  77.                     return INVALID_SXP;
  78.                 if(exp[y] == '|')
  79.                     ++np;
  80.                 t = _valid_subexp(&exp[x],exp[y]);
  81.                 if(t == INVALID_SXP)
  82.                     return INVALID_SXP;
  83.                 x+=t;
  84.                 if(exp[x] == ')') {
  85.                     if(!np)
  86.                         return INVALID_SXP;
  87.                     break;
  88.                 }
  89.             }
  90.             break;
  91.           case ')':
  92.           case ']':
  93.             return INVALID_SXP;
  94.           case '\\':
  95.             if(!exp[++x])
  96.                 return INVALID_SXP;
  97.           default:
  98.             break;
  99.         }
  100.         ++x;
  101.     }
  102.     if((!stop) && (!nsc))
  103.         return NON_SXP;
  104.     return ((exp[x] == stop) ? x : INVALID_SXP);
  105. }
  106.  
  107. PUBLIC int 
  108. XP_RegExpValid(char *exp) 
  109. {
  110.     int x;
  111.  
  112.     x = _valid_subexp(exp, '\0');
  113.     return (x < 0 ? x : VALID_SXP);
  114. }
  115.  
  116.  
  117. /* ----------------------------- shexp_match ----------------------------- */
  118.  
  119.  
  120. #define MATCH 0
  121. #define NOMATCH 1
  122. #define ABORTED -1
  123.  
  124. PRIVATE int _shexp_match(char *str, char *exp, Bool case_insensitive);
  125.  
  126. PRIVATE int 
  127. _handle_union(char *str, char *exp, Bool case_insensitive) 
  128. {
  129.     char *e2 = (char *) XP_ALLOC(sizeof(char)*strlen(exp));
  130.     register int t,p2,p1 = 1;
  131.     int cp;
  132.  
  133.     while(1) {
  134.         for(cp=1;exp[cp] != ')';cp++)
  135.             if(exp[cp] == '\\')
  136.                 ++cp;
  137.         for(p2 = 0;(exp[p1] != '|') && (p1 != cp);p1++,p2++) {
  138.             if(exp[p1] == '\\')
  139.                 e2[p2++] = exp[p1++];
  140.             e2[p2] = exp[p1];
  141.         }
  142.         for (t=cp+1; ((e2[p2] = exp[t]) != 0); ++t,++p2) {}
  143.         if(_shexp_match(str,e2, case_insensitive) == MATCH) {
  144.             XP_FREE(e2);
  145.             return MATCH;
  146.         }
  147.         if(p1 == cp) {
  148.             XP_FREE(e2);
  149.             return NOMATCH;
  150.         }
  151.         else ++p1;
  152.     }
  153. }
  154.  
  155.  
  156. PRIVATE int 
  157. _shexp_match(char *str, char *exp, Bool case_insensitive) 
  158. {
  159.     register int x,y;
  160.     int ret,neg;
  161.  
  162.     ret = 0;
  163.     for(x=0,y=0;exp[y];++y,++x) {
  164.         if((!str[x]) && (exp[y] != '(') && (exp[y] != '$') && (exp[y] != '*'))
  165.             ret = ABORTED;
  166.         else {
  167.             switch(exp[y]) {
  168.               case '$':
  169.                 if( (str[x]) )
  170.                     ret = NOMATCH;
  171.                 else
  172.                     --x;             /* we don't want loop to increment x */
  173.                 break;
  174.               case '*':
  175.                 while(exp[++y] == '*'){}
  176.                 if(!exp[y])
  177.                     return MATCH;
  178.                 while(str[x]) {
  179.                     switch(_shexp_match(&str[x++],&exp[y], case_insensitive)) {
  180.                     case NOMATCH:
  181.                         continue;
  182.                     case ABORTED:
  183.                         ret = ABORTED;
  184.                         break;
  185.                     default:
  186.                         return MATCH;
  187.                     }
  188.                     break;
  189.                 }
  190.                 if((exp[y] == '$') && (exp[y+1] == '\0') && (!str[x]))
  191.                     return MATCH;
  192.                 else
  193.                     ret = ABORTED;
  194.                 break;
  195.               case '[':
  196.                   neg = ((exp[++y] == '^') && (exp[y+1] != ']'));
  197.                 if (neg)
  198.                     ++y;
  199.                 
  200.                 if ((isalnum(exp[y])) && (exp[y+1] == '-') && 
  201.                    (isalnum(exp[y+2])) && (exp[y+3] == ']'))
  202.                     {
  203.                         int start = exp[y], end = exp[y+2];
  204.                         
  205.                         /* Droolproofing for pinheads not included */
  206.                         if(neg ^ ((str[x] < start) || (str[x] > end))) {
  207.                             ret = NOMATCH;
  208.                             break;
  209.                         }
  210.                         y+=3;
  211.                     }
  212.                 else {
  213.                     int matched;
  214.                     
  215.                     for (matched=0;exp[y] != ']';y++)
  216.                         matched |= (str[x] == exp[y]);
  217.                     if (neg ^ (!matched))
  218.                         ret = NOMATCH;
  219.                 }
  220.                 break;
  221.               case '(':
  222.                 return _handle_union(&str[x],&exp[y], case_insensitive);
  223.                 break;
  224.               case '?':
  225.                 break;
  226.               case '\\':
  227.                 ++y;
  228.               default:
  229.                 if(case_insensitive)
  230.                   {
  231.                     if(toupper(str[x]) != toupper(exp[y]))
  232.                         ret = NOMATCH;
  233.                   }
  234.                 else
  235.                   {
  236.                     if(str[x] != exp[y])
  237.                         ret = NOMATCH;
  238.                   }
  239.                 break;
  240.             }
  241.         }
  242.         if(ret)
  243.             break;
  244.     }
  245.     return (ret ? ret : (str[x] ? NOMATCH : MATCH));
  246. }
  247.  
  248. PUBLIC int 
  249. XP_RegExpMatch(char *str, char *xp, Bool case_insensitive) {
  250.     register int x;
  251.     char *exp = 0;
  252.  
  253.     StrAllocCopy(exp, xp);
  254.  
  255.     if(!exp)
  256.         return 1;
  257.  
  258.     for(x=strlen(exp)-1;x;--x) {
  259.         if((exp[x] == '~') && (exp[x-1] != '\\')) {
  260.             exp[x] = '\0';
  261.             if(_shexp_match(str,&exp[++x], case_insensitive) == MATCH)
  262.                 goto punt;
  263.             break;
  264.         }
  265.     }
  266.     if(_shexp_match(str,exp, FALSE) == MATCH) {
  267.         XP_FREE(exp);
  268.         return 0;
  269.     }
  270.  
  271.   punt:
  272.     XP_FREE(exp);
  273.     return 1;
  274. }
  275.  
  276.  
  277. /* ------------------------------ shexp_cmp ------------------------------- */
  278.  
  279. PUBLIC int 
  280. XP_RegExpSearch(char *str, char *exp)
  281. {
  282.     switch(XP_RegExpValid(exp)) 
  283.       {
  284.         case INVALID_SXP:
  285.             return -1;
  286.         case NON_SXP:
  287.             return (strcmp(exp,str) ? 1 : 0);
  288.         default:
  289.             return XP_RegExpMatch(str, exp, FALSE);
  290.       }
  291. }
  292.  
  293. PUBLIC int
  294. XP_RegExpCaseSearch(char *str, char *exp)
  295. {
  296.     switch(XP_RegExpValid(exp))
  297.       {
  298.         case INVALID_SXP:
  299.             return -1;
  300.         case NON_SXP:
  301.             return (strcmp(exp,str) ? 1 : 0);
  302.         default:
  303.             return XP_RegExpMatch(str, exp, TRUE);
  304.       }
  305. }
  306.  
  307.