src/wild.c

Go to the documentation of this file.
00001 /*
00002  * wild.c - wildcard routines
00003  * *
00004  * * Written by T. Alexander Popiel, 24 June 1993
00005  * * Last modified by T. Alexander Popiel, 19 August 1993
00006  * *
00007  * * Thanks go to Andrew Molitor for debugging
00008  * * Thanks also go to Rich $alz for code to benchmark against
00009  * *
00010  * * Copyright (c) 1993 by T. Alexander Popiel
00011  * * This code is hereby placed under GNU copyleft,
00012  * * see copyright.h for details.
00013  * *
00014  */
00015 
00016 #include "copyright.h"
00017 #include "config.h"
00018 
00019 #include "config.h"
00020 #include "db.h"
00021 #include "mudconf.h"
00022 #include "externs.h"
00023 #include "alloc.h"
00024 
00025 #define FIXCASE(a) (ToLower(a))
00026 #define EQUAL(a,b) ((a == b) || (FIXCASE(a) == FIXCASE(b)))
00027 #define NOTEQUAL(a,b) ((a != b) && (FIXCASE(a) != FIXCASE(b)))
00028 
00029 static char **arglist;                  /* Argument return space */
00030 static int numargs;                             /* Argument return size  */
00031 
00036 int quick_wild(char *tstr, char *dstr)
00037 {
00038         while (*tstr != '*') {
00039                 switch (*tstr) {
00040                 case '?':
00041                         /*
00042                          * Single character match.  Return false if at * end
00043                          * * * * of data. 
00044                          */
00045                         if(!*dstr)
00046                                 return 0;
00047                         break;
00048                 case '\\':
00049                         /*
00050                          * Escape character.  Move up, and force literal * *
00051                          * * * match of next character. 
00052                          */
00053                         tstr++;
00054                         /*
00055                          * FALL THROUGH 
00056                          */
00057                 default:
00058                         /*
00059                          * Literal character.  Check for a match. * If * * *
00060                          * matching end of data, return true. 
00061                          */
00062                         if(NOTEQUAL(*dstr, *tstr))
00063                                 return 0;
00064                         if(!*dstr)
00065                                 return 1;
00066                 }
00067                 tstr++;
00068                 dstr++;
00069         }
00070 
00071         /*
00072          * Skip over '*'. 
00073          */
00074 
00075         tstr++;
00076 
00077         /*
00078          * Return true on trailing '*'. 
00079          */
00080 
00081         if(!*tstr)
00082                 return 1;
00083 
00084         /*
00085          * Skip over wildcards. 
00086          */
00087 
00088         while ((*tstr == '?') || (*tstr == '*')) {
00089                 if(*tstr == '?') {
00090                         if(!*dstr)
00091                                 return 0;
00092                         dstr++;
00093                 }
00094                 tstr++;
00095         }
00096 
00097         /*
00098          * Skip over a backslash in the pattern string if it is there. 
00099          */
00100 
00101         if(*tstr == '\\')
00102                 tstr++;
00103 
00104         /*
00105          * Return true on trailing '*'. 
00106          */
00107 
00108         if(!*tstr)
00109                 return 1;
00110 
00111         /*
00112          * Scan for possible matches. 
00113          */
00114 
00115         while (*dstr) {
00116                 if(EQUAL(*dstr, *tstr) && quick_wild(tstr + 1, dstr + 1))
00117                         return 1;
00118                 dstr++;
00119         }
00120         return 0;
00121 }
00122 
00132 int wild1(char *tstr, char *dstr, int arg)
00133 {
00134         char *datapos;
00135         int argpos, numextra;
00136 
00137         while (*tstr != '*') {
00138                 switch (*tstr) {
00139                 case '?':
00140                         /*
00141                          * Single character match.  Return false if at * end
00142                          * * * * of data. 
00143                          */
00144                         if(!*dstr)
00145                                 return 0;
00146                         arglist[arg][0] = *dstr;
00147                         arglist[arg][1] = '\0';
00148                         arg++;
00149 
00150                         /*
00151                          * Jump to the fast routine if we can. 
00152                          */
00153 
00154                         if(arg >= numargs)
00155                                 return quick_wild(tstr + 1, dstr + 1);
00156                         break;
00157                 case '\\':
00158                         /*
00159                          * Escape character.  Move up, and force literal * *
00160                          * * * match of next character. 
00161                          */
00162                         tstr++;
00163                         /*
00164                          * FALL THROUGH 
00165                          */
00166                 default:
00167                         /*
00168                          * Literal character.  Check for a match. * If * * *
00169                          * matching end of data, return true. 
00170                          */
00171                         if(NOTEQUAL(*dstr, *tstr))
00172                                 return 0;
00173                         if(!*dstr)
00174                                 return 1;
00175                 }
00176                 tstr++;
00177                 dstr++;
00178         }
00179 
00180         /*
00181          * If at end of pattern, slurp the rest, and leave. 
00182          */
00183 
00184         if(!tstr[1]) {
00185                 StringCopyTrunc(arglist[arg], dstr, LBUF_SIZE - 1);
00186                 arglist[arg][LBUF_SIZE - 1] = '\0';
00187                 return 1;
00188         }
00189         /*
00190          * Remember current position for filling in the '*' return. 
00191          */
00192 
00193         datapos = dstr;
00194         argpos = arg;
00195 
00196         /*
00197          * Scan forward until we find a non-wildcard. 
00198          */
00199 
00200         do {
00201                 if(argpos < arg) {
00202                         /*
00203                          * Fill in arguments if someone put another '*' * * * 
00204                          * 
00205                          * * before a fixed string. 
00206                          */
00207                         arglist[argpos][0] = '\0';
00208                         argpos++;
00209 
00210                         /*
00211                          * Jump to the fast routine if we can. 
00212                          */
00213 
00214                         if(argpos >= numargs)
00215                                 return quick_wild(tstr, dstr);
00216 
00217                         /*
00218                          * Fill in any intervening '?'s 
00219                          */
00220 
00221                         while (argpos < arg) {
00222                                 arglist[argpos][0] = *datapos;
00223                                 arglist[argpos][1] = '\0';
00224                                 datapos++;
00225                                 argpos++;
00226 
00227                                 /*
00228                                  * Jump to the fast routine if we can. 
00229                                  */
00230 
00231                                 if(argpos >= numargs)
00232                                         return quick_wild(tstr, dstr);
00233                         }
00234                 }
00235                 /*
00236                  * Skip over the '*' for now... 
00237                  */
00238 
00239                 tstr++;
00240                 arg++;
00241 
00242                 /*
00243                  * Skip over '?'s for now... 
00244                  */
00245 
00246                 numextra = 0;
00247                 while (*tstr == '?') {
00248                         if(!*dstr)
00249                                 return 0;
00250                         tstr++;
00251                         dstr++;
00252                         arg++;
00253                         numextra++;
00254                 }
00255         } while (*tstr == '*');
00256 
00257         /*
00258          * Skip over a backslash in the pattern string if it is there. 
00259          */
00260 
00261         if(*tstr == '\\')
00262                 tstr++;
00263 
00264         /*
00265          * Check for possible matches.  This loop terminates either at * end
00266          * * * * of data (resulting in failure), or at a successful match. 
00267          */
00268         while (1) {
00269 
00270                 /*
00271                  * Scan forward until first character matches. 
00272                  */
00273 
00274                 if(*tstr)
00275                         while (NOTEQUAL(*dstr, *tstr)) {
00276                                 if(!*dstr)
00277                                         return 0;
00278                                 dstr++;
00279                 } else
00280                         while (*dstr)
00281                                 dstr++;
00282 
00283                 /*
00284                  * The first character matches, now.  Check if the rest * * * 
00285                  * 
00286                  * * does, using the fastest method, as usual. 
00287                  */
00288                 if(!*dstr || ((arg < numargs) ? wild1(tstr + 1, dstr + 1, arg)
00289                                           : quick_wild(tstr + 1, dstr + 1))) {
00290 
00291                         /*
00292                          * Found a match!  Fill in all remaining arguments. * 
00293                          * 
00294                          * *  * *  * * First do the '*'... 
00295                          */
00296                         StringCopyTrunc(arglist[argpos], datapos,
00297                                                         (dstr - datapos) - numextra);
00298                         arglist[argpos][(dstr - datapos) - numextra] = '\0';
00299                         datapos = dstr - numextra;
00300                         argpos++;
00301 
00302                         /*
00303                          * Fill in any trailing '?'s that are left. 
00304                          */
00305 
00306                         while (numextra) {
00307                                 if(argpos >= numargs)
00308                                         return 1;
00309                                 arglist[argpos][0] = *datapos;
00310                                 arglist[argpos][1] = '\0';
00311                                 datapos++;
00312                                 argpos++;
00313                                 numextra--;
00314                         }
00315 
00316                         /*
00317                          * It's done! 
00318                          */
00319 
00320                         return 1;
00321                 } else {
00322                         dstr++;
00323                 }
00324         }
00325 }
00326 
00337 int wild(char *tstr, char *dstr, char *args[], int nargs)
00338 {
00339         int i, value;
00340         char *scan;
00341 
00342         /*
00343          * Initialize the return array. 
00344          */
00345 
00346         for(i = 0; i < nargs; i++)
00347                 args[i] = NULL;
00348 
00349         /*
00350          * Do fast match. 
00351          */
00352 
00353         while ((*tstr != '*') && (*tstr != '?')) {
00354                 if(*tstr == '\\')
00355                         tstr++;
00356                 if(NOTEQUAL(*dstr, *tstr))
00357                         return 0;
00358                 if(!*dstr)
00359                         return 1;
00360                 tstr++;
00361                 dstr++;
00362         }
00363 
00364         /*
00365          * Allocate space for the return args. 
00366          */
00367 
00368         i = 0;
00369         scan = tstr;
00370         while (*scan && (i < nargs)) {
00371                 switch (*scan) {
00372                 case '?':
00373                         args[i] = alloc_lbuf("wild.?");
00374             memset(args[i], 0, LBUF_SIZE);
00375                         i++;
00376                         break;
00377                 case '*':
00378                         args[i] = alloc_lbuf("wild.*");
00379             memset(args[i], 0, LBUF_SIZE);
00380                         i++;
00381                 }
00382                 scan++;
00383         }
00384 
00385         /*
00386          * Put stuff in globals for quick recursion. 
00387          */
00388 
00389         arglist = args;
00390         numargs = nargs;
00391 
00392         /*
00393          * Do the match. 
00394          */
00395 
00396         value = nargs ? wild1(tstr, dstr, 0) : quick_wild(tstr, dstr);
00397 
00398         /*
00399          * Clean out any fake match data left by wild1. 
00400          */
00401 
00402         for(i = 0; i < nargs; i++)
00403                 if((args[i] != NULL) && (!*args[i] || !value)) {
00404                         free_lbuf(args[i]);
00405                         args[i] = NULL;
00406                 }
00407         return value;
00408 }
00409 
00416 int wild_match(char *tstr, char *dstr)
00417 {
00418         switch (*tstr) {
00419         case '>':
00420                 tstr++;
00421                 if(isdigit(*tstr) || (*tstr == '-'))
00422                         return (atoi(tstr) < atoi(dstr));
00423                 else
00424                         return (strcmp(tstr, dstr) < 0);
00425         case '<':
00426                 tstr++;
00427                 if(isdigit(*tstr) || (*tstr == '-'))
00428                         return (atoi(tstr) > atoi(dstr));
00429                 else
00430                         return (strcmp(tstr, dstr) > 0);
00431         }
00432 
00433         return quick_wild(tstr, dstr);
00434 }

Generated on Mon May 28 04:25:26 2007 for BattletechMUX by  doxygen 1.4.7