Bug Summary

File:mkfontscale.c
Location:line 934, column 27
Description:Potential leak of memory pointed to by 'xlfd_name'

Annotated Source Code

1/*
2 Copyright (c) 2002-2003 by Juliusz Chroboczek
3
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 THE SOFTWARE.
21*/
22
23#ifdef HAVE_CONFIG_H1
24#include "config.h"
25#endif
26
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30
31#include <sys/types.h>
32#include <sys/stat.h>
33#include <dirent.h>
34#include <unistd.h>
35#include <errno(*__error()).h>
36#include <ctype.h>
37
38#include <X11/Xos.h>
39#include <X11/Xfuncproto.h>
40#include <X11/fonts/fontenc.h>
41#include <ft2build.h>
42#include FT_FREETYPE_H<freetype/freetype.h>
43#include FT_SFNT_NAMES_H<freetype/ftsnames.h>
44#include FT_TRUETYPE_TABLES_H<freetype/tttables.h>
45#include FT_TRUETYPE_IDS_H<freetype/ttnameid.h>
46#include FT_TYPE1_TABLES_H<freetype/t1tables.h>
47#include FT_BDF_H<freetype/ftbdf.h>
48#include FT_XFREE86_H<freetype/ftxf86.h>
49
50#include "list.h"
51#include "hash.h"
52#include "data.h"
53#include "ident.h"
54
55#define NPREFIX1024 1024
56
57#ifndef MAXFONTFILENAMELEN1024
58#define MAXFONTFILENAMELEN1024 1024
59#endif
60#ifndef MAXFONTNAMELEN1024
61#define MAXFONTNAMELEN1024 1024
62#endif
63
64/* Two levels of macro calls are needed so that we stringify the value
65 of MAXFONT... and not the string "MAXFONT..." */
66#define QUOTE(x)"x" #x
67#define STRINGIFY(x)"x" QUOTE(x)"x"
68
69static const char *encodings_array[] =
70 { "ascii-0",
71 "iso8859-1", "iso8859-2", "iso8859-3", "iso8859-4", "iso8859-5",
72 "iso8859-6", "iso8859-6.8", "iso8859-6.8x", "iso8859-6.16",
73 "iso8859-7", "iso8859-8", "iso8859-9", "iso8859-10",
74 "iso8859-11", "iso8859-12", "iso8859-13", "iso8859-14",
75 "iso8859-15", "iso8859-16",
76 "ansi-1251", "koi8-r", "koi8-u", "koi8-ru", "koi8-e", "koi8-uni",
77 "tis620-2",
78 "sun.unicode.india-0", "suneu-greek",
79 "adobe-standard", "adobe-symbol",
80 "ibm-cp437", "ibm-cp850", "ibm-cp852", "ibm-cp866", "microsoft-cp1252",
81 /* But not "adobe-dingbats", as it uses generic glyph names. */
82 "cns11643-1", "cns11643-2", "cns11643-3",
83 "jisx0201.1976-0", "jisx0208.1983-0", "jisx0208.1990-0",
84 "jisx0212.1990-0", "big5-0", "big5.eten-0", "big5hkscs-0",
85 "gb2312.1980-0", "gb18030.2000-0", "gb18030.2000-1",
86 "ksc5601.1987-0", "ksc5601.1992-3"};
87
88static const char *extra_encodings_array[] =
89 { "iso10646-1", "adobe-fontspecific", "microsoft-symbol" };
90
91static ListPtr encodings, extra_encodings;
92static const char *outfilename;
93
94#define countof(_a)(sizeof(_a)/sizeof((_a)[0])) (sizeof(_a)/sizeof((_a)[0]))
95
96static int doDirectory(const char*, int, ListPtr);
97static int checkEncoding(FT_Face face, char *encoding_name);
98static int checkExtraEncoding(FT_Face face, char *encoding_name, int found);
99static int find_cmap(int type, int pid, int eid, FT_Face face);
100static const char* notice_foundry(const char *notice);
101static const char* vendor_foundry(const signed char *vendor);
102static int readFontScale(HashTablePtr entries, char *dirname);
103ListPtr makeXLFD(char *filename, FT_Face face, int);
104static int readEncodings(ListPtr encodings, char *dirname);
105
106static FT_Library ft_library;
107static float bigEncodingFuzz = 0.02;
108
109static int relative;
110static int doScalable;
111static int doBitmaps;
112static int doISO10646_1_encoding;
113static int onlyEncodings;
114static ListPtr encodingsToDo;
115static int reencodeLegacy;
116static char *encodingPrefix;
117static char *exclusionSuffix;
118static char *ProgramName;
119
120static void _X_NORETURN__attribute((noreturn)) _X_COLD__attribute__((__cold__))
121usage(void)
122{
123 fprintf(stderr__stderrp, "Usage:\n"
124 "mkfontscale [ -b ] [ -s ] [ -o filename ] [-x suffix ]\n"
125 " [ -a encoding ] [ -f fuzz ] [ -l ]\n"
126 " [ -e directory ] [ -p prefix ] [ -n ] [ -r ] \n"
127 " [-u] [-U] [-v] [ directory ]...\n");
128 exit(1);
129}
130
131static void _X_NORETURN__attribute((noreturn)) _X_COLD__attribute__((__cold__))
132missing_arg (const char *option)
133{
134 fprintf(stderr__stderrp, "%s: %s requires an argument\n", ProgramName, option);
135 usage();
136}
137
138int
139main(int argc, char **argv)
140{
141 int argn;
142 FT_Error ftrc;
143 int rc, ll = 0;
144 char prefix[NPREFIX1024];
145
146 ProgramName = argv[0];
147 encodingPrefix = NULL((void*)0);
148 exclusionSuffix = NULL((void*)0);
149
150 if(getcwd(prefix, NPREFIX1024 - 1) == NULL((void*)0)) {
151 perror("Couldn't get cwd");
152 exit(1);
153 }
154 if(prefix[strlen(prefix) - 1] != '/')
155 strcat(prefix, "/")__builtin___strcat_chk (prefix, "/", __builtin_object_size (prefix
, 2 > 1 ? 1 : 0))
;
156 encodingPrefix = dsprintf("%s", prefix);
157
158 outfilename = NULL((void*)0);
159
160 encodings = makeList(encodings_array, countof(encodings_array)(sizeof(encodings_array)/sizeof((encodings_array)[0])), NULL((void*)0), 0);
161
162 extra_encodings = makeList(extra_encodings_array,
163 countof(extra_encodings_array)(sizeof(extra_encodings_array)/sizeof((extra_encodings_array)
[0]))
,
164 NULL((void*)0), 0);
165 doBitmaps = 0;
166 doISO10646_1_encoding = 1;
167 doScalable = 1;
168 onlyEncodings = 0;
169 relative = 0;
170 reencodeLegacy = 1;
171 encodingsToDo = NULL((void*)0);
172
173 argn = 1;
174 while(argn < argc) {
175 if(argv[argn][0] == '\0' || argv[argn][0] != '-')
176 break;
177 if(argv[argn][1] == '-') {
178 argn++;
179 break;
180 } else if (strcmp(argv[argn], "-x") == 0) {
181 if(argn >= argc - 1) {
182 missing_arg("-x");
183 }
184 exclusionSuffix = argv[argn + 1];
185 argn += 2;
186 } else if(strcmp(argv[argn], "-a") == 0) {
187 if(argn >= argc - 1) {
188 missing_arg("-a");
189 }
190 makeList(&argv[argn + 1], 1, encodings, 0);
191 argn += 2;
192 } else if(strcmp(argv[argn], "-p") == 0) {
193 if(argn >= argc - 1) {
194 missing_arg("-p");
195 }
196 if(strlen(argv[argn + 1]) > NPREFIX1024 - 1) {
197 fprintf(stderr__stderrp, "%s: argument to -p cannot be longer than "
198 "%d characters\n", ProgramName, NPREFIX1024 - 1);
199 usage();
200 }
201 free(encodingPrefix);
202 encodingPrefix = dsprintf("%s", argv[argn + 1]);
203 argn += 2;
204 } else if(strcmp(argv[argn], "-e") == 0) {
205 if(argn >= argc - 1) {
206 missing_arg("-e");
207 }
208 rc = readEncodings(encodingsToDo, argv[argn + 1]);
209 if(rc < 0)
210 exit(1);
211 argn += 2;
212 } else if(strcmp(argv[argn], "-b") == 0) {
213 doBitmaps = 1;
214 argn++;
215 } else if(strcmp(argv[argn], "-u") == 0) {
216 doISO10646_1_encoding = 0;
217 argn++;
218 } else if(strcmp(argv[argn], "-U") == 0) {
219 doISO10646_1_encoding = 1;
220 argn++;
221 } else if(strcmp(argv[argn], "-s") == 0) {
222 doScalable = 0;
223 argn++;
224 } else if(strcmp(argv[argn], "-n") == 0) {
225 onlyEncodings = 1;
226 argn++;
227 } else if(strcmp(argv[argn], "-r") == 0) {
228 relative = 1;
229 argn++;
230 } else if(strcmp(argv[argn], "-l") == 0) {
231 reencodeLegacy = !reencodeLegacy;
232 argn++;
233 } else if(strcmp(argv[argn], "-o") == 0) {
234 if(argn >= argc - 1) {
235 missing_arg("-o");
236 }
237 outfilename = argv[argn + 1];
238 argn += 2;
239 } else if(strcmp(argv[argn], "-f") == 0) {
240 if(argn >= argc - 1) {
241 missing_arg("-f");
242 }
243 bigEncodingFuzz = atof(argv[argn + 1]) / 100.0;
244 argn += 2;
245 } else if (strcmp(argv[argn], "-v") == 0) {
246 printf("%s\n", PACKAGE_STRING"mkfontscale 1.1.2");
247 exit(0);
248 } else {
249 usage();
250 }
251 }
252
253 if(outfilename == NULL((void*)0)) {
254 if(doBitmaps)
255 outfilename = "fonts.dir";
256 else
257 outfilename = "fonts.scale";
258 }
259
260 ftrc = FT_Init_FreeType(&ft_library);
261 if(ftrc) {
262 fprintf(stderr__stderrp, "Could not initialise FreeType library: %d\n", ftrc);
263 exit(1);
264 }
265
266 ll = listLength(encodingsToDo);
267
268 if (argn == argc)
269 doDirectory(".", ll, encodingsToDo);
270 else
271 while(argn < argc) {
272 doDirectory(argv[argn], ll, encodingsToDo);
273 argn++;
274 }
275 return 0;
276}
277
278static int
279getNameHelper(FT_Face face, int nid, int pid, int eid,
280 FT_SfntName *name_return)
281{
282 FT_SfntName name;
283 int n, i;
284
285 n = FT_Get_Sfnt_Name_Count(face);
286 if(n <= 0)
287 return 0;
288
289 for(i = 0; i < n; i++) {
290 if(FT_Get_Sfnt_Name(face, i, &name))
291 continue;
292 if(name.name_id == nid &&
293 name.platform_id == pid &&
294 (eid < 0 || name.encoding_id == eid)) {
295 switch(name.platform_id) {
296 case TT_PLATFORM_APPLE_UNICODE0:
297 case TT_PLATFORM_MACINTOSH1:
298 if(name.language_id != TT_MAC_LANGID_ENGLISH0)
299 continue;
300 break;
301 case TT_PLATFORM_MICROSOFT3:
302 if(name.language_id != TT_MS_LANGID_ENGLISH_UNITED_STATES0x0409 &&
303 name.language_id != TT_MS_LANGID_ENGLISH_UNITED_KINGDOM0x0809)
304 continue;
305 break;
306 default:
307 continue;
308 }
309 if(name.string_len > 0) {
310 *name_return = name;
311 return 1;
312 }
313 }
314 }
315 return 0;
316}
317
318static char *
319getName(FT_Face face, int nid)
320{
321 FT_SfntName name;
322 char *string;
323 int i;
324
325 if(getNameHelper(face, nid,
326 TT_PLATFORM_MICROSOFT3, TT_MS_ID_UNICODE_CS1, &name) ||
327 getNameHelper(face, nid,
328 TT_PLATFORM_APPLE_UNICODE0, -1, &name)) {
329 string = malloc(name.string_len / 2 + 1);
330 if(string == NULL((void*)0)) {
331 fprintf(stderr__stderrp, "Couldn't allocate name\n");
332 exit(1);
333 }
334 for(i = 0; i < name.string_len / 2; i++) {
335 if(name.string[2 * i] != 0)
336 string[i] = '?';
337 else
338 string[i] = name.string[2 * i + 1];
339 }
340 string[i] = '\0';
341 return string;
342 }
343
344 /* Pretend that Apple Roman is ISO 8859-1. */
345 if(getNameHelper(face, nid, TT_PLATFORM_MACINTOSH1, TT_MAC_ID_ROMAN0,
346 &name)) {
347 string = malloc(name.string_len + 1);
348 if(string == NULL((void*)0)) {
349 fprintf(stderr__stderrp, "Couldn't allocate name\n");
350 exit(1);
351 }
352 memcpy(string, name.string, name.string_len)__builtin___memcpy_chk (string, name.string, name.string_len,
__builtin_object_size (string, 0))
;
353 string[name.string_len] = '\0';
354 return string;
355 }
356
357 return NULL((void*)0);
358}
359
360static const char*
361os2Weight(int weight)
362{
363 if(weight < 150)
364 return "thin";
365 else if(weight < 250)
366 return "extralight";
367 else if(weight < 350)
368 return "light";
369 else if(weight < 450)
370 return "medium"; /* officially "normal" */
371 else if(weight < 550)
372 return "medium";
373 else if(weight < 650)
374 return "semibold";
375 else if(weight < 750)
376 return "bold";
377 else if(weight < 850)
378 return "extrabold";
379 else
380 return "black";
381}
382
383static const char*
384os2Width(int width)
385{
386 if(width <= 1)
387 return "ultracondensed";
388 else if(width <= 2)
389 return "extracondensed";
390 else if(width <= 3)
391 return "condensed";
392 else if(width <= 4)
393 return "semicondensed";
394 else if(width <= 5)
395 return "normal";
396 else if(width <= 6)
397 return "semiexpanded";
398 else if(width <= 7)
399 return "expanded";
400 else if(width <= 8)
401 return "extraexpanded";
402 else
403 return "ultraexpanded";
404}
405
406static const char *widths[] = {
407 "ultracondensed", "extracondensed", "condensed", "semicondensed",
408 "normal", "semiexpanded", "expanded", "extraexpanded", "ultraexpanded"
409};
410
411#define NUMWIDTHS(sizeof(widths) / sizeof(widths[0])) (sizeof(widths) / sizeof(widths[0]))
412
413static const char*
414nameWidth(const char *name)
415{
416 char buf[500];
417 int i;
418 int n = strlen(name);
419
420 if(n >= 499) return NULL((void*)0);
421 for(i = 0; i < n; i++)
422 buf[i] = tolower(name[i]);
423 buf[i] = '\0';
424
425 for(i = 0; i < NUMWIDTHS(sizeof(widths) / sizeof(widths[0])); i++)
426 if(strstr(buf, widths[i]))
427 return widths[i];
428 return NULL((void*)0);
429}
430
431static const char*
432t1Weight(const char *weight)
433{
434 if(!weight)
435 return NULL((void*)0);
436 if(strcmp(weight, "Thin") == 0)
437 return "thin";
438 if(strcmp(weight, "ExtraLight") == 0) /* FontForge uses this for 200*/
439 return "extralight";
440 if(strcmp(weight, "Light") == 0)
441 return "light";
442 if(strcmp(weight, "Regular") == 0)
443 return "medium";
444 if(strcmp(weight, "Normal") == 0)
445 return "medium";
446 if(strcmp(weight, "Medium") == 0)
447 return "medium";
448 if(strcmp(weight, "Book") == 0)
449 return "medium";
450 if(strcmp(weight, "Roman") == 0) /* Some URW++ fonts do that! */
451 return "medium";
452 if(strcmp(weight, "Demi") == 0)
453 return "semibold";
454 if(strcmp(weight, "DemiBold") == 0)
455 return "semibold";
456 if(strcmp(weight, "SemiBold") == 0) /* some TeX fonts apparently do that */
457 return "semibold";
458 else if(strcmp(weight, "Bold") == 0)
459 return "bold";
460 else if(strcmp(weight, "Heavy") == 0) /* FontForge uses this for 800*/
461 return "extrabold";
462 else if(strcmp(weight, "Black") == 0)
463 return "black";
464 else {
465 fprintf(stderr__stderrp, "Unknown Type 1 weight \"%s\"\n", weight);
466 return NULL((void*)0);
467 }
468}
469
470static int
471unsafe(char c)
472{
473 return
474 c < 0x20 || c > 0x7E ||
475 c == '[' || c == ']' || c == '(' || c == ')' || c == '\\' || c == '-';
476}
477
478static const char *
479safe(const char* s)
480{
481 int i, len, safe_flag = 1;
482 char *t;
483
484 i = 0;
485 while(s[i] != '\0') {
486 if(unsafe(s[i]))
487 safe_flag = 0;
488 i++;
489 }
490
491 if(safe_flag) return strdup(s);
492
493 len = i;
494 t = malloc(len + 1);
495 if(t == NULL((void*)0)) {
496 perror("Couldn't allocate string");
497 exit(1);
498 }
499
500 for(i = 0; i < len; i++) {
501 if(unsafe(s[i]))
502 t[i] = ' ';
503 else
504 t[i] = s[i];
505 }
506 t[i] = '\0';
507 return t;
508}
509
510ListPtr
511makeXLFD(char *filename, FT_Face face, int isBitmap)
512{
513 ListPtr xlfd = NULL((void*)0);
514 const char *foundry, *family, *weight, *slant, *sWidth, *adstyle,
515 *spacing, *full_name, *tmp;
516 TT_Header *head;
517 TT_HoriHeader *hhea;
518 TT_OS2 *os2;
519 TT_Postscript *post;
520 PS_FontInfoRec *t1info, t1info_rec;
521 int rc;
522
523 foundry = NULL((void*)0);
524 family = NULL((void*)0);
525 weight = NULL((void*)0);
526 slant = NULL((void*)0);
527 sWidth = NULL((void*)0);
528 adstyle = NULL((void*)0);
529 spacing = NULL((void*)0);
530 full_name = NULL((void*)0);
531
532 head = FT_Get_Sfnt_Table(face, ft_sfnt_head);
533 hhea = FT_Get_Sfnt_Table(face, ft_sfnt_hhea);
534 os2 = FT_Get_Sfnt_Table(face, ft_sfnt_os2);
535 post = FT_Get_Sfnt_Table(face, ft_sfnt_post);
536
537 rc = FT_Get_PS_Font_Info(face, &t1info_rec);
538 if(rc == 0)
539 t1info = &t1info_rec;
540 else
541 t1info = NULL((void*)0);
542
543 if(!family)
544 family = getName(face, TT_NAME_ID_FONT_FAMILY1);
545 if(!family)
546 family = getName(face, TT_NAME_ID_FULL_NAME4);
547 if(!family)
548 family = getName(face, TT_NAME_ID_PS_NAME6);
549
550 if(!full_name)
551 full_name = getName(face, TT_NAME_ID_FULL_NAME4);
552 if(!full_name)
553 full_name = getName(face, TT_NAME_ID_PS_NAME6);
554
555 if(os2 && os2->version != 0xFFFF) {
556 if(!weight)
557 weight = os2Weight(os2->usWeightClass);
558 if(!sWidth)
559 sWidth = os2Width(os2->usWidthClass);
560 if(!foundry)
561 foundry = vendor_foundry(os2->achVendID);
562 if(!slant)
563 slant = os2->fsSelection & 1 ? "i" : "r";
564 }
565
566 if(post) {
567 if(!spacing) {
568 if(post->isFixedPitch) {
569 if(hhea->min_Left_Side_Bearing >= 0 &&
570 hhea->xMax_Extent <= hhea->advance_Width_Max) {
571 spacing = "c";
572 } else {
573 spacing = "m";
574 }
575 } else {
576 spacing = "p";
577 }
578 }
579 }
580
581 if(t1info) {
582 if(!family && t1info->family_name)
583 family = strdup(t1info->family_name);
584 if(!family && t1info->full_name)
585 family = strdup(t1info->full_name);
586 /* Hershey fonts miss /FamilyName */
587 if(!family && face->family_name)
588 family = strdup(face->family_name);
589 if(!full_name && t1info->full_name)
590 full_name = strdup(t1info->full_name);
591 if(!foundry)
592 foundry = notice_foundry(t1info->notice);
593 if(!weight)
594 weight = t1Weight(t1info->weight);
595 if(!spacing)
596 spacing = t1info->is_fixed_pitch ? "m" : "p";
597 if(!slant) {
598 /* Bitstream fonts have positive italic angle. */
599 slant =
600 t1info->italic_angle <= -4 || t1info->italic_angle >= 4 ?
601 "i" : "r";
602 }
603 }
604
605 if(!full_name) {
606 fprintf(stderr__stderrp, "Couldn't determine full name for %s\n", filename);
607 full_name = strdup(filename);
608 }
609
610 if(head) {
611 if(!slant)
612 slant = head->Mac_Style & 2 ? "i" : "r";
613 if(!weight)
614 weight = head->Mac_Style & 1 ? "bold" : "medium";
615 }
616
617 if(!slant) {
618 fprintf(stderr__stderrp, "Couldn't determine slant for %s\n", filename);
619 slant = "r";
620 }
621
622 if(!weight) {
623 fprintf(stderr__stderrp, "Couldn't determine weight for %s\n", filename);
624 weight = "medium";
625 }
626
627 if(!foundry) {
628 char *notice;
629 notice = getName(face, TT_NAME_ID_TRADEMARK7);
630 if(notice) {
631 foundry = notice_foundry(notice);
632 free(notice);
633 }
634 if(!foundry) {
635 notice = getName(face, TT_NAME_ID_MANUFACTURER8);
636 if(notice) {
637 foundry = notice_foundry(notice);
638 free(notice);
639 }
640 }
641 }
642
643 if(strcmp(slant, "i") == 0) {
644 if(strstr(full_name, "Oblique"))
645 slant = "o";
646 if(strstr(full_name, "Slanted"))
647 slant = "o";
648 }
649
650 if(!sWidth)
651 sWidth = nameWidth(full_name);
652
653 if(!foundry) foundry = "misc";
654 if(!family) {
655 fprintf(stderr__stderrp, "Couldn't get family name for %s\n", filename);
656 family = strdup(filename);
657 }
658
659 if(!weight) weight = "medium";
660 if(!slant) slant = "r";
661 if(!sWidth) sWidth = "normal";
662 if(!adstyle) adstyle = "";
663 if(!spacing) spacing = "p";
664
665 foundry = safe(foundry);
666
667 tmp = family;
668 family = safe(family);
669 free((void *)tmp);
670
671 if(!isBitmap) {
672 xlfd = listConsF(xlfd,
673 "-%s-%s-%s-%s-%s-%s-0-0-0-0-%s-0",
674 foundry, family,
675 weight, slant, sWidth, adstyle, spacing);
676 } else {
677 int i, w, h, xres, yres;
678 for(i = 0; i < face->num_fixed_sizes; i++) {
679 w = face->available_sizes[i].width;
680 h = face->available_sizes[i].height;
681 xres = 75;
682 yres = (double)h / w * xres;
683 xlfd = listConsF(xlfd,
684 "-%s-%s-%s-%s-%s-%s-%d-%d-%d-%d-%s-%d",
685 foundry, family,
686 weight, slant, sWidth, adstyle,
687 h, (int)(h / (double)yres * 72.27 * 10 + 0.5),
688 xres, yres,
689 spacing, 60);
690 }
691 }
692
693 free((void *)family);
694 free((void *)foundry);
695 free((void *)full_name);
696 return xlfd;
697}
698
699static int
700readFontScale(HashTablePtr entries, char *dirname)
701{
702 int n = strlen(dirname);
703 char *filename;
704 FILE *in;
705 int rc, count, i;
706 char file[MAXFONTFILENAMELEN1024+1], font[MAXFONTNAMELEN1024+1];
707
708 if(dirname[n - 1] == '/')
709 filename = dsprintf("%sfonts.scale", dirname);
710 else
711 filename = dsprintf("%s/fonts.scale", dirname);
712 if(filename == NULL((void*)0))
713 return -1;
714
715 in = fopen(filename, "r");
716 free(filename);
717 if(in == NULL((void*)0)) {
718 if(errno(*__error()) != ENOENT2)
719 perror("open(fonts.scale)");
720 return -1;
721 }
722
723 rc = fscanf(in, "%d\n", &count);
724 if(rc != 1) {
725 fprintf(stderr__stderrp, "Invalid fonts.scale in %s.\n", dirname);
726 fclose(in);
727 return -1;
728 }
729
730 for(i = 0; i < count; i++) {
731 rc = fscanf(in,
732 "%" STRINGIFY(MAXFONTFILENAMELEN)"1024" "s "
733 "%" STRINGIFY(MAXFONTNAMELEN)"1024" "[^\n]\n",
734 file, font);
735 if(rc != 2)
736 break;
737 putHash(entries, font, file, 100);
738 }
739 fclose(in);
740 return 1;
741}
742
743static int
744filePrio(char *filename)
745{
746 int n = strlen(filename);
747 if(n < 4)
748 return 0;
749 if(strcmp(filename + n - 4, ".otf") == 0)
750 return 6;
751 if(strcmp(filename + n - 4, ".OTF") == 0)
752 return 6;
753 if(strcmp(filename + n - 4, ".ttf") == 0)
754 return 5;
755 if(strcmp(filename + n - 4, ".TTF") == 0)
756 return 5;
757 if(strcmp(filename + n - 4, ".pcf") == 0)
758 return 4;
759 if(strcmp(filename + n - 4, ".PCF") == 0)
760 return 4;
761 if(strcmp(filename + n - 3, ".gz") == 0)
762 return 3;
763#ifdef X_BZIP2_FONT_COMPRESSION
764 if(strcmp(filename + n - 4, ".bz2") == 0)
765 return 2;
766#endif
767 if(strcmp(filename + n - 2, ".Z") == 0)
768 return 2;
769 if(strcmp(filename + n - 4, ".bdf") == 0)
770 return 1;
771 if(strcmp(filename + n - 4, ".BDF") == 0)
772 return 1;
773 return 0;
774}
775
776static int
777doDirectory(const char *dirname_given, int numEncodings, ListPtr encodingsToDo)
778{
779 char *dirname, *fontscale_name, *filename, *encdir;
780 FILE *fontscale, *encfile;
781 DIR *dirp;
782 struct dirent *entry;
783 FT_Error ftrc;
784 FT_Face face;
785 ListPtr encoding, xlfd, lp;
786 HashTablePtr entries;
787 HashBucketPtr *array;
788 int i, n, found, rc;
789 int isBitmap=0,xl=0;
790
791 if (exclusionSuffix)
1
Assuming 'exclusionSuffix' is null
2
Taking false branch
792 xl = strlen (exclusionSuffix);
793
794 i = strlen(dirname_given);
795 if(i == 0)
3
Assuming 'i' is not equal to 0
4
Taking false branch
796 dirname = dsprintf("./");
797 else if(dirname_given[i - 1] != '/')
5
Taking false branch
798 dirname = dsprintf("%s/", dirname_given);
799 else
800 dirname = dsprintf("%s", dirname_given);
801
802 if(dirname == NULL((void*)0)) {
6
Assuming 'dirname' is not equal to null
7
Taking false branch
803 perror("dirname");
804 exit(1);
805 }
806
807 if (onlyEncodings)
8
Assuming 'onlyEncodings' is 0
9
Taking false branch
808 goto encodings;
809
810 entries = makeHashTable();
811 if(doBitmaps && !doScalable) {
812 readFontScale(entries, dirname);
813 }
814
815 if(strcmp(outfilename, "-") == 0)
10
Taking false branch
816 fontscale_name = NULL((void*)0);
817 else {
818 if(outfilename[0] == '/')
11
Taking false branch
819 fontscale_name = dsprintf("%s", outfilename);
820 else
821 fontscale_name = dsprintf("%s%s", dirname, outfilename);
822 if(fontscale_name == NULL((void*)0)) {
12
Assuming 'fontscale_name' is not equal to null
13
Taking false branch
823 perror("fontscale_name");
824 exit(1);
825 }
826 }
827
828 dirp = opendir(dirname);
829 if(dirp == NULL((void*)0)) {
14
Assuming 'dirp' is not equal to null
15
Taking false branch
830 fprintf(stderr__stderrp, "%s: ", dirname);
831 perror("opendir");
832 return 0;
833 }
834
835 if(fontscale_name == NULL((void*)0))
16
Taking false branch
836 fontscale = stdout__stdoutp;
837 else
838 fontscale = fopen(fontscale_name, "wb");
839
840 if(fontscale == NULL((void*)0)) {
17
Assuming 'fontscale' is not equal to null
18
Taking false branch
841 fprintf(stderr__stderrp, "%s: ", fontscale_name);
842 perror("fopen(w)");
843 return 0;
844 }
845
846 while((entry = readdir(dirp)) != NULL((void*)0)) {
19
Loop condition is true. Entering loop body
40
Loop condition is true. Entering loop body
61
Loop condition is true. Entering loop body
82
Loop condition is true. Entering loop body
847 int have_face = 0;
848 char *xlfd_name = NULL((void*)0);
849 struct stat f_stat;
850 int tprio = 1;
851
852 xlfd = NULL((void*)0);
853
854 if (xl) {
20
Taking false branch
41
Taking false branch
62
Taking false branch
83
Taking false branch
855 int dl = strlen (entry->d_name);
856 if (strcmp (entry->d_name + dl - xl, exclusionSuffix) == 0)
857 continue;
858 }
859
860 filename = dsprintf("%s%s", dirname, entry->d_name);
861
862#define PRIO(x) ((x << 1) + tprio)
863#ifdef DT_LNK10
864 if (entry->d_type != DT_UNKNOWN0) {
21
Taking false branch
42
Taking false branch
63
Taking false branch
84
Taking false branch
865 if (entry->d_type == DT_LNK10)
866 tprio = 0;
867 } else
868#endif
869#ifdef S_ISLNK
870 {
871 if (lstat(filename, &f_stat))
22
Taking false branch
43
Taking false branch
64
Taking false branch
85
Taking false branch
872 goto done;
873 if (S_ISLNK(f_stat.st_mode)(((f_stat.st_mode) & 0170000) == 0120000))
23
Taking false branch
44
Taking false branch
65
Taking false branch
86
Taking false branch
874 tprio = 0;
875 }
876#else
877 ;
878#endif
879 if(doBitmaps)
24
Assuming 'doBitmaps' is 0
25
Taking false branch
45
Assuming 'doBitmaps' is 0
46
Taking false branch
66
Assuming 'doBitmaps' is 0
67
Taking false branch
87
Assuming 'doBitmaps' is 0
88
Taking false branch
880 rc = bitmapIdentify(filename, &xlfd_name);
881 else
882 rc = 0;
883
884 if(rc < 0)
26
Taking false branch
47
Taking false branch
68
Taking false branch
89
Taking false branch
885 goto done;
886
887 if(rc == 0) {
27
Taking true branch
48
Taking true branch
69
Taking true branch
90
Taking true branch
888 ftrc = FT_New_Face(ft_library, filename, 0, &face);
889 if(ftrc)
28
Assuming 'ftrc' is 0
29
Taking false branch
49
Assuming 'ftrc' is 0
50
Taking false branch
70
Assuming 'ftrc' is 0
71
Taking false branch
91
Assuming 'ftrc' is 0
92
Taking false branch
890 goto done;
891 have_face = 1;
892
893 isBitmap = ((face->face_flags & FT_FACE_FLAG_SCALABLE( 1L << 0 )) == 0);
894
895 if(!isBitmap) {
30
Taking true branch
51
Taking true branch
72
Taking true branch
93
Taking true branch
896 /* Workaround for bitmap-only SFNT fonts */
897 if(FT_IS_SFNT(face)( face->face_flags & ( 1L << 3 ) ) && face->num_fixed_sizes > 0 &&
94
Taking true branch
898 strcmp(FT_Get_X11_Font_Format(face), "TrueType") == 0) {
899 TT_MaxProfile *maxp;
900 maxp = FT_Get_Sfnt_Table(face, ft_sfnt_maxp);
901 if(maxp != NULL((void*)0) && maxp->maxContours == 0)
95
Assuming 'maxp' is not equal to null
96
Taking true branch
902 isBitmap = 1;
903 }
904 }
905
906 if(isBitmap) {
31
Taking false branch
52
Taking false branch
73
Taking false branch
97
Taking true branch
907 if(!doBitmaps)
98
Assuming 'doBitmaps' is not equal to 0
99
Taking false branch
908 goto done;
909 } else {
910 if(!doScalable)
32
Assuming 'doScalable' is not equal to 0
33
Taking false branch
53
Assuming 'doScalable' is not equal to 0
54
Taking false branch
74
Assuming 'doScalable' is not equal to 0
75
Taking false branch
911 goto done;
912 }
913
914 if(isBitmap) {
34
Taking false branch
55
Taking false branch
76
Taking false branch
100
Taking true branch
915 BDF_PropertyRec prop;
916 rc = FT_Get_BDF_Property(face, "FONT", &prop);
917 if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_ATOM) {
101
Assuming 'rc' is equal to 0
102
Taking true branch
918 xlfd_name = strdup(prop.u.atom);
103
Memory is allocated
919 if(xlfd_name == NULL((void*)0))
104
Assuming 'xlfd_name' is not equal to null
105
Taking false branch
920 goto done;
921 }
922 }
923 }
924
925 if(xlfd_name) {
35
Taking false branch
56
Taking false branch
77
Taking false branch
106
Taking true branch
926 /* We know it's a bitmap font, and we know its XLFD */
927 int n = strlen(xlfd_name);
928 if(reencodeLegacy &&
108
Taking true branch
929 n >= 12 && strcasecmp(xlfd_name + n - 11, "-iso10646-1") == 0) {
107
Assuming 'n' is >= 12
930 char *s;
931
932 s = malloc(n - 10);
933 memcpy(s, xlfd_name, n - 11)__builtin___memcpy_chk (s, xlfd_name, n - 11, __builtin_object_size
(s, 0))
;
934 s[n - 11] = '\0';
109
Potential leak of memory pointed to by 'xlfd_name'
935 xlfd = listCons(s, xlfd);
936 } else {
937 /* Not a reencodable font -- skip all the rest of the loop body */
938 putHash(entries, xlfd_name, entry->d_name, PRIO(filePrio(entry->d_name)));
939 goto done;
940 }
941 }
942
943 if(!have_face) {
36
Taking false branch
57
Taking false branch
78
Taking false branch
944 ftrc = FT_New_Face(ft_library, filename, 0, &face);
945 if(ftrc)
946 goto done;
947 have_face = 1;
948 isBitmap = ((face->face_flags & FT_FACE_FLAG_SCALABLE( 1L << 0 )) == 0);
949
950 if(!isBitmap) {
951 if(face->num_fixed_sizes > 0) {
952 TT_MaxProfile *maxp;
953 maxp = FT_Get_Sfnt_Table(face, ft_sfnt_maxp);
954 if(maxp != NULL((void*)0) && maxp->maxContours == 0)
955 isBitmap = 1;
956 }
957 }
958 }
959
960 if(xlfd == NULL((void*)0))
37
Taking true branch
58
Taking true branch
79
Taking true branch
961 xlfd = makeXLFD(entry->d_name, face, isBitmap);
962
963 found = 0;
964
965 for(lp = xlfd; lp; lp = lp->next) {
38
Loop condition is false. Execution continues on line 986
59
Loop condition is false. Execution continues on line 986
80
Loop condition is false. Execution continues on line 986
966 char buf[MAXFONTNAMELEN1024];
967 for(encoding = encodings; encoding; encoding = encoding->next) {
968 if(checkEncoding(face, encoding->value)) {
969 found = 1;
970 snprintf(buf, MAXFONTNAMELEN, "%s-%s",__builtin___snprintf_chk (buf, 1024, 0, __builtin_object_size
(buf, 2 > 1 ? 1 : 0), "%s-%s", lp->value, encoding->
value)
971 lp->value, encoding->value)__builtin___snprintf_chk (buf, 1024, 0, __builtin_object_size
(buf, 2 > 1 ? 1 : 0), "%s-%s", lp->value, encoding->
value)
;
972 putHash(entries, buf, entry->d_name, PRIO(filePrio(entry->d_name)));
973 }
974 }
975 for(encoding = extra_encodings; encoding;
976 encoding = encoding->next) {
977 if(checkExtraEncoding(face, encoding->value, found)) {
978 /* Do not set found! */
979 snprintf(buf, MAXFONTNAMELEN, "%s-%s",__builtin___snprintf_chk (buf, 1024, 0, __builtin_object_size
(buf, 2 > 1 ? 1 : 0), "%s-%s", lp->value, encoding->
value)
980 lp->value, encoding->value)__builtin___snprintf_chk (buf, 1024, 0, __builtin_object_size
(buf, 2 > 1 ? 1 : 0), "%s-%s", lp->value, encoding->
value)
;
981 putHash(entries, buf, entry->d_name, PRIO(filePrio(entry->d_name)));
982 }
983 }
984 }
985 done:
986 if(have_face)
39
Taking true branch
60
Taking true branch
81
Taking true branch
987 FT_Done_Face(face);
988 deepDestroyList(xlfd);
989 xlfd = NULL((void*)0);
990 free(filename);
991#undef PRIO
992 }
993
994 closedir(dirp);
995 n = hashElements(entries);
996 fprintf(fontscale, "%d\n", n);
997 array = hashArray(entries, 1);
998 for(i = 0; i < n; i++)
999 fprintf(fontscale, "%s %s\n", array[i]->value, array[i]->key);
1000 destroyHashArray(array);
1001 entries = NULL((void*)0);
1002 if(fontscale_name) {
1003 fclose(fontscale);
1004 free(fontscale_name);
1005 }
1006
1007 encodings:
1008 encdir = dsprintf("%s%s", dirname, "encodings.dir");
1009
1010 if(encdir == NULL((void*)0)) {
1011 perror("encodings");
1012 exit(1);
1013 }
1014 unlink(encdir);
1015
1016 if (numEncodings) {
1017 encfile = fopen(encdir, "w");
1018 if(encfile == NULL((void*)0)) {
1019 perror("open(encodings.dir)");
1020 exit(1);
1021 }
1022 fprintf(encfile, "%d\n", numEncodings);
1023 encodingsToDo = sortList(encodingsToDo);
1024 for(lp = encodingsToDo; lp; lp = lp->next) {
1025 fprintf(encfile, "%s\n", lp->value);
1026 }
1027 fclose (encfile);
1028 }
1029
1030 free(dirname);
1031 return 1;
1032}
1033
1034#define CODE_IGNORED(c)((c) < 0x20 || ((c) >= 0x7F && (c) <= 0xA0) ||
(c) == 0xAD || (c) == 0xF71B)
((c) < 0x20 || \
1035 ((c) >= 0x7F && (c) <= 0xA0) || \
1036 (c) == 0xAD || (c) == 0xF71B)
1037
1038static int
1039checkEncoding(FT_Face face, char *encoding_name)
1040{
1041 FontEncPtr encoding;
1042 FontMapPtr mapping;
1043 int i, j, c, koi8;
1044 char *n;
1045
1046 encoding = FontEncFind(encoding_name, NULL((void*)0));
1047 if(!encoding)
1048 return 0;
1049
1050 /* An encoding is ``small'' if one of the following is true:
1051 - it is linear and has no more than 256 codepoints; or
1052 - it is a matrix encoding and has no more than one column.
1053
1054 For small encodings using Unicode indices, we require perfect
1055 coverage except for CODE_IGNORED and KOI-8 IBM-PC compatibility.
1056
1057 For large encodings, we require coverage up to bigEncodingFuzz.
1058
1059 For encodings using PS names (currently Adobe Standard and
1060 Adobe Symbol only), we require perfect coverage. */
1061
1062
1063 if(FT_Has_PS_Glyph_Names(face)) {
1064 for(mapping = encoding->mappings; mapping; mapping = mapping->next) {
1065 if(mapping->type == FONT_ENCODING_POSTSCRIPT3) {
1066 if(encoding->row_size > 0) {
1067 for(i = encoding->first; i < encoding->size; i++) {
1068 for(j = encoding->first_col;
1069 j < encoding->row_size;
1070 j++) {
1071 n = FontEncName((i<<8) | j, mapping);
1072 if(n && FT_Get_Name_Index(face, n) == 0) {
1073 return 0;
1074 }
1075 }
1076 }
1077 return 1;
1078 } else {
1079 for(i = encoding->first; i < encoding->size; i++) {
1080 n = FontEncName(i, mapping);
1081 if(n && FT_Get_Name_Index(face, n) == 0) {
1082 return 0;
1083 }
1084 }
1085 return 1;
1086 }
1087 }
1088 }
1089 }
1090
1091 for(mapping = encoding->mappings; mapping; mapping = mapping->next) {
1092 if(find_cmap(mapping->type, mapping->pid, mapping->eid, face)) {
1093 int total = 0, failed = 0;
1094 if(encoding->row_size > 0) {
1095 int estimate =
1096 (encoding->size - encoding->first) *
1097 (encoding->row_size - encoding->first_col);
1098 for(i = encoding->first; i < encoding->size; i++) {
1099 for(j = encoding->first_col;
1100 j < encoding->row_size;
1101 j++) {
1102 c = FontEncRecode((i<<8) | j, mapping);
1103 if(CODE_IGNORED(c)((c) < 0x20 || ((c) >= 0x7F && (c) <= 0xA0) ||
(c) == 0xAD || (c) == 0xF71B)
) {
1104 continue;
1105 } else {
1106 if(FT_Get_Char_Index(face, c) == 0) {
1107 failed++;
1108 }
1109 total++;
1110 if((encoding->size <= 1 && failed > 0) ||
1111 ((float)failed >= bigEncodingFuzz * estimate)) {
1112 return 0;
1113 }
1114 }
1115 }
1116 }
1117 if((float)failed >= total * bigEncodingFuzz)
1118 return 0;
1119 else
1120 return 1;
1121 } else {
1122 int estimate = encoding->size - encoding->first;
1123 /* For the KOI8 encodings, we ignore the lack of
1124 linedrawing and pseudo-math characters */
1125 if(strncmp(encoding->name, "koi8-", 5) == 0)
1126 koi8 = 1;
1127 else
1128 koi8 = 0;
1129 for(i = encoding->first; i < encoding->size; i++) {
1130 c = FontEncRecode(i, mapping);
1131 if(CODE_IGNORED(c)((c) < 0x20 || ((c) >= 0x7F && (c) <= 0xA0) ||
(c) == 0xAD || (c) == 0xF71B)
||
1132 (koi8 && ((c >= 0x2200 && c < 0x2600) || c == 0x00b2))) {
1133 continue;
1134 } else {
1135 if(FT_Get_Char_Index(face, c) == 0) {
1136 failed++;
1137 }
1138 total++;
1139 if((encoding->size <= 256 && failed > 0) ||
1140 ((float)failed >= bigEncodingFuzz * estimate)) {
1141 return 0;
1142 }
1143 }
1144 }
1145 if((float)failed >= total * bigEncodingFuzz)
1146 return 0;
1147 else
1148 return 1;
1149 }
1150 }
1151 }
1152 return 0;
1153}
1154
1155static int
1156find_cmap(int type, int pid, int eid, FT_Face face)
1157{
1158 int i, n, rc;
1159 FT_CharMap cmap = NULL((void*)0);
1160
1161 n = face->num_charmaps;
1162
1163 switch(type) {
1164 case FONT_ENCODING_TRUETYPE2: /* specific cmap */
1165 for(i=0; i<n; i++) {
1166 cmap = face->charmaps[i];
1167 if(cmap->platform_id == pid && cmap->encoding_id == eid) {
1168 rc = FT_Set_Charmap(face, cmap);
1169 if(rc == 0)
1170 return 1;
1171 }
1172 }
1173 break;
1174 case FONT_ENCODING_UNICODE1: /* any Unicode cmap */
1175 /* prefer Microsoft Unicode */
1176 for(i=0; i<n; i++) {
1177 cmap = face->charmaps[i];
1178 if(cmap->platform_id == TT_PLATFORM_MICROSOFT3 &&
1179 cmap->encoding_id == TT_MS_ID_UNICODE_CS1) {
1180 rc = FT_Set_Charmap(face, cmap);
1181 if(rc == 0)
1182 return 1;
1183 }
1184 }
1185 /* Try Apple Unicode */
1186 for(i=0; i<n; i++) {
1187 cmap = face->charmaps[i];
1188 if(cmap->platform_id == TT_PLATFORM_APPLE_UNICODE0) {
1189 rc = FT_Set_Charmap(face, cmap);
1190 if(rc == 0)
1191 return 1;
1192 }
1193 }
1194 /* ISO Unicode? */
1195 for(i=0; i<n; i++) {
1196 cmap = face->charmaps[i];
1197 if(cmap->platform_id == TT_PLATFORM_ISO2) {
1198 rc = FT_Set_Charmap(face, cmap);
1199 if(rc == 0)
1200 return 1;
1201 }
1202 }
1203 break;
1204 default:
1205 return 0;
1206 }
1207 return 0;
1208}
1209
1210static int
1211checkExtraEncoding(FT_Face face, char *encoding_name, int found)
1212{
1213 int c;
1214
1215 if(strcasecmp(encoding_name, "iso10646-1") == 0) {
1216 if(doISO10646_1_encoding && find_cmap(FONT_ENCODING_UNICODE1, -1, -1, face)) {
1217 int found = 0;
1218 /* Export as Unicode if there are at least 15 BMP
1219 characters that are not a space or ignored. */
1220 for(c = 0x21; c < 0x10000; c++) {
1221 if(CODE_IGNORED(c)((c) < 0x20 || ((c) >= 0x7F && (c) <= 0xA0) ||
(c) == 0xAD || (c) == 0xF71B)
)
1222 continue;
1223 if(FT_Get_Char_Index(face, c) > 0)
1224 found++;
1225 if(found >= 15)
1226 return 1;
1227 }
1228 return 0;
1229 } else
1230 return 0;
1231 } else if(strcasecmp(encoding_name, "microsoft-symbol") == 0) {
1232 if(find_cmap(FONT_ENCODING_TRUETYPE2,
1233 TT_PLATFORM_MICROSOFT3, TT_MS_ID_SYMBOL_CS0,
1234 face))
1235 return 1;
1236 else
1237 return 0;
1238 } else if(strcasecmp(encoding_name, "adobe-fontspecific") == 0) {
1239 if(!found) {
1240 if(FT_Has_PS_Glyph_Names(face))
1241 return 1;
1242 else
1243 return 0;
1244 } else
1245 return 0;
1246 } else {
1247 fprintf(stderr__stderrp, "Unknown extra encoding %s\n", encoding_name);
1248 return 0;
1249 }
1250}
1251
1252static const char*
1253notice_foundry(const char *notice)
1254{
1255 int i;
1256 for(i = 0; i < countof(notice_foundries)(sizeof(notice_foundries)/sizeof((notice_foundries)[0])); i++)
1257 if(notice && strstr(notice, notice_foundries[i][0]))
1258 return notice_foundries[i][1];
1259 return NULL((void*)0);
1260}
1261
1262static int
1263vendor_match(const signed char *vendor, const char *vendor_string)
1264{
1265 /* vendor is not necessarily NUL-terminated. */
1266 int i, len;
1267 len = strlen(vendor_string);
1268 if(memcmp(vendor, vendor_string, len) != 0)
1269 return 0;
1270 for(i = len; i < 4; i++)
1271 if(vendor[i] != ' ' && vendor[i] != '\0')
1272 return 0;
1273 return 1;
1274}
1275
1276static const char*
1277vendor_foundry(const signed char *vendor)
1278{
1279 int i;
1280 for(i = 0; i < countof(vendor_foundries)(sizeof(vendor_foundries)/sizeof((vendor_foundries)[0])); i++)
1281 if(vendor_match(vendor, vendor_foundries[i][0]))
1282 return vendor_foundries[i][1];
1283 return NULL((void*)0);
1284}
1285
1286static int
1287readEncodings(ListPtr encodings, char *dirname)
1288{
1289 char *fullname;
1290 DIR *dirp;
1291 struct dirent *file;
1292 char **names, **name;
1293
1294 if(strlen(dirname) > 1 && dirname[strlen(dirname) - 1] == '/')
1295 dirname[strlen(dirname) - 1] = '\0';
1296
1297 dirp = opendir(dirname);
1298 if(dirp == NULL((void*)0)) {
1299 perror("opendir");
1300 return -1;
1301 }
1302
1303 while((file = readdir(dirp)) != NULL((void*)0)) {
1304 fullname = dsprintf("%s/%s", dirname, file->d_name);
1305 if(fullname == NULL((void*)0)) {
1306 fprintf(stderr__stderrp, "Couldn't allocate fullname\n");
1307 closedir(dirp);
1308 return -1;
1309 }
1310
1311 names = FontEncIdentify(fullname);
1312 if(!names)
1313 continue;
1314
1315 for(name = names; *name; name++) {
1316 if(fullname[0] != '/' && !relative) {
1317 char *n;
1318 n = dsprintf("%s%s", encodingPrefix, fullname);
1319 if(n == NULL((void*)0)) {
1320 fprintf(stderr__stderrp, "Couldn't allocate name\n");
1321 closedir(dirp);
1322 return -1;
1323 }
1324 encodingsToDo = listConsF(encodingsToDo, "%s %s", *name, n);
1325 free(n);
1326 } else {
1327 encodingsToDo =
1328 listConsF(encodingsToDo, "%s %s", *name, fullname);
1329 }
1330 if(encodingsToDo == NULL((void*)0)) {
1331 fprintf(stderr__stderrp, "Couldn't allocate encodings\n");
1332 closedir(dirp);
1333 return -1;
1334 }
1335 }
1336 free(names); /* only the spine */
1337 }
1338 closedir(dirp);
1339 return 0;
1340}