2 * $RCSId: xc/lib/fontconfig/src/fcpat.c,v 1.18 2002/09/18 17:11:46 tsi Exp $
4 * Copyright © 2000 Keith Packard
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.
31 FcPatternCreate (void)
35 p
= (FcPattern
*) malloc (sizeof (FcPattern
));
38 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
));
47 FcValueDestroy (FcValue v
)
51 FcStrFree ((FcChar8
*) v
.u
.s
);
54 FcMatrixFree ((FcMatrix
*) v
.u
.m
);
57 FcCharSetDestroy ((FcCharSet
*) v
.u
.c
);
60 FcLangSetDestroy ((FcLangSet
*) v
.u
.l
);
68 FcValueSave (FcValue v
)
72 v
.u
.s
= FcStrCopy (v
.u
.s
);
77 v
.u
.m
= FcMatrixCopy (v
.u
.m
);
82 v
.u
.c
= FcCharSetCopy ((FcCharSet
*) v
.u
.c
);
87 v
.u
.l
= FcLangSetCopy (v
.u
.l
);
98 FcValueListDestroy (FcValueList
*l
)
103 switch (l
->value
.type
) {
105 FcStrFree ((FcChar8
*) l
->value
.u
.s
);
108 FcMatrixFree ((FcMatrix
*) l
->value
.u
.m
);
111 FcCharSetDestroy ((FcCharSet
*) l
->value
.u
.c
);
114 FcLangSetDestroy ((FcLangSet
*) l
->value
.u
.l
);
120 FcMemFree (FC_MEM_VALLIST
, sizeof (FcValueList
));
126 FcValueEqual (FcValue va
, FcValue vb
)
128 if (va
.type
!= vb
.type
)
130 if (va
.type
== FcTypeInteger
)
132 va
.type
= FcTypeDouble
;
135 if (vb
.type
== FcTypeInteger
)
137 vb
.type
= FcTypeDouble
;
140 if (va
.type
!= vb
.type
)
147 return va
.u
.i
== vb
.u
.i
;
149 return va
.u
.d
== vb
.u
.d
;
151 return FcStrCmpIgnoreCase (va
.u
.s
, vb
.u
.s
) == 0;
153 return va
.u
.b
== vb
.u
.b
;
155 return FcMatrixEqual (va
.u
.m
, vb
.u
.m
);
157 return FcCharSetEqual (va
.u
.c
, vb
.u
.c
);
159 return va
.u
.f
== vb
.u
.f
;
161 return FcLangSetEqual (va
.u
.l
, vb
.u
.l
);
167 FcDoubleHash (double d
)
177 FcStringHash (const FcChar8
*s
)
184 h
= ((h
<< 1) | (h
>> 31)) ^ c
;
189 FcValueHash (FcValue v
)
195 return (FcChar32
) v
.u
.i
;
197 return FcDoubleHash (v
.u
.d
);
199 return FcStringHash (v
.u
.s
);
201 return (FcChar32
) v
.u
.b
;
203 return (FcDoubleHash (v
.u
.m
->xx
) ^
204 FcDoubleHash (v
.u
.m
->xy
) ^
205 FcDoubleHash (v
.u
.m
->yx
) ^
206 FcDoubleHash (v
.u
.m
->yy
));
208 return (FcChar32
) v
.u
.c
->num
;
210 return FcStringHash ((const FcChar8
*) ((FT_Face
) v
.u
.f
)->family_name
) ^
211 FcStringHash ((const FcChar8
*) ((FT_Face
) v
.u
.f
)->style_name
);
213 return FcLangSetHash (v
.u
.l
);
219 FcValueListEqual (FcValueList
*la
, FcValueList
*lb
)
226 if (!FcValueEqual (la
->value
, lb
->value
))
237 FcValueListHash (FcValueList
*l
)
243 hash
= ((hash
<< 1) | (hash
>> 31)) ^ FcValueHash (l
->value
);
250 FcPatternDestroy (FcPattern
*p
)
254 if (p
->ref
== FC_REF_CONSTANT
|| --p
->ref
> 0)
257 for (i
= 0; i
< p
->num
; i
++)
258 FcValueListDestroy (p
->elts
[i
].values
);
263 FcMemFree (FC_MEM_PATELT
, p
->size
* sizeof (FcPatternElt
));
268 FcMemFree (FC_MEM_PATTERN
, sizeof (FcPattern
));
272 #define FC_VALUE_LIST_HASH_SIZE 257
273 #define FC_PATTERN_HASH_SIZE 67
275 typedef struct _FcValueListEnt FcValueListEnt
;
277 struct _FcValueListEnt
{
278 FcValueListEnt
*next
;
283 typedef union _FcValueListAlign
{
288 static int FcValueListFrozenCount
[FcTypeLangSet
+ 1];
289 static int FcValueListFrozenBytes
[FcTypeLangSet
+ 1];
290 static char *FcValueListFrozenName
[] = {
303 FcValueListReport (void);
306 FcValueListReport (void)
310 printf ("Fc Frozen Values:\n");
311 printf ("\t%8s %9s %9s\n", "Type", "Count", "Bytes");
312 for (t
= FcTypeVoid
; t
<= FcTypeLangSet
; t
++)
313 printf ("\t%8s %9d %9d\n", FcValueListFrozenName
[t
],
314 FcValueListFrozenCount
[t
], FcValueListFrozenBytes
[t
]);
317 static FcValueListEnt
*
318 FcValueListEntCreate (FcValueList
*h
)
320 FcValueListAlign
*ea
;
322 FcValueList
*l
, *new;
327 for (l
= h
; l
; l
= l
->next
)
329 size
= sizeof (FcValueListAlign
) + n
* sizeof (FcValueList
);
330 FcValueListFrozenCount
[h
->value
.type
]++;
331 FcValueListFrozenBytes
[h
->value
.type
] += size
;
335 FcMemAlloc (FC_MEM_VALLIST
, size
);
337 e
->list
= (FcValueList
*) (ea
+ 1);
339 for (l
= h
; l
; l
= l
->next
, new++)
341 if (l
->value
.type
== FcTypeString
)
343 new->value
.type
= FcTypeString
;
344 new->value
.u
.s
= FcObjectStaticName (l
->value
.u
.s
);
348 new->value
= FcValueSave (l
->value
);
350 new->binding
= l
->binding
;
360 FcValueListEntDestroy (FcValueListEnt
*e
)
364 FcValueListFrozenCount
[e
->list
->value
.type
]--;
366 /* XXX: We should perform these two operations with "size" as
367 computed in FcValueListEntCreate, but we don't have access to
368 that value here. Without this, the FcValueListFrozenBytes
369 values will be wrong as will the FcMemFree counts.
371 FcValueListFrozenBytes[e->list->value.type] -= size;
372 FcMemFree (FC_MEM_VALLIST, size);
375 for (l
= e
->list
; l
; l
= l
->next
)
377 if (l
->value
.type
!= FcTypeString
)
378 FcValueDestroy (l
->value
);
380 /* XXX: Are we being too chummy with the implementation here to
381 free(e) when it was actually the enclosing FcValueListAlign
382 that was allocated? */
386 static int FcValueListTotal
;
387 static int FcValueListUsed
;
389 static FcValueListEnt
*FcValueListHashTable
[FC_VALUE_LIST_HASH_SIZE
];
392 FcValueListFreeze (FcValueList
*l
)
394 FcChar32 hash
= FcValueListHash (l
);
395 FcValueListEnt
**bucket
= &FcValueListHashTable
[hash
% FC_VALUE_LIST_HASH_SIZE
];
399 for (ent
= *bucket
; ent
; ent
= ent
->next
)
401 if (ent
->hash
== hash
&& FcValueListEqual (ent
->list
, l
))
405 ent
= FcValueListEntCreate (l
);
417 FcValueListThawAll (void)
420 FcValueListEnt
*ent
, *next
;
422 for (i
= 0; i
< FC_VALUE_LIST_HASH_SIZE
; i
++)
424 for (ent
= FcValueListHashTable
[i
]; ent
; ent
= next
)
427 FcValueListEntDestroy (ent
);
429 FcValueListHashTable
[i
] = 0;
432 FcValueListTotal
= 0;
437 FcPatternBaseHash (FcPattern
*b
)
439 FcChar32 hash
= b
->num
;
442 for (i
= 0; i
< b
->num
; i
++)
443 hash
= ((hash
<< 1) | (hash
>> 31)) ^ ((long) b
->elts
[i
].values
);
447 typedef struct _FcPatternEnt FcPatternEnt
;
449 struct _FcPatternEnt
{
455 static int FcPatternTotal
;
456 static int FcPatternUsed
;
458 static FcPatternEnt
*FcPatternHashTable
[FC_VALUE_LIST_HASH_SIZE
];
461 FcPatternBaseFreeze (FcPattern
*b
)
463 FcChar32 hash
= FcPatternBaseHash (b
);
464 FcPatternEnt
**bucket
= &FcPatternHashTable
[hash
% FC_VALUE_LIST_HASH_SIZE
];
470 for (ent
= *bucket
; ent
; ent
= ent
->next
)
472 if (ent
->hash
== hash
&& b
->num
== ent
->pattern
.num
)
474 for (i
= 0; i
< b
->num
; i
++)
476 if (b
->elts
[i
].object
!= ent
->pattern
.elts
[i
].object
)
478 if (b
->elts
[i
].values
!= ent
->pattern
.elts
[i
].values
)
482 return &ent
->pattern
;
487 * Compute size of pattern + elts
489 size
= sizeof (FcPatternEnt
) + b
->num
*sizeof (FcPatternElt
);
494 FcMemAlloc (FC_MEM_PATTERN
, size
);
497 ent
->pattern
.elts
= (FcPatternElt
*) (ent
+ 1);
498 ent
->pattern
.num
= b
->num
;
499 ent
->pattern
.size
= b
->num
;
500 ent
->pattern
.ref
= FC_REF_CONSTANT
;
502 for (i
= 0; i
< b
->num
; i
++)
504 ent
->pattern
.elts
[i
].values
= b
->elts
[i
].values
;
505 ent
->pattern
.elts
[i
].object
= b
->elts
[i
].object
;
511 return &ent
->pattern
;
515 FcPatternBaseThawAll (void)
518 FcPatternEnt
*ent
, *next
;
520 for (i
= 0; i
< FC_VALUE_LIST_HASH_SIZE
; i
++)
522 for (ent
= FcPatternHashTable
[i
]; ent
; ent
= next
)
527 FcPatternHashTable
[i
] = 0;
535 FcPatternFreeze (FcPattern
*p
)
537 FcPattern
*b
, *n
= 0;
541 size
= sizeof (FcPattern
) + p
->num
* sizeof (FcPatternElt
);
542 b
= (FcPattern
*) malloc (size
);
545 FcMemAlloc (FC_MEM_PATTERN
, size
);
549 b
->elts
= (FcPatternElt
*) (b
+ 1);
551 * Freeze object lists
553 for (i
= 0; i
< p
->num
; i
++)
555 b
->elts
[i
].object
= p
->elts
[i
].object
;
556 b
->elts
[i
].values
= FcValueListFreeze (p
->elts
[i
].values
);
557 if (!b
->elts
[i
].values
)
563 n
= FcPatternBaseFreeze (b
);
565 if (FcDebug() & FC_DBG_MEMORY
)
567 printf ("ValueLists: total %9d used %9d\n", FcValueListTotal
, FcValueListUsed
);
568 printf ("Patterns: total %9d used %9d\n", FcPatternTotal
, FcPatternUsed
);
574 assert (FcPatternEqual (n
, p
));
580 FcPatternThawAll (void)
582 FcPatternBaseThawAll ();
583 FcValueListThawAll ();
587 FcPatternPosition (const FcPattern
*p
, const char *object
)
589 int low
, high
, mid
, c
;
597 mid
= (low
+ high
) >> 1;
598 c
= strcmp (p
->elts
[mid
].object
, object
);
612 FcPatternFindElt (const FcPattern
*p
, const char *object
)
614 int i
= FcPatternPosition (p
, object
);
621 FcPatternInsertElt (FcPattern
*p
, const char *object
)
626 i
= FcPatternPosition (p
, object
);
632 if (p
->num
+ 1 >= p
->size
)
634 int s
= p
->size
+ 16;
636 e
= (FcPatternElt
*) realloc (p
->elts
, s
* sizeof (FcPatternElt
));
638 e
= (FcPatternElt
*) malloc (s
* sizeof (FcPatternElt
));
643 FcMemFree (FC_MEM_PATELT
, p
->size
* sizeof (FcPatternElt
));
644 FcMemAlloc (FC_MEM_PATELT
, s
* sizeof (FcPatternElt
));
647 p
->elts
[p
->size
].object
= 0;
648 p
->elts
[p
->size
].values
= 0;
654 memmove (p
->elts
+ i
+ 1,
656 sizeof (FcPatternElt
) *
662 p
->elts
[i
].object
= FcObjectStaticName (object
);
663 p
->elts
[i
].values
= 0;
670 FcPatternEqual (const FcPattern
*pa
, const FcPattern
*pb
)
677 if (pa
->num
!= pb
->num
)
679 for (i
= 0; i
< pa
->num
; i
++)
681 if (pa
->elts
[i
].object
!= pb
->elts
[i
].object
)
683 if (!FcValueListEqual (pa
->elts
[i
].values
, pb
->elts
[i
].values
))
690 FcPatternHash (const FcPattern
*p
)
695 for (i
= 0; i
< p
->num
; i
++)
697 h
= (((h
<< 1) | (h
>> 31)) ^
698 FcStringHash ((const FcChar8
*) p
->elts
[i
].object
) ^
699 FcValueListHash (p
->elts
[i
].values
));
705 FcPatternEqualSubset (const FcPattern
*pa
, const FcPattern
*pb
, const FcObjectSet
*os
)
707 FcPatternElt
*ea
, *eb
;
710 for (i
= 0; i
< os
->nobject
; i
++)
712 ea
= FcPatternFindElt (pa
, os
->objects
[i
]);
713 eb
= FcPatternFindElt (pb
, os
->objects
[i
]);
718 if (!FcValueListEqual (ea
->values
, eb
->values
))
731 FcPatternAddWithBinding (FcPattern
*p
,
734 FcValueBinding binding
,
738 FcValueList
*new, **prev
;
740 if (p
->ref
== FC_REF_CONSTANT
)
743 new = (FcValueList
*) malloc (sizeof (FcValueList
));
747 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
));
749 value
= FcValueSave (value
);
750 if (value
.type
== FcTypeVoid
)
754 new->binding
= binding
;
757 e
= FcPatternInsertElt (p
, object
);
763 for (prev
= &e
->values
; *prev
; prev
= &(*prev
)->next
);
768 new->next
= e
->values
;
775 switch (value
.type
) {
777 FcStrFree ((FcChar8
*) value
.u
.s
);
780 FcMatrixFree ((FcMatrix
*) value
.u
.m
);
783 FcCharSetDestroy ((FcCharSet
*) value
.u
.c
);
786 FcLangSetDestroy ((FcLangSet
*) value
.u
.l
);
792 FcMemFree (FC_MEM_VALLIST
, sizeof (FcValueList
));
799 FcPatternAdd (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
801 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingStrong
, append
);
805 FcPatternAddWeak (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
807 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingWeak
, append
);
811 FcPatternDel (FcPattern
*p
, const char *object
)
816 e
= FcPatternFindElt (p
, object
);
823 FcValueListDestroy (e
->values
);
825 /* shuffle existing ones down */
826 memmove (e
, e
+1, (p
->elts
+ p
->num
- (e
+ 1)) * sizeof (FcPatternElt
));
828 p
->elts
[p
->num
].object
= 0;
829 p
->elts
[p
->num
].values
= 0;
834 FcPatternRemove (FcPattern
*p
, const char *object
, int id
)
837 FcValueList
**prev
, *l
;
839 e
= FcPatternFindElt (p
, object
);
842 for (prev
= &e
->values
; (l
= *prev
); prev
= &l
->next
)
848 FcValueListDestroy (l
);
850 FcPatternDel (p
, object
);
859 FcPatternAddInteger (FcPattern
*p
, const char *object
, int i
)
863 v
.type
= FcTypeInteger
;
865 return FcPatternAdd (p
, object
, v
, FcTrue
);
869 FcPatternAddDouble (FcPattern
*p
, const char *object
, double d
)
873 v
.type
= FcTypeDouble
;
875 return FcPatternAdd (p
, object
, v
, FcTrue
);
880 FcPatternAddString (FcPattern
*p
, const char *object
, const FcChar8
*s
)
884 v
.type
= FcTypeString
;
886 return FcPatternAdd (p
, object
, v
, FcTrue
);
890 FcPatternAddMatrix (FcPattern
*p
, const char *object
, const FcMatrix
*s
)
894 v
.type
= FcTypeMatrix
;
895 v
.u
.m
= (FcMatrix
*) s
;
896 return FcPatternAdd (p
, object
, v
, FcTrue
);
901 FcPatternAddBool (FcPattern
*p
, const char *object
, FcBool b
)
907 return FcPatternAdd (p
, object
, v
, FcTrue
);
911 FcPatternAddCharSet (FcPattern
*p
, const char *object
, const FcCharSet
*c
)
915 v
.type
= FcTypeCharSet
;
916 v
.u
.c
= (FcCharSet
*) c
;
917 return FcPatternAdd (p
, object
, v
, FcTrue
);
921 FcPatternAddFTFace (FcPattern
*p
, const char *object
, const FT_Face f
)
925 v
.type
= FcTypeFTFace
;
927 return FcPatternAdd (p
, object
, v
, FcTrue
);
931 FcPatternAddLangSet (FcPattern
*p
, const char *object
, const FcLangSet
*ls
)
935 v
.type
= FcTypeLangSet
;
936 v
.u
.l
= (FcLangSet
*) ls
;
937 return FcPatternAdd (p
, object
, v
, FcTrue
);
941 FcPatternGet (const FcPattern
*p
, const char *object
, int id
, FcValue
*v
)
946 e
= FcPatternFindElt (p
, object
);
948 return FcResultNoMatch
;
949 for (l
= e
->values
; l
; l
= l
->next
)
954 return FcResultMatch
;
962 FcPatternGetInteger (const FcPattern
*p
, const char *object
, int id
, int *i
)
967 r
= FcPatternGet (p
, object
, id
, &v
);
968 if (r
!= FcResultMatch
)
978 return FcResultTypeMismatch
;
980 return FcResultMatch
;
984 FcPatternGetDouble (const FcPattern
*p
, const char *object
, int id
, double *d
)
989 r
= FcPatternGet (p
, object
, id
, &v
);
990 if (r
!= FcResultMatch
)
1000 return FcResultTypeMismatch
;
1002 return FcResultMatch
;
1006 FcPatternGetString (const FcPattern
*p
, const char *object
, int id
, FcChar8
** s
)
1011 r
= FcPatternGet (p
, object
, id
, &v
);
1012 if (r
!= FcResultMatch
)
1014 if (v
.type
!= FcTypeString
)
1015 return FcResultTypeMismatch
;
1016 *s
= (FcChar8
*) v
.u
.s
;
1017 return FcResultMatch
;
1021 FcPatternGetMatrix(const FcPattern
*p
, const char *object
, int id
, FcMatrix
**m
)
1026 r
= FcPatternGet (p
, object
, id
, &v
);
1027 if (r
!= FcResultMatch
)
1029 if (v
.type
!= FcTypeMatrix
)
1030 return FcResultTypeMismatch
;
1031 *m
= (FcMatrix
*) v
.u
.m
;
1032 return FcResultMatch
;
1037 FcPatternGetBool(const FcPattern
*p
, const char *object
, int id
, FcBool
*b
)
1042 r
= FcPatternGet (p
, object
, id
, &v
);
1043 if (r
!= FcResultMatch
)
1045 if (v
.type
!= FcTypeBool
)
1046 return FcResultTypeMismatch
;
1048 return FcResultMatch
;
1052 FcPatternGetCharSet(const FcPattern
*p
, const char *object
, int id
, FcCharSet
**c
)
1057 r
= FcPatternGet (p
, object
, id
, &v
);
1058 if (r
!= FcResultMatch
)
1060 if (v
.type
!= FcTypeCharSet
)
1061 return FcResultTypeMismatch
;
1062 *c
= (FcCharSet
*) v
.u
.c
;
1063 return FcResultMatch
;
1067 FcPatternGetFTFace(const FcPattern
*p
, const char *object
, int id
, FT_Face
*f
)
1072 r
= FcPatternGet (p
, object
, id
, &v
);
1073 if (r
!= FcResultMatch
)
1075 if (v
.type
!= FcTypeFTFace
)
1076 return FcResultTypeMismatch
;
1077 *f
= (FT_Face
) v
.u
.f
;
1078 return FcResultMatch
;
1082 FcPatternGetLangSet(const FcPattern
*p
, const char *object
, int id
, FcLangSet
**ls
)
1087 r
= FcPatternGet (p
, object
, id
, &v
);
1088 if (r
!= FcResultMatch
)
1090 if (v
.type
!= FcTypeLangSet
)
1091 return FcResultTypeMismatch
;
1092 *ls
= (FcLangSet
*) v
.u
.l
;
1093 return FcResultMatch
;
1097 FcPatternDuplicate (const FcPattern
*orig
)
1103 new = FcPatternCreate ();
1107 for (i
= 0; i
< orig
->num
; i
++)
1109 for (l
= orig
->elts
[i
].values
; l
; l
= l
->next
)
1110 if (!FcPatternAdd (new, orig
->elts
[i
].object
, l
->value
, FcTrue
))
1117 FcPatternDestroy (new);
1123 FcPatternReference (FcPattern
*p
)
1125 if (p
->ref
!= FC_REF_CONSTANT
)
1130 FcPatternVaBuild (FcPattern
*orig
, va_list va
)
1134 FcPatternVapBuild (ret
, orig
, va
);
1139 FcPatternBuild (FcPattern
*orig
, ...)
1143 va_start (va
, orig
);
1144 FcPatternVapBuild (orig
, orig
, va
);
1150 * Add all of the elements in 's' to 'p'
1153 FcPatternAppend (FcPattern
*p
, FcPattern
*s
)
1159 for (i
= 0; i
< s
->num
; i
++)
1162 for (v
= e
->values
; v
; v
= v
->next
)
1164 if (!FcPatternAddWithBinding (p
, e
->object
,
1165 v
->value
, v
->binding
, FcTrue
))
1173 FcObjectStaticName (const char *name
)
1175 #define OBJECT_HASH_SIZE 31
1176 static struct objectBucket
{
1177 struct objectBucket
*next
;
1179 } *buckets
[OBJECT_HASH_SIZE
];
1180 FcChar32 hash
= FcStringHash ((const FcChar8
*) name
);
1181 struct objectBucket
**p
;
1182 struct objectBucket
*b
;
1185 for (p
= &buckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1186 if (b
->hash
== hash
&& !strcmp (name
, (char *) (b
+ 1)))
1187 return (char *) (b
+ 1);
1188 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1190 FcMemAlloc (FC_MEM_STATICSTR
, size
);
1195 strcpy ((char *) (b
+ 1), name
);
1197 return (char *) (b
+ 1);