]>
git.wh0rd.org - fontconfig.git/blob - src/fcformat.c
2 * Copyright © 2008 Red Hat, Inc.
4 * Red Hat Author(s): Behdad Esfahbod
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of Keith Packard not be used in
11 * advertising or publicity pertaining to distribution of the software without
12 * specific, written prior permission. Keith Packard makes no
13 * representations about the suitability of this software for any purpose. It
14 * is provided "as is" without express or implied warranty.
16 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22 * PERFORMANCE OF THIS SOFTWARE.
32 message (const char *fmt
, ...)
36 fprintf (stderr
, "Fontconfig: Pattern format error: ");
37 vfprintf (stderr
, fmt
, args
);
38 fprintf (stderr
, ".\n");
43 typedef struct _FcFormatContext
45 const FcChar8
*format_orig
;
46 const FcChar8
*format
;
52 FcFormatContextInit (FcFormatContext
*c
,
53 const FcChar8
*format
)
55 c
->format_orig
= c
->format
= format
;
56 c
->format_len
= strlen ((const char *) format
);
57 c
->scratch
= malloc (c
->format_len
+ 1);
59 return c
->scratch
!= NULL
;
63 FcFormatContextDone (FcFormatContext
*c
)
72 consume_char (FcFormatContext
*c
,
75 if (*c
->format
!= term
)
83 expect_char (FcFormatContext
*c
,
86 FcBool res
= consume_char (c
, term
);
89 if (c
->format
== c
->format_orig
+ c
->format_len
)
90 message ("format ended while expecting '%c'",
93 message ("expected '%c' at %d",
94 term
, c
->format
- c
->format_orig
+ 1);
100 FcCharIsPunct (const FcChar8 c
)
120 read_elt_name_to_scratch (FcFormatContext
*c
)
128 if (*c
->format
== '\\')
135 else if (FcCharIsPunct (*c
->format
))
144 message ("expected element name at %d",
145 c
->format
- c
->format_orig
+ 1);
153 interpret_expr (FcFormatContext
*c
,
159 interpret_subexpr (FcFormatContext
*c
,
163 return expect_char (c
, '{') &&
164 interpret_expr (c
, pat
, buf
, '}') &&
165 expect_char (c
, '}');
169 maybe_interpret_subexpr (FcFormatContext
*c
,
173 return (*c
->format
== '{') ?
174 interpret_subexpr (c
, pat
, buf
) :
179 skip_subexpr (FcFormatContext
*c
);
182 skip_percent (FcFormatContext
*c
)
184 if (!expect_char (c
, '%'))
187 /* skip an optional width specifier */
188 strtol ((const char *) c
->format
, (char **) &c
->format
, 10);
190 if (!expect_char (c
, '{'))
193 while(*c
->format
&& *c
->format
!= '}')
198 c
->format
++; /* skip over '\\' */
203 if (!skip_subexpr (c
))
210 return expect_char (c
, '}');
214 skip_expr (FcFormatContext
*c
)
216 while(*c
->format
&& *c
->format
!= '}')
221 c
->format
++; /* skip over '\\' */
226 if (!skip_percent (c
))
237 skip_subexpr (FcFormatContext
*c
)
239 return expect_char (c
, '{') &&
241 expect_char (c
, '}');
245 maybe_skip_subexpr (FcFormatContext
*c
)
247 return (*c
->format
== '{') ?
253 interpret_simple_tag (FcFormatContext
*c
,
258 FcBool add_colon
= FcFalse
;
259 FcBool add_elt_name
= FcFalse
;
261 if (consume_char (c
, ':'))
264 if (!read_elt_name_to_scratch (c
))
267 if (consume_char (c
, '='))
268 add_elt_name
= FcTrue
;
270 e
= FcPatternObjectFindElt (pat
,
271 FcObjectFromName ((const char *) c
->scratch
));
277 FcStrBufChar (buf
, ':');
280 FcStrBufString (buf
, c
->scratch
);
281 FcStrBufChar (buf
, '=');
284 l
= FcPatternEltValues(e
);
285 FcNameUnparseValueList (buf
, l
, '\0');
292 interpret_filter (FcFormatContext
*c
,
299 if (!expect_char (c
, '+'))
302 os
= FcObjectSetCreate ();
308 if (!read_elt_name_to_scratch (c
) ||
309 !FcObjectSetAdd (os
, (const char *) c
->scratch
))
311 FcObjectSetDestroy (os
);
315 while (consume_char (c
, ','));
317 subpat
= FcPatternFilter (pat
, os
);
318 FcObjectSetDestroy (os
);
321 !interpret_subexpr (c
, subpat
, buf
))
324 FcPatternDestroy (subpat
);
329 interpret_delete (FcFormatContext
*c
,
335 if (!expect_char (c
, '-'))
338 subpat
= FcPatternDuplicate (pat
);
344 if (!read_elt_name_to_scratch (c
))
346 FcPatternDestroy (subpat
);
350 FcPatternDel (subpat
, (const char *) c
->scratch
);
352 while (consume_char (c
, ','));
354 if (!interpret_subexpr (c
, subpat
, buf
))
357 FcPatternDestroy (subpat
);
362 interpret_conditional (FcFormatContext
*c
,
368 if (!expect_char (c
, '?'))
378 negate
= consume_char (c
, '!');
380 if (!read_elt_name_to_scratch (c
))
385 FcResultMatch
== FcPatternGet (pat
,
386 (const char *) c
->scratch
,
389 while (consume_char (c
, ','));
393 if (!interpret_subexpr (c
, pat
, buf
) ||
394 !maybe_skip_subexpr (c
))
399 if (!skip_subexpr (c
) ||
400 !maybe_interpret_subexpr (c
, pat
, buf
))
408 interpret_percent (FcFormatContext
*c
,
414 if (!expect_char (c
, '%'))
417 if (consume_char (c
, '%')) /* "%%" */
419 FcStrBufChar (buf
, '%');
423 /* parse an optional width specifier */
424 width
= strtol ((const char *) c
->format
, (char **) &c
->format
, 10);
428 if (!expect_char (c
, '{'))
431 switch (*c
->format
) {
435 if (!interpret_subexpr (c
, pat
, buf
))
440 /* filtering pattern elements */
441 if (!interpret_filter (c
, pat
, buf
))
446 /* deleting pattern elements */
447 if (!interpret_delete (c
, pat
, buf
))
452 /* conditional on pattern elements */
453 if (!interpret_conditional (c
, pat
, buf
))
459 if (!interpret_simple_tag (c
, pat
, buf
))
465 /* handle filters, if any */
475 len
= after
- before
;
480 while (len
++ < -width
)
481 FcStrBufChar (buf
, ' ');
483 else if (len
< width
)
486 while (len
++ < width
)
487 FcStrBufChar (buf
, ' ');
488 len
= after
- before
;
489 memmove (buf
->buf
+ buf
->len
- len
,
490 buf
->buf
+ buf
->len
- width
,
492 memset (buf
->buf
+ buf
->len
- width
,
498 return expect_char (c
, '}');
501 static char escaped_char(const char ch
)
504 case 'a': return '\a';
505 case 'b': return '\b';
506 case 'f': return '\f';
507 case 'n': return '\n';
508 case 'r': return '\r';
509 case 't': return '\t';
510 case 'v': return '\v';
516 interpret_expr (FcFormatContext
*c
,
521 while (*c
->format
&& *c
->format
!= term
)
526 c
->format
++; /* skip over '\\' */
528 FcStrBufChar (buf
, escaped_char (*c
->format
++));
531 if (!interpret_percent (c
, pat
, buf
))
535 FcStrBufChar (buf
, *c
->format
++);
541 FcPatternFormat (FcPattern
*pat
, const FcChar8
*format
)
547 FcStrBufInit (&buf
, 0, 0);
548 if (!FcFormatContextInit (&c
, format
))
551 ret
= interpret_expr (&c
, pat
, &buf
, '\0');
555 FcFormatContextDone (&c
);
557 return FcStrBufDone (&buf
);
560 FcStrBufDestroy (&buf
);
566 #include "fcaliastail.h"