MagickCore 7.0.10
token.c
Go to the documentation of this file.
1/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% TTTTT OOO K K EEEEE N N %
7% T O O K K E NN N %
8% T O O KKK EEE N N N %
9% T O O K K E N NN %
10% T OOO K K EEEEE N N %
11% %
12% %
13% Wizard's Toolkit Token Methods %
14% %
15% Software Design %
16% Cristy %
17% March 2003 %
18% %
19% %
20% Copyright @ 1999 ImageMagick Studio LLC, a non-profit organization %
21% dedicated to making software imaging solutions freely available. %
22% %
23% You may not use this file except in compliance with the License. You may %
24% obtain a copy of the License at %
25% %
26% https://imagemagick.org/script/license.php %
27% %
28% Unless required by applicable law or agreed to in writing, software %
29% distributed under the License is distributed on an "AS IS" BASIS, %
30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31% See the License for the specific language governing permissions and %
32% limitations under the License. %
33% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37%
38*/
39
40/*
41 Include declarations.
42*/
43#include "wizard/studio.h"
44#include "wizard/exception.h"
46#include "wizard/locale_.h"
47#include "wizard/string_.h"
49#include "wizard/token.h"
50#include "wizard/utility.h"
51
52/*
53 Typedef declarations.
54*/
56{
57 int
59
62
63 ssize_t
65
66 char
68};
69
70/*
71%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
72% %
73% %
74% %
75+ G e t N e x t T o k e n %
76% %
77% %
78% %
79%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
80%
81% GetNextToken() gets a token from the token stream. A token is defined as
82% a sequence of characters delimited by whitespace (e.g. clip-path), a
83% sequence delimited with quotes (.e.g "Quote me"), or a sequence enclosed in
84% parenthesis (e.g. rgb(0,0,0)). GetNextToken() also recognizes these
85% separator characters: ':', '=', ',', and ';'.
86%
87% The format of the GetNextToken method is:
88%
89% void GetNextToken(const char *start,const char **end,
90% const size_t extent,char *token)
91%
92% A description of each parameter follows:
93%
94% o start: the start of the token sequence.
95%
96% o end: point to the end of the token sequence.
97%
98% o extent: maximum extent of the token.
99%
100% o token: copy the token to this buffer.
101%
102*/
103WizardExport void GetNextToken(const char *start,const char **end,
104 const size_t extent,char *token)
105{
106 double
107 value;
108
109 const char
110 *p;
111
112 ssize_t
113 i;
114
115 assert(start != (const char *) NULL);
116 assert(token != (char *) NULL);
117 i=0;
118 p=start;
119 while ((isspace((int) ((unsigned char) *p)) != 0) && (*p != '\0'))
120 p++;
121 switch (*p)
122 {
123 case '\0':
124 break;
125 case '"':
126 case '\'':
127 case '`':
128 case '{':
129 {
130 char
131 escape;
132
133 switch (*p)
134 {
135 case '"': escape='"'; break;
136 case '\'': escape='\''; break;
137 case '`': escape='\''; break;
138 case '{': escape='}'; break;
139 default: escape=(*p); break;
140 }
141 for (p++; *p != '\0'; p++)
142 {
143 if ((*p == '\\') && ((*(p+1) == escape) || (*(p+1) == '\\')))
144 p++;
145 else
146 if (*p == escape)
147 {
148 p++;
149 break;
150 }
151 if (i < (ssize_t) (extent-1))
152 token[i++]=(*p);
153 }
154 break;
155 }
156 case '/':
157 {
158 if (i < (ssize_t) (extent-1))
159 token[i++]=(*p++);
160 if ((*p == '>') || (*p == '/'))
161 if (i < (ssize_t) (extent-1))
162 token[i++]=(*p++);
163 break;
164 }
165 default:
166 {
167 char
168 *q;
169
170 value=StringToDouble(p,&q);
171 (void) value;
172 if ((p != q) && (*p != ','))
173 {
174 for ( ; (p < q) && (*p != ','); p++)
175 if (i < (ssize_t) (extent-1))
176 token[i++]=(*p);
177 if (*p == '%')
178 if (i < (ssize_t) (extent-1))
179 token[i++]=(*p++);
180 break;
181 }
182 if ((*p != '\0') && (isalpha((int) ((unsigned char) *p)) == 0) &&
183 (*p != *DirectorySeparator) && (*p != '#') && (*p != '<'))
184 {
185 if (i < (ssize_t) (extent-1))
186 token[i++]=(*p++);
187 break;
188 }
189 for ( ; *p != '\0'; p++)
190 {
191 if (((isspace((int) ((unsigned char) *p)) != 0) || (*p == '=') ||
192 (*p == ',') || (*p == ':') || (*p == ';')) && (*(p-1) != '\\'))
193 break;
194 if ((i > 0) && (*p == '<'))
195 break;
196 if (i < (ssize_t) (extent-1))
197 token[i++]=(*p);
198 if (*p == '>')
199 break;
200 if (*p == '(')
201 for (p++; *p != '\0'; p++)
202 {
203 if (i < (ssize_t) (extent-1))
204 token[i++]=(*p);
205 if ((*p == ')') && (*(p-1) != '\\'))
206 break;
207 }
208 }
209 break;
210 }
211 }
212 token[i]='\0';
213 if (LocaleNCompare(token,"url(",4) == 0)
214 {
215 ssize_t
216 offset;
217
218 offset=4;
219 if (token[offset] == '#')
220 offset++;
221 i=(ssize_t) strlen(token);
222 (void) CopyWizardString(token,token+offset,WizardPathExtent);
223 token[i-offset-1]='\0';
224 }
225 while (isspace((int) ((unsigned char) *p)) != 0)
226 p++;
227 if (end != (const char **) NULL)
228 *end=(const char *) p;
229}
230
231/*
232%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
233% %
234% %
235% %
236% G l o b E x p r e s s i o n %
237% %
238% %
239% %
240%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
241%
242% GlobExpression() returns WizardTrue if the expression matches the pattern.
243%
244% The format of the GlobExpression function is:
245%
246% WizardBooleanType GlobExpression(const char *expression,
247% const char *pattern,const WizardBooleanType case_insensitive)
248%
249% A description of each parameter follows:
250%
251% o expression: Specifies a pointer to a text string containing a file name.
252%
253% o pattern: Specifies a pointer to a text string containing a pattern.
254%
255% o case_insensitive: set to WizardTrue to ignore the case when matching
256% an expression.
257%
258*/
260 const char *pattern,const WizardBooleanType case_insensitive)
261{
263 done,
264 match;
265
266 /*
267 Return on empty pattern or '*'.
268 */
269 if (pattern == (char *) NULL)
270 return(WizardTrue);
271 if (*pattern == '\0')
272 return(WizardTrue);
273 if (LocaleCompare(pattern,"*") == 0)
274 return(WizardTrue);
275 /*
276 Evaluate glob expression.
277 */
278 done=WizardFalse;
279 while ((*pattern != '\0') && (done == WizardFalse))
280 {
281 if (*expression == '\0')
282 if ((*pattern != '{') && (*pattern != '*'))
283 break;
284 switch (*pattern)
285 {
286 case '*':
287 {
289 status;
290
291 while (*pattern == '*')
292 pattern++;
293 status=WizardFalse;
294 while ((*expression != '\0') && (status == WizardFalse))
295 status=GlobExpression(expression++,pattern,case_insensitive);
296 if (status != WizardFalse)
297 {
298 while (*expression != '\0')
299 expression++;
300 while (*pattern != '\0')
301 pattern++;
302 }
303 break;
304 }
305 case '[':
306 {
307 char
308 c;
309
310 pattern++;
311 for ( ; ; )
312 {
313 if ((*pattern == '\0') || (*pattern == ']'))
314 {
315 done=WizardTrue;
316 break;
317 }
318 if (*pattern == '\\')
319 {
320 pattern++;
321 if (*pattern == '\0')
322 {
323 done=WizardTrue;
324 break;
325 }
326 }
327 if (*(pattern+1) == '-')
328 {
329 c=(*pattern);
330 pattern+=2;
331 if (*pattern == ']')
332 {
333 done=WizardTrue;
334 break;
335 }
336 if (*pattern == '\\')
337 {
338 pattern++;
339 if (*pattern == '\0')
340 {
341 done=WizardTrue;
342 break;
343 }
344 }
345 if ((*expression < c) || (*expression > *pattern))
346 {
347 pattern++;
348 continue;
349 }
350 }
351 else
352 if (*pattern != *expression)
353 {
354 pattern++;
355 continue;
356 }
357 pattern++;
358 while ((*pattern != ']') && (*pattern != '\0'))
359 {
360 if ((*pattern == '\\') && (*(pattern+1) != '\0'))
361 pattern++;
362 pattern++;
363 }
364 if (*pattern != '\0')
365 {
366 pattern++;
367 expression++;
368 }
369 break;
370 }
371 break;
372 }
373 case '?':
374 {
375 pattern++;
376 expression++;
377 break;
378 }
379 case '{':
380 {
381 const char
382 *p;
383
384 pattern++;
385 while ((*pattern != '}') && (*pattern != '\0'))
386 {
387 p=expression;
388 match=WizardTrue;
389 while ((*p != '\0') && (*pattern != '\0') &&
390 (*pattern != ',') && (*pattern != '}') &&
391 (match != WizardFalse))
392 {
393 if (*pattern == '\\')
394 pattern++;
395 match=(*pattern == *p) ? WizardTrue : WizardFalse;
396 p++;
397 pattern++;
398 }
399 if (*pattern == '\0')
400 {
401 match=WizardFalse;
402 done=WizardTrue;
403 break;
404 }
405 if (match != WizardFalse)
406 {
407 expression=p;
408 while ((*pattern != '}') && (*pattern != '\0'))
409 {
410 pattern++;
411 if (*pattern == '\\')
412 {
413 pattern++;
414 if (*pattern == '}')
415 pattern++;
416 }
417 }
418 }
419 else
420 {
421 while ((*pattern != '}') && (*pattern != ',') &&
422 (*pattern != '\0'))
423 {
424 pattern++;
425 if (*pattern == '\\')
426 {
427 pattern++;
428 if ((*pattern == '}') || (*pattern == ','))
429 pattern++;
430 }
431 }
432 }
433 if (*pattern != '\0')
434 pattern++;
435 }
436 break;
437 }
438 case '\\':
439 {
440 pattern++;
441 if (*pattern == '\0')
442 break;
443 }
444 default:
445 {
446 if (case_insensitive != WizardFalse)
447 {
448 if (tolower((int) ((unsigned char) *expression)) !=
449 tolower((int) ((unsigned char) *pattern)))
450 {
451 done=WizardTrue;
452 break;
453 }
454 }
455 else
456 if (*expression != *pattern)
457 {
458 done=WizardTrue;
459 break;
460 }
461 expression++;
462 pattern++;
463 }
464 }
465 }
466 while (*pattern == '*')
467 pattern++;
468 match=(*expression == '\0') && (*pattern == '\0') ? WizardTrue : WizardFalse;
469 return(match);
470}
471
472/*
473%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
474% %
475% %
476+ I s G l o b %
477% %
478% %
479% %
480%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
481%
482% IsGlob() returns WizardTrue if the path specification contains a globbing
483% pattern.
484%
485% The format of the IsGlob method is:
486%
487% WizardBooleanType IsGlob(const char *geometry)
488%
489% A description of each parameter follows:
490%
491% o status: IsGlob() returns WizardTrue if the path specification contains
492% a globbing patten.
493%
494% o path: The path.
495%
496*/
498{
500 status = WizardFalse;
501
502 const char
503 *p;
504
505 if (IsPathAcessible(path) != WizardFalse)
506 return(WizardFalse);
507 for (p=path; *p != '\0'; p++)
508 {
509 switch (*p)
510 {
511 case '*':
512 case '?':
513 case '{':
514 case '}':
515 case '[':
516 case ']':
517 {
518 status=WizardTrue;
519 break;
520 }
521 default:
522 break;
523 }
524 }
525 return(status);
526}
#define WizardExport
#define WizardPathExtent
static double StringToDouble(const char *string, char **sentinal)
WizardExport int LocaleNCompare(const char *p, const char *q, const size_t length)
Definition string.c:1608
WizardExport int LocaleCompare(const char *p, const char *q)
Definition string.c:1510
WizardExport size_t CopyWizardString(char *destination, const char *source, const size_t length)
Definition string.c:762
char quote
Definition token.c:67
ssize_t offset
Definition token.c:64
WizardStatusType flag
Definition token.c:61
int state
Definition token.c:58
#define DirectorySeparator
Definition studio.h:239
WizardExport WizardBooleanType GlobExpression(const char *expression, const char *pattern, const WizardBooleanType case_insensitive)
Definition token.c:259
WizardExport WizardBooleanType IsGlob(const char *path)
Definition token.c:497
WizardExport void GetNextToken(const char *start, const char **end, const size_t extent, char *token)
Definition token.c:103
WizardExport WizardBooleanType IsPathAcessible(const char *path)
Definition utility.c:779
WizardBooleanType
Definition wizard-type.h:26
@ WizardTrue
Definition wizard-type.h:28
@ WizardFalse
Definition wizard-type.h:27
unsigned int WizardStatusType
Definition wizard-type.h:42