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
;
591 object
= FcObjectStaticName(object
);
598 mid
= (low
+ high
) >> 1;
599 c
= p
->elts
[mid
].object
- object
;
613 FcPatternFindElt (const FcPattern
*p
, const char *object
)
615 int i
= FcPatternPosition (p
, object
);
622 FcPatternInsertElt (FcPattern
*p
, const char *object
)
627 i
= FcPatternPosition (p
, object
);
633 if (p
->num
+ 1 >= p
->size
)
635 int s
= p
->size
+ 16;
637 e
= (FcPatternElt
*) realloc (p
->elts
, s
* sizeof (FcPatternElt
));
639 e
= (FcPatternElt
*) malloc (s
* sizeof (FcPatternElt
));
644 FcMemFree (FC_MEM_PATELT
, p
->size
* sizeof (FcPatternElt
));
645 FcMemAlloc (FC_MEM_PATELT
, s
* sizeof (FcPatternElt
));
648 p
->elts
[p
->size
].object
= 0;
649 p
->elts
[p
->size
].values
= 0;
655 memmove (p
->elts
+ i
+ 1,
657 sizeof (FcPatternElt
) *
663 p
->elts
[i
].object
= FcObjectStaticName (object
);
664 p
->elts
[i
].values
= 0;
671 FcPatternEqual (const FcPattern
*pa
, const FcPattern
*pb
)
678 if (pa
->num
!= pb
->num
)
680 for (i
= 0; i
< pa
->num
; i
++)
682 if (pa
->elts
[i
].object
!= pb
->elts
[i
].object
)
684 if (!FcValueListEqual (pa
->elts
[i
].values
, pb
->elts
[i
].values
))
691 FcPatternHash (const FcPattern
*p
)
696 for (i
= 0; i
< p
->num
; i
++)
698 h
= (((h
<< 1) | (h
>> 31)) ^
699 FcStringHash ((const FcChar8
*) p
->elts
[i
].object
) ^
700 FcValueListHash (p
->elts
[i
].values
));
706 FcPatternEqualSubset (const FcPattern
*pa
, const FcPattern
*pb
, const FcObjectSet
*os
)
708 FcPatternElt
*ea
, *eb
;
711 for (i
= 0; i
< os
->nobject
; i
++)
713 ea
= FcPatternFindElt (pa
, os
->objects
[i
]);
714 eb
= FcPatternFindElt (pb
, os
->objects
[i
]);
719 if (!FcValueListEqual (ea
->values
, eb
->values
))
732 FcPatternAddWithBinding (FcPattern
*p
,
735 FcValueBinding binding
,
739 FcValueList
*new, **prev
;
741 if (p
->ref
== FC_REF_CONSTANT
)
744 new = (FcValueList
*) malloc (sizeof (FcValueList
));
748 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
));
750 value
= FcValueSave (value
);
751 if (value
.type
== FcTypeVoid
)
755 new->binding
= binding
;
758 e
= FcPatternInsertElt (p
, object
);
764 for (prev
= &e
->values
; *prev
; prev
= &(*prev
)->next
);
769 new->next
= e
->values
;
776 switch (value
.type
) {
778 FcStrFree ((FcChar8
*) value
.u
.s
);
781 FcMatrixFree ((FcMatrix
*) value
.u
.m
);
784 FcCharSetDestroy ((FcCharSet
*) value
.u
.c
);
787 FcLangSetDestroy ((FcLangSet
*) value
.u
.l
);
793 FcMemFree (FC_MEM_VALLIST
, sizeof (FcValueList
));
800 FcPatternAdd (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
802 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingStrong
, append
);
806 FcPatternAddWeak (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
808 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingWeak
, append
);
812 FcPatternDel (FcPattern
*p
, const char *object
)
817 e
= FcPatternFindElt (p
, object
);
824 FcValueListDestroy (e
->values
);
826 /* shuffle existing ones down */
827 memmove (e
, e
+1, (p
->elts
+ p
->num
- (e
+ 1)) * sizeof (FcPatternElt
));
829 p
->elts
[p
->num
].object
= 0;
830 p
->elts
[p
->num
].values
= 0;
835 FcPatternRemove (FcPattern
*p
, const char *object
, int id
)
838 FcValueList
**prev
, *l
;
840 e
= FcPatternFindElt (p
, object
);
843 for (prev
= &e
->values
; (l
= *prev
); prev
= &l
->next
)
849 FcValueListDestroy (l
);
851 FcPatternDel (p
, object
);
860 FcPatternAddInteger (FcPattern
*p
, const char *object
, int i
)
864 v
.type
= FcTypeInteger
;
866 return FcPatternAdd (p
, object
, v
, FcTrue
);
870 FcPatternAddDouble (FcPattern
*p
, const char *object
, double d
)
874 v
.type
= FcTypeDouble
;
876 return FcPatternAdd (p
, object
, v
, FcTrue
);
881 FcPatternAddString (FcPattern
*p
, const char *object
, const FcChar8
*s
)
885 v
.type
= FcTypeString
;
887 return FcPatternAdd (p
, object
, v
, FcTrue
);
891 FcPatternAddMatrix (FcPattern
*p
, const char *object
, const FcMatrix
*s
)
895 v
.type
= FcTypeMatrix
;
896 v
.u
.m
= (FcMatrix
*) s
;
897 return FcPatternAdd (p
, object
, v
, FcTrue
);
902 FcPatternAddBool (FcPattern
*p
, const char *object
, FcBool b
)
908 return FcPatternAdd (p
, object
, v
, FcTrue
);
912 FcPatternAddCharSet (FcPattern
*p
, const char *object
, const FcCharSet
*c
)
916 v
.type
= FcTypeCharSet
;
917 v
.u
.c
= (FcCharSet
*) c
;
918 return FcPatternAdd (p
, object
, v
, FcTrue
);
922 FcPatternAddFTFace (FcPattern
*p
, const char *object
, const FT_Face f
)
926 v
.type
= FcTypeFTFace
;
928 return FcPatternAdd (p
, object
, v
, FcTrue
);
932 FcPatternAddLangSet (FcPattern
*p
, const char *object
, const FcLangSet
*ls
)
936 v
.type
= FcTypeLangSet
;
937 v
.u
.l
= (FcLangSet
*) ls
;
938 return FcPatternAdd (p
, object
, v
, FcTrue
);
942 FcPatternGet (const FcPattern
*p
, const char *object
, int id
, FcValue
*v
)
947 e
= FcPatternFindElt (p
, object
);
949 return FcResultNoMatch
;
950 for (l
= e
->values
; l
; l
= l
->next
)
955 return FcResultMatch
;
963 FcPatternGetInteger (const FcPattern
*p
, const char *object
, int id
, int *i
)
968 r
= FcPatternGet (p
, object
, id
, &v
);
969 if (r
!= FcResultMatch
)
979 return FcResultTypeMismatch
;
981 return FcResultMatch
;
985 FcPatternGetDouble (const FcPattern
*p
, const char *object
, int id
, double *d
)
990 r
= FcPatternGet (p
, object
, id
, &v
);
991 if (r
!= FcResultMatch
)
1001 return FcResultTypeMismatch
;
1003 return FcResultMatch
;
1007 FcPatternGetString (const FcPattern
*p
, const char *object
, int id
, FcChar8
** s
)
1012 r
= FcPatternGet (p
, object
, id
, &v
);
1013 if (r
!= FcResultMatch
)
1015 if (v
.type
!= FcTypeString
)
1016 return FcResultTypeMismatch
;
1017 *s
= (FcChar8
*) v
.u
.s
;
1018 return FcResultMatch
;
1022 FcPatternGetMatrix(const FcPattern
*p
, const char *object
, int id
, FcMatrix
**m
)
1027 r
= FcPatternGet (p
, object
, id
, &v
);
1028 if (r
!= FcResultMatch
)
1030 if (v
.type
!= FcTypeMatrix
)
1031 return FcResultTypeMismatch
;
1032 *m
= (FcMatrix
*) v
.u
.m
;
1033 return FcResultMatch
;
1038 FcPatternGetBool(const FcPattern
*p
, const char *object
, int id
, FcBool
*b
)
1043 r
= FcPatternGet (p
, object
, id
, &v
);
1044 if (r
!= FcResultMatch
)
1046 if (v
.type
!= FcTypeBool
)
1047 return FcResultTypeMismatch
;
1049 return FcResultMatch
;
1053 FcPatternGetCharSet(const FcPattern
*p
, const char *object
, int id
, FcCharSet
**c
)
1058 r
= FcPatternGet (p
, object
, id
, &v
);
1059 if (r
!= FcResultMatch
)
1061 if (v
.type
!= FcTypeCharSet
)
1062 return FcResultTypeMismatch
;
1063 *c
= (FcCharSet
*) v
.u
.c
;
1064 return FcResultMatch
;
1068 FcPatternGetFTFace(const FcPattern
*p
, const char *object
, int id
, FT_Face
*f
)
1073 r
= FcPatternGet (p
, object
, id
, &v
);
1074 if (r
!= FcResultMatch
)
1076 if (v
.type
!= FcTypeFTFace
)
1077 return FcResultTypeMismatch
;
1078 *f
= (FT_Face
) v
.u
.f
;
1079 return FcResultMatch
;
1083 FcPatternGetLangSet(const FcPattern
*p
, const char *object
, int id
, FcLangSet
**ls
)
1088 r
= FcPatternGet (p
, object
, id
, &v
);
1089 if (r
!= FcResultMatch
)
1091 if (v
.type
!= FcTypeLangSet
)
1092 return FcResultTypeMismatch
;
1093 *ls
= (FcLangSet
*) v
.u
.l
;
1094 return FcResultMatch
;
1098 FcPatternDuplicate (const FcPattern
*orig
)
1104 new = FcPatternCreate ();
1108 for (i
= 0; i
< orig
->num
; i
++)
1110 for (l
= orig
->elts
[i
].values
; l
; l
= l
->next
)
1111 if (!FcPatternAdd (new, orig
->elts
[i
].object
, l
->value
, FcTrue
))
1118 FcPatternDestroy (new);
1124 FcPatternReference (FcPattern
*p
)
1126 if (p
->ref
!= FC_REF_CONSTANT
)
1131 FcPatternVaBuild (FcPattern
*orig
, va_list va
)
1135 FcPatternVapBuild (ret
, orig
, va
);
1140 FcPatternBuild (FcPattern
*orig
, ...)
1144 va_start (va
, orig
);
1145 FcPatternVapBuild (orig
, orig
, va
);
1151 * Add all of the elements in 's' to 'p'
1154 FcPatternAppend (FcPattern
*p
, FcPattern
*s
)
1160 for (i
= 0; i
< s
->num
; i
++)
1163 for (v
= e
->values
; v
; v
= v
->next
)
1165 if (!FcPatternAddWithBinding (p
, e
->object
,
1166 v
->value
, v
->binding
, FcTrue
))
1174 FcObjectStaticName (const char *name
)
1176 #define OBJECT_HASH_SIZE 31
1177 static struct objectBucket
{
1178 struct objectBucket
*next
;
1180 } *buckets
[OBJECT_HASH_SIZE
];
1181 FcChar32 hash
= FcStringHash ((const FcChar8
*) name
);
1182 struct objectBucket
**p
;
1183 struct objectBucket
*b
;
1186 for (p
= &buckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1187 if (b
->hash
== hash
&& !strcmp (name
, (char *) (b
+ 1)))
1188 return (char *) (b
+ 1);
1189 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1191 FcMemAlloc (FC_MEM_STATICSTR
, size
);
1196 strcpy ((char *) (b
+ 1), name
);
1198 return (char *) (b
+ 1);