WizardsToolkit  1.0.7
token.c
Go to the documentation of this file.
00001 /*
00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00003 %                                                                             %
00004 %                                                                             %
00005 %                                                                             %
00006 %                    TTTTT   OOO   K   K  EEEEE  N   N                        %
00007 %                      T    O   O  K  K   E      NN  N                        %
00008 %                      T    O   O  KKK    EEE    N N N                        %
00009 %                      T    O   O  K  K   E      N  NN                        %
00010 %                      T     OOO   K   K  EEEEE  N   N                        %
00011 %                                                                             %
00012 %                                                                             %
00013 %                      Wizard's Toolkit Token Methods                         %
00014 %                                                                             %
00015 %                               Software Design                               %
00016 %                                 John Cristy                                 %
00017 %                                 March 2003                                  %
00018 %                                                                             %
00019 %                                                                             %
00020 %  Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization      %
00021 %  dedicated to making software imaging solutions freely available.           %
00022 %                                                                             %
00023 %  You may not use this file except in compliance with the License.  You may  %
00024 %  obtain a copy of the License at                                            %
00025 %                                                                             %
00026 %    http://www.wizards-toolkit.org/script/license.php                        %
00027 %                                                                             %
00028 %  Unless required by applicable law or agreed to in writing, software        %
00029 %  distributed under the License is distributed on an "AS IS" BASIS,          %
00030 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
00031 %  See the License for the specific language governing permissions and        %
00032 %  limitations under the License.                                             %
00033 %                                                                             %
00034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00035 %
00036 %
00037 %
00038 */
00039 
00040 /*
00041   Include declarations.
00042 */
00043 #include "wizard/studio.h"
00044 #include "wizard/exception.h"
00045 #include "wizard/exception-private.h"
00046 #include "wizard/locale_.h"
00047 #include "wizard/string_.h"
00048 #include "wizard/string-private.h"
00049 #include "wizard/token.h"
00050 #include "wizard/utility.h"
00051 
00052 /*
00053   Typedef declarations.
00054 */
00055 struct _TokenInfo
00056 {
00057   int
00058     state;
00059 
00060   WizardStatusType
00061     flag;
00062 
00063   ssize_t
00064     offset;
00065 
00066   char
00067     quote;
00068 };
00069 
00070 /*
00071 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00072 %                                                                             %
00073 %                                                                             %
00074 %                                                                             %
00075 +   G e t W i z a r d T o k e n                                               %
00076 %                                                                             %
00077 %                                                                             %
00078 %                                                                             %
00079 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00080 %
00081 %  GetWizardToken() gets a token from the token stream.  A token is defined as a
00082 %  sequence of characters delimited by whitespace (e.g. clip-path), a sequence
00083 %  delimited with quotes (.e.g "Quote me"), or a sequence enclosed in
00084 %  parenthesis (e.g. rgb(0,0,0)).
00085 %
00086 %  The format of the GetWizardToken method is:
00087 %
00088 %      void GetWizardToken(const char *start,const char **end,char *token)
00089 %
00090 %  A description of each parameter follows:
00091 %
00092 %    o start: the start of the token sequence.
00093 %
00094 %    o end: point to the end of the token sequence.
00095 %
00096 %    o token: copy the token to this buffer.
00097 %
00098 */
00099 WizardExport void GetWizardToken(const char *start,const char **end,char *token)
00100 {
00101   register const char
00102     *p;
00103 
00104   register ssize_t
00105     i;
00106 
00107   assert(start != (const char *) NULL);
00108   assert(token != (char *) NULL);
00109   i=0;
00110   for (p=start; *p != '\0'; )
00111   {
00112     while ((isspace((int) ((unsigned char) *p)) != 0) && (*p != '\0'))
00113       p++;
00114     if (*p == '\0')
00115       break;
00116     switch (*p)
00117     {
00118       case '"':
00119       case '\'':
00120       case '`':
00121       case '{':
00122       {
00123         register char
00124           escape;
00125 
00126         switch (*p)
00127         {
00128           case '"': escape='"'; break;
00129           case '\'': escape='\''; break;
00130           case '`': escape='\''; break;
00131           case '{': escape='}'; break;
00132           default: escape=(*p); break;
00133         }
00134         for (p++; *p != '\0'; p++)
00135         {
00136           if ((*p == '\\') && ((*(p+1) == escape) || (*(p+1) == '\\')))
00137             p++;
00138           else
00139             if (*p == escape)
00140               {
00141                 p++;
00142                 break;
00143               }
00144           token[i++]=(*p);
00145         }
00146         break;
00147       }
00148       case '/':
00149       {
00150         token[i++]=(*p++);
00151         if ((*p == '>') || (*p == '/'))
00152           token[i++]=(*p++);
00153         break;
00154       }
00155       default:
00156       {
00157         char
00158           *q;
00159 
00160         double
00161           value;
00162 
00163         value=StringToDouble(p,&q);
00164         (void) value;
00165         if ((p != q) && (*p != ','))
00166           {
00167             for ( ; (p < q) && (*p != ','); p++)
00168               token[i++]=(*p);
00169             if (*p == '%')
00170               token[i++]=(*p++);
00171             break;
00172           }
00173         if ((*p != '\0') && (isalpha((int) ((unsigned char) *p)) == 0) &&
00174             (*p != *DirectorySeparator) && (*p != '#') && (*p != '<'))
00175           {
00176             token[i++]=(*p++);
00177             break;
00178           }
00179         for ( ; *p != '\0'; p++)
00180         {
00181           if (((isspace((int) ((unsigned char) *p)) != 0) || (*p == '=') ||
00182               (*p == ',') || (*p == ':')) && (*(p-1) != '\\'))
00183             break;
00184           if ((i > 0) && (*p == '<'))
00185             break;
00186           token[i++]=(*p);
00187           if (*p == '>')
00188             break;
00189           if (*p == '(')
00190             for (p++; *p != '\0'; p++)
00191             {
00192               token[i++]=(*p);
00193               if ((*p == ')') && (*(p-1) != '\\'))
00194                 break;
00195             }
00196         }
00197         break;
00198       }
00199     }
00200     break;
00201   }
00202   token[i]='\0';
00203   if (LocaleNCompare(token,"url(#",5) == 0)
00204     {
00205       i=(ssize_t) strlen(token);
00206       (void) CopyWizardString(token,token+5,MaxTextExtent);
00207       token[i-6]='\0';
00208     }
00209   if (LocaleNCompare(token,"url(",4) == 0)
00210     {
00211       i=(ssize_t) strlen(token);
00212       (void) CopyWizardString(token,token+4,MaxTextExtent);
00213       token[i-5]='\0';
00214     }
00215   while (isspace((int) ((unsigned char) *p)) != 0)
00216     p++;
00217   if (end != (const char **) NULL)
00218     *end=(const char *) p;
00219 }
00220 
00221 /*
00222 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00223 %                                                                             %
00224 %                                                                             %
00225 %                                                                             %
00226 %   G l o b E x p r e s s i o n                                               %
00227 %                                                                             %
00228 %                                                                             %
00229 %                                                                             %
00230 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00231 %
00232 %  GlobExpression() returns WizardTrue if the expression matches the pattern.
00233 %
00234 %  The format of the GlobExpression function is:
00235 %
00236 %      WizardBooleanType GlobExpression(const char *expression,
00237 %        const char *pattern,const WizardBooleanType case_insensitive)
00238 %
00239 %  A description of each parameter follows:
00240 %
00241 %    o expression: Specifies a pointer to a text string containing a file name.
00242 %
00243 %    o pattern: Specifies a pointer to a text string containing a pattern.
00244 %
00245 %    o case_insensitive: set to WizardTrue to ignore the case when matching
00246 %      an expression.
00247 %
00248 */
00249 WizardExport WizardBooleanType GlobExpression(const char *expression,
00250   const char *pattern,const WizardBooleanType case_insensitive)
00251 {
00252   WizardBooleanType
00253     done,
00254     match;
00255 
00256   /*
00257     Return on empty pattern or '*'.
00258   */
00259   if (pattern == (char *) NULL)
00260     return(WizardTrue);
00261   if (*pattern == '\0')
00262     return(WizardTrue);
00263   if (LocaleCompare(pattern,"*") == 0)
00264     return(WizardTrue);
00265   /*
00266     Evaluate glob expression.
00267   */
00268   done=WizardFalse;
00269   while ((*pattern != '\0') && (done == WizardFalse))
00270   {
00271     if (*expression == '\0')
00272       if ((*pattern != '{') && (*pattern != '*'))
00273         break;
00274     switch (*pattern)
00275     {
00276       case '*':
00277       {
00278         WizardBooleanType
00279           status;
00280 
00281         pattern++;
00282         status=WizardFalse;
00283         while ((*expression != '\0') && (status == WizardFalse))
00284           status=GlobExpression(expression++,pattern,case_insensitive);
00285         if (status != WizardFalse)
00286           {
00287             while (*expression != '\0')
00288               expression++;
00289             while (*pattern != '\0')
00290               pattern++;
00291           }
00292         break;
00293       }
00294       case '[':
00295       {
00296         char
00297           c;
00298 
00299         pattern++;
00300         for ( ; ; )
00301         {
00302           if ((*pattern == '\0') || (*pattern == ']'))
00303             {
00304               done=WizardTrue;
00305               break;
00306             }
00307           if (*pattern == '\\')
00308             {
00309               pattern++;
00310               if (*pattern == '\0')
00311                 {
00312                   done=WizardTrue;
00313                   break;
00314                 }
00315              }
00316           if (*(pattern+1) == '-')
00317             {
00318               c=(*pattern);
00319               pattern+=2;
00320               if (*pattern == ']')
00321                 {
00322                   done=WizardTrue;
00323                   break;
00324                 }
00325               if (*pattern == '\\')
00326                 {
00327                   pattern++;
00328                   if (*pattern == '\0')
00329                     {
00330                       done=WizardTrue;
00331                       break;
00332                     }
00333                 }
00334               if ((*expression < c) || (*expression > *pattern))
00335                 {
00336                   pattern++;
00337                   continue;
00338                 }
00339             }
00340           else
00341             if (*pattern != *expression)
00342               {
00343                 pattern++;
00344                 continue;
00345               }
00346           pattern++;
00347           while ((*pattern != ']') && (*pattern != '\0'))
00348           {
00349             if ((*pattern == '\\') && (*(pattern+1) != '\0'))
00350               pattern++;
00351             pattern++;
00352           }
00353           if (*pattern != '\0')
00354             {
00355               pattern++;
00356               expression++;
00357             }
00358           break;
00359         }
00360         break;
00361       }
00362       case '?':
00363       {
00364         pattern++;
00365         expression++;
00366         break;
00367       }
00368       case '{':
00369       {
00370         register const char
00371           *p;
00372 
00373         pattern++;
00374         while ((*pattern != '}') && (*pattern != '\0'))
00375         {
00376           p=expression;
00377           match=WizardTrue;
00378           while ((*p != '\0') && (*pattern != '\0') &&
00379                  (*pattern != ',') && (*pattern != '}') &&
00380                  (match != WizardFalse))
00381           {
00382             if (*pattern == '\\')
00383               pattern++;
00384             match=(*pattern == *p) ? WizardTrue : WizardFalse;
00385             p++;
00386             pattern++;
00387           }
00388           if (*pattern == '\0')
00389             {
00390               match=WizardFalse;
00391               done=WizardTrue;
00392               break;
00393             }
00394           else
00395             if (match != WizardFalse)
00396               {
00397                 expression=p;
00398                 while ((*pattern != '}') && (*pattern != '\0'))
00399                 {
00400                   pattern++;
00401                   if (*pattern == '\\')
00402                     {
00403                       pattern++;
00404                       if (*pattern == '}')
00405                         pattern++;
00406                     }
00407                 }
00408               }
00409             else
00410               {
00411                 while ((*pattern != '}') && (*pattern != ',') &&
00412                        (*pattern != '\0'))
00413                 {
00414                   pattern++;
00415                   if (*pattern == '\\')
00416                     {
00417                       pattern++;
00418                       if ((*pattern == '}') || (*pattern == ','))
00419                         pattern++;
00420                     }
00421                 }
00422               }
00423             if (*pattern != '\0')
00424               pattern++;
00425           }
00426         break;
00427       }
00428       case '\\':
00429       {
00430         pattern++;
00431         if (*pattern == '\0')
00432           break;
00433       }
00434       default:
00435       {
00436         if (case_insensitive != WizardFalse)
00437           {
00438             if (tolower((int) ((unsigned char) *expression)) !=
00439                 tolower((int) ((unsigned char) *pattern)))
00440               {
00441                 done=WizardTrue;
00442                 break;
00443               }
00444           }
00445         else
00446           if (*expression != *pattern)
00447             {
00448               done=WizardTrue;
00449               break;
00450             }
00451         expression++;
00452         pattern++;
00453       }
00454     }
00455   }
00456   while (*pattern == '*') 
00457     pattern++;
00458   match=(*expression == '\0') && (*pattern == '\0') ? WizardTrue : WizardFalse;
00459   return(match);
00460 }
00461 
00462 /*
00463 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00464 %                                                                             %
00465 %                                                                             %
00466 +     I s G l o b                                                             %
00467 %                                                                             %
00468 %                                                                             %
00469 %                                                                             %
00470 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00471 %
00472 %  IsGlob() returns WizardTrue if the path specification contains a globbing
00473 %  pattern.
00474 %
00475 %  The format of the IsGlob method is:
00476 %
00477 %      WizardBooleanType IsGlob(const char *geometry)
00478 %
00479 %  A description of each parameter follows:
00480 %
00481 %    o status: IsGlob() returns WizardTrue if the path specification contains
00482 %      a globbing patten.
00483 %
00484 %    o path: The path.
00485 %
00486 */
00487 WizardExport WizardBooleanType IsGlob(const char *path)
00488 {
00489   WizardBooleanType
00490     status;
00491 
00492   if (IsAccessible(path) != WizardFalse)
00493     return(WizardFalse);
00494   status=(strchr(path,'*') != (char *) NULL) ||
00495     (strchr(path,'?') != (char *) NULL) ||
00496     (strchr(path,'{') != (char *) NULL) ||
00497     (strchr(path,'}') != (char *) NULL) ||
00498     (strchr(path,'[') != (char *) NULL) ||
00499     (strchr(path,']') != (char *) NULL) ? WizardTrue : WizardFalse;
00500   return(status);
00501 }