File: | ucs2any.c |
Location: | line 777, column 24 |
Description: | Null pointer argument in call to string comparison function |
1 | /*- | |||
2 | * Copyright (c) 2003 The NetBSD Foundation, Inc. | |||
3 | * All rights reserved. | |||
4 | * | |||
5 | * This code is derived from software contributed to The NetBSD Foundation | |||
6 | * by Ben Collver <collver1@attbi.com>. | |||
7 | * | |||
8 | * Redistribution and use in source and binary forms, with or without | |||
9 | * modification, are permitted provided that the following conditions | |||
10 | * are met: | |||
11 | * 1. Redistributions of source code must retain the above copyright | |||
12 | * notice, this list of conditions and the following disclaimer. | |||
13 | * 2. Redistributions in binary form must reproduce the above copyright | |||
14 | * notice, this list of conditions and the following disclaimer in the | |||
15 | * documentation and/or other materials provided with the distribution. | |||
16 | * | |||
17 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |||
18 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |||
19 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |||
20 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |||
21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |||
22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |||
23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |||
24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |||
25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |||
26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |||
27 | * POSSIBILITY OF SUCH DAMAGE. | |||
28 | */ | |||
29 | /* | |||
30 | * This utility allows you to generate from an ISO10646-1 encoded | |||
31 | * BDF font other BDF fonts in any possible encoding. This way, you can | |||
32 | * derive from a single ISO10646-1 master font a whole set of 8-bit | |||
33 | * fonts in all ISO 8859 and various other encodings. (Hopefully | |||
34 | * a future XFree86 release will have a similar facility built into | |||
35 | * the server, which can reencode ISO10646-1 on the fly, because | |||
36 | * storing the same fonts in many different encodings is clearly | |||
37 | * a waste of storage capacity). | |||
38 | */ | |||
39 | ||||
40 | #include <ctype.h> | |||
41 | #include <errno(*__error()).h> | |||
42 | #include <fcntl.h> | |||
43 | #if !defined(NEED_BASENAME) && !defined(Lynx) | |||
44 | #include <libgen.h> | |||
45 | #endif | |||
46 | #include <limits.h> | |||
47 | #include <stdarg.h> | |||
48 | #include <stdio.h> | |||
49 | #include <stdlib.h> | |||
50 | #include <string.h> | |||
51 | #include <unistd.h> | |||
52 | ||||
53 | /* global variable for argv[0] */ | |||
54 | static const char *my_name = NULL((void *)0); | |||
55 | ||||
56 | #ifdef NEED_BASENAME | |||
57 | static char * | |||
58 | basename(char *pathname) | |||
59 | { | |||
60 | char *ptr; | |||
61 | ||||
62 | ptr = strrchr(pathname, '/'); | |||
63 | return ((ptr == NULL((void *)0)) ? pathname : &ptr[1]); | |||
64 | } | |||
65 | #endif | |||
66 | ||||
67 | /* "CLASS" "z" string and memory manipulation */ | |||
68 | ||||
69 | static void * | |||
70 | zmalloc(size_t size) | |||
71 | { | |||
72 | void *r; | |||
73 | r = malloc(size); | |||
74 | if (r == NULL((void *)0)) { | |||
75 | perror(my_name); | |||
76 | exit(errno(*__error())); | |||
77 | } | |||
78 | memset(r, 0, size)__builtin___memset_chk (r, 0, size, __builtin_object_size (r, 0)); | |||
79 | return r; | |||
80 | } | |||
81 | ||||
82 | static void * | |||
83 | zrealloc(void *ptr, size_t size) | |||
84 | { | |||
85 | void *temp; | |||
86 | temp = realloc(ptr, size); | |||
87 | if (temp == NULL((void *)0)) { | |||
88 | perror(my_name); | |||
89 | exit(errno(*__error())); | |||
90 | } | |||
91 | return temp; | |||
92 | } | |||
93 | ||||
94 | static char * | |||
95 | zstrdup(const char *str) | |||
96 | { | |||
97 | char *retval; | |||
98 | ||||
99 | if (str == NULL((void *)0)) { | |||
100 | fprintf(stderr__stderrp, "%s: zstrdup(NULL)\n", my_name); | |||
101 | exit(1); | |||
102 | } | |||
103 | retval = strdup(str); | |||
104 | if (retval == NULL((void *)0)) { | |||
105 | perror(my_name); | |||
106 | exit(errno(*__error())); | |||
107 | } | |||
108 | return retval; | |||
109 | } | |||
110 | ||||
111 | static void | |||
112 | zstrcpy(char **dest, const char *source) | |||
113 | { | |||
114 | if (*dest != NULL((void *)0)) | |||
115 | free(*dest); | |||
116 | *dest = zstrdup(source); | |||
117 | } | |||
118 | ||||
119 | static void | |||
120 | zquotedcpy(char **dest, const char *source) | |||
121 | { | |||
122 | const char *start, *end; | |||
123 | ||||
124 | if (*dest != NULL((void *)0)) | |||
125 | free(*dest); | |||
126 | *dest = NULL((void *)0); | |||
127 | start = source; | |||
128 | if (*start == '"') { | |||
129 | start = source+1; | |||
130 | end = strrchr(start, '"'); | |||
131 | if (!end) return; | |||
132 | *dest = zmalloc(end-start+1); | |||
133 | strncpy(*dest, start, end-start)__builtin___strncpy_chk (*dest, start, end-start, __builtin_object_size (*dest, 2 > 1 ? 1 : 0)); | |||
134 | (*dest)[end-start] = '\0'; | |||
135 | } else { | |||
136 | *dest = zstrdup(source); | |||
137 | } | |||
138 | } | |||
139 | ||||
140 | static void | |||
141 | zstrcat(char **dest, const char *source) | |||
142 | { | |||
143 | size_t dest_size = 1; | |||
144 | size_t source_size; | |||
145 | ||||
146 | if (*dest != NULL((void *)0)) | |||
147 | dest_size = strlen(*dest) + 1; | |||
148 | source_size = strlen(source); | |||
149 | *dest = zrealloc(*dest, dest_size + source_size); | |||
150 | strcpy(*dest + dest_size - 1, source)__builtin___strcpy_chk (*dest + dest_size - 1, source, __builtin_object_size (*dest + dest_size - 1, 2 > 1 ? 1 : 0)); | |||
151 | } | |||
152 | ||||
153 | static void | |||
154 | zstrtoupper(char *s) | |||
155 | { | |||
156 | char *t; | |||
157 | ||||
158 | for (t = s; *t != '\000'; t++) | |||
159 | *t = (char) toupper(*t); | |||
160 | } | |||
161 | ||||
162 | #define zs_true(x)(x != ((void *)0) && strcmp(x, "0") != 0) (x != NULL((void *)0) && strcmp(x, "0") != 0) | |||
163 | #define zi_true(x)(x == 1) (x == 1) | |||
164 | ||||
165 | /* "CLASS" "dynamic array" */ | |||
166 | ||||
167 | typedef struct { | |||
168 | char *name; | |||
169 | int size; | |||
170 | int count; | |||
171 | void **values; | |||
172 | void *nv; | |||
173 | } da_t; | |||
174 | ||||
175 | static da_t * | |||
176 | da_new(const char *name) | |||
177 | { | |||
178 | da_t *da; | |||
179 | ||||
180 | da = zmalloc(sizeof(da_t)); | |||
181 | da->size = 0; | |||
182 | da->count = 0; | |||
183 | da->values = NULL((void *)0); | |||
184 | da->nv = NULL((void *)0); | |||
185 | da->name = NULL((void *)0); | |||
186 | zstrcpy(&(da->name), name); | |||
187 | return da; | |||
188 | } | |||
189 | ||||
190 | static void * | |||
191 | da_fetch(da_t *da, int key) | |||
192 | { | |||
193 | void *r = NULL((void *)0); | |||
194 | ||||
195 | if (key >= 0 && key < da->size && da->values[key] != NULL((void *)0)) | |||
196 | r = da->values[key]; | |||
197 | else | |||
198 | if (key == -1 && da->nv != NULL((void *)0)) | |||
199 | r = da->nv; | |||
200 | ||||
201 | return r; | |||
202 | } | |||
203 | ||||
204 | static int | |||
205 | da_fetch_int(da_t *da, int key) | |||
206 | { | |||
207 | int *t; | |||
208 | int r = -1; | |||
209 | t = da_fetch(da, key); | |||
210 | if (t != NULL((void *)0)) | |||
211 | r = *t; | |||
212 | return r; | |||
213 | } | |||
214 | ||||
215 | #define da_fetch_str(a,k)(char *)da_fetch(a,k) \ | |||
216 | (char *)da_fetch(a,k) | |||
217 | ||||
218 | static void | |||
219 | da_add(da_t *da, int key, void *value) | |||
220 | { | |||
221 | int i = da->size; | |||
222 | if (key >= 0) { | |||
223 | if (key >= da->size) { | |||
224 | da->size = key + 1; | |||
225 | da->values = zrealloc(da->values, | |||
226 | da->size * sizeof(void *)); | |||
227 | for (; i < da->size; i++) | |||
228 | da->values[i] = NULL((void *)0); | |||
229 | } | |||
230 | if (da->values[key] != NULL((void *)0)) { | |||
231 | free(da->values[key]); | |||
232 | } else { | |||
233 | if (value == NULL((void *)0)) { | |||
234 | if (da->count > 0) | |||
235 | da->count--; | |||
236 | } else { | |||
237 | da->count++; | |||
238 | } | |||
239 | } | |||
240 | da->values[key] = value; | |||
241 | } else if (key == -1) { | |||
242 | if (da->nv != NULL((void *)0)) | |||
243 | free(da->nv); | |||
244 | da->nv = value; | |||
245 | } | |||
246 | } | |||
247 | ||||
248 | static void | |||
249 | da_add_str(da_t *da, int key, const char *value) | |||
250 | { | |||
251 | da_add(da, key, value?zstrdup(value):NULL((void *)0)); | |||
252 | } | |||
253 | ||||
254 | static void | |||
255 | da_add_int(da_t *da, int key, int value) | |||
256 | { | |||
257 | int *v; | |||
258 | ||||
259 | v = zmalloc(sizeof(int)); | |||
260 | *v = value; | |||
261 | da_add(da, key, v); | |||
262 | } | |||
263 | ||||
264 | #define da_count(da)(da->count) (da->count) | |||
265 | #define da_size(da)(da->size) (da->size) | |||
266 | ||||
267 | static void | |||
268 | da_clear(da_t *da) | |||
269 | { | |||
270 | int i; | |||
271 | ||||
272 | for (i = da->size; i; i--) | |||
273 | free(da->values[i]); | |||
274 | if (da->values != NULL((void *)0)) | |||
275 | free(da->values); | |||
276 | da->size = 0; | |||
277 | da->count = 0; | |||
278 | da->values = NULL((void *)0); | |||
279 | } | |||
280 | ||||
281 | /* "CLASS" file input */ | |||
282 | ||||
283 | #define TYPICAL_LINE_SIZE(80) (80) | |||
284 | ||||
285 | /* read a line and strip trailing whitespace */ | |||
286 | static int | |||
287 | read_line(FILE *fp, char **buffer) | |||
288 | { | |||
289 | int buffer_size = TYPICAL_LINE_SIZE(80); | |||
290 | int eof = 0; | |||
291 | int position = 0; | |||
292 | int c; | |||
293 | ||||
294 | *buffer = zmalloc(TYPICAL_LINE_SIZE(80)); | |||
295 | (*buffer)[0] = '\0'; | |||
296 | ||||
297 | if ((c = getc(fp)) == EOF(-1)) | |||
298 | eof = 1; | |||
299 | ||||
300 | while (c != '\n' && !eof) { | |||
301 | if (position + 1 >= buffer_size) { | |||
302 | buffer_size = buffer_size * 2 + 1; | |||
303 | *buffer = zrealloc(*buffer, buffer_size); | |||
304 | } | |||
305 | (*buffer)[position++] = (char) c; | |||
306 | (*buffer)[position] = '\0'; | |||
307 | c = getc(fp); | |||
308 | if (c == EOF(-1)) | |||
309 | eof = 1; | |||
310 | } | |||
311 | ||||
312 | if (eof) { | |||
313 | free(*buffer); | |||
314 | *buffer = NULL((void *)0); | |||
315 | return 0; | |||
316 | } | |||
317 | ||||
318 | while (position > 1) { | |||
319 | position--; | |||
320 | if (!isspace((*buffer)[position])) | |||
321 | break; | |||
322 | (*buffer)[position] = '\0'; | |||
323 | } | |||
324 | ||||
325 | return 1; | |||
326 | } | |||
327 | ||||
328 | /* BEGIN */ | |||
329 | ||||
330 | /* | |||
331 | DEC VT100 graphics characters in the range 1-31 (as expected by | |||
332 | some old xterm versions and a few other applications) | |||
333 | */ | |||
334 | #define decmap_size31 31 | |||
335 | static int decmap[decmap_size31] = { | |||
336 | 0x25C6, /* BLACK DIAMOND */ | |||
337 | 0x2592, /* MEDIUM SHADE */ | |||
338 | 0x2409, /* SYMBOL FOR HORIZONTAL TABULATION */ | |||
339 | 0x240C, /* SYMBOL FOR FORM FEED */ | |||
340 | 0x240D, /* SYMBOL FOR CARRIAGE RETURN */ | |||
341 | 0x240A, /* SYMBOL FOR LINE FEED */ | |||
342 | 0x00B0, /* DEGREE SIGN */ | |||
343 | 0x00B1, /* PLUS-MINUS SIGN */ | |||
344 | 0x2424, /* SYMBOL FOR NEWLINE */ | |||
345 | 0x240B, /* SYMBOL FOR VERTICAL TABULATION */ | |||
346 | 0x2518, /* BOX DRAWINGS LIGHT UP AND LEFT */ | |||
347 | 0x2510, /* BOX DRAWINGS LIGHT DOWN AND LEFT */ | |||
348 | 0x250C, /* BOX DRAWINGS LIGHT DOWN AND RIGHT */ | |||
349 | 0x2514, /* BOX DRAWINGS LIGHT UP AND RIGHT */ | |||
350 | 0x253C, /* BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */ | |||
351 | 0x23BA, /* HORIZONTAL SCAN LINE-1 (Unicode 3.2 draft) */ | |||
352 | 0x23BB, /* HORIZONTAL SCAN LINE-3 (Unicode 3.2 draft) */ | |||
353 | 0x2500, /* BOX DRAWINGS LIGHT HORIZONTAL */ | |||
354 | 0x23BC, /* HORIZONTAL SCAN LINE-7 (Unicode 3.2 draft) */ | |||
355 | 0x23BD, /* HORIZONTAL SCAN LINE-9 (Unicode 3.2 draft) */ | |||
356 | 0x251C, /* BOX DRAWINGS LIGHT VERTICAL AND RIGHT */ | |||
357 | 0x2524, /* BOX DRAWINGS LIGHT VERTICAL AND LEFT */ | |||
358 | 0x2534, /* BOX DRAWINGS LIGHT UP AND HORIZONTAL */ | |||
359 | 0x252C, /* BOX DRAWINGS LIGHT DOWN AND HORIZONTAL */ | |||
360 | 0x2502, /* BOX DRAWINGS LIGHT VERTICAL */ | |||
361 | 0x2264, /* LESS-THAN OR EQUAL TO */ | |||
362 | 0x2265, /* GREATER-THAN OR EQUAL TO */ | |||
363 | 0x03C0, /* GREEK SMALL LETTER PI */ | |||
364 | 0x2260, /* NOT EQUAL TO */ | |||
365 | 0x00A3, /* POUND SIGN */ | |||
366 | 0x00B7 /* MIDDLE DOT */ | |||
367 | }; | |||
368 | ||||
369 | static int | |||
370 | is_control(int ucs) | |||
371 | { | |||
372 | return ((ucs >= 0x00 && ucs <= 0x1f) || | |||
373 | (ucs >= 0x7f && ucs <= 0x9f)); | |||
374 | } | |||
375 | ||||
376 | static int | |||
377 | is_blockgraphics(int ucs) | |||
378 | { | |||
379 | return ucs >= 0x2500 && ucs <= 0x25FF; | |||
380 | } | |||
381 | ||||
382 | /* calculate the bounding box that covers both provided bounding boxes */ | |||
383 | typedef struct { | |||
384 | int cwidth; | |||
385 | int cheight; | |||
386 | int cxoff; | |||
387 | int cyoff; | |||
388 | } bbx_t; | |||
389 | ||||
390 | static bbx_t * | |||
391 | combine_bbx(int awidth, int aheight, int axoff, int ayoff, | |||
392 | int cwidth, int cheight, int cxoff, int cyoff, bbx_t *r) | |||
393 | { | |||
394 | r->cwidth = cwidth; | |||
395 | r->cheight = cheight; | |||
396 | r->cxoff = cxoff; | |||
397 | r->cyoff = cyoff; | |||
398 | ||||
399 | if (axoff < r->cxoff) { | |||
400 | r->cwidth += r->cxoff - axoff; | |||
401 | r->cxoff = axoff; | |||
402 | } | |||
403 | if (ayoff < r->cyoff) { | |||
404 | r->cheight += r->cyoff - ayoff; | |||
405 | r->cyoff = ayoff; | |||
406 | } | |||
407 | if (awidth + axoff > r->cwidth + r->cxoff) { | |||
408 | r->cwidth = awidth + axoff - r->cxoff; | |||
409 | } | |||
410 | if (aheight + ayoff > r->cheight + r->cyoff) { | |||
411 | r->cheight = aheight + ayoff - r->cyoff; | |||
412 | } | |||
413 | ||||
414 | return r; | |||
415 | } | |||
416 | ||||
417 | static void | |||
418 | usage(void) { | |||
419 | printf("%s", "\n" | |||
420 | "Usage: ucs2any [+d|-d] <source-name> { <mapping-file> <registry-encoding> }\n" | |||
421 | "\n" | |||
422 | "where\n" | |||
423 | "\n" | |||
424 | " +d put DEC VT100 graphics characters in the C0 range\n" | |||
425 | " (default for upright charcell fonts)\n" | |||
426 | "\n" | |||
427 | " -d do not put DEC VT100 graphics characters in the\n" | |||
428 | " C0 range (default for all other font types)\n" | |||
429 | "\n" | |||
430 | " <source-name> is the name of an ISO10646-1 encoded BDF file\n" | |||
431 | "\n" | |||
432 | " <mapping-file> is the name of a character set table like those on\n" | |||
433 | " <ftp://ftp.unicode.org/Public/MAPPINGS/>\n" | |||
434 | "\n" | |||
435 | " <registry-encoding> are the CHARSET_REGISTRY and CHARSET_ENCODING\n" | |||
436 | " field values for the font name (XLFD) of the\n" | |||
437 | " target font, separated by a hyphen\n" | |||
438 | "\n" | |||
439 | "Example:\n" | |||
440 | "\n" | |||
441 | " ucs2any 6x13.bdf 8859-1.TXT iso8859-1 8859-2.TXT iso8859-2\n" | |||
442 | "\n" | |||
443 | "will generate the files 6x13-iso8859-1.bdf and 6x13-iso8859-2.bdf\n" | |||
444 | "\n"); | |||
445 | } | |||
446 | ||||
447 | static int | |||
448 | chars_compare(const void *aa, const void *bb) | |||
449 | { | |||
450 | int a = *(const int *)aa; | |||
451 | int b = *(const int *)bb; | |||
452 | ||||
453 | return a - b; | |||
454 | } | |||
455 | ||||
456 | /* | |||
457 | * Return != 0 if "string" starts with "pattern" followed by whitespace. | |||
458 | * If it does, return a pointer to the first non space char. | |||
459 | */ | |||
460 | static const char * | |||
461 | startswith(const char *string, const char *pattern) | |||
462 | { | |||
463 | size_t l = strlen(pattern); | |||
464 | ||||
465 | if (strlen(string) <= l) return NULL((void *)0); | |||
466 | if (strncmp(string, pattern, l) != 0) return NULL((void *)0); | |||
467 | string += l; | |||
468 | if (!isspace(*string)) return NULL((void *)0); | |||
469 | while (isspace(*string)) | |||
470 | string++; | |||
471 | return string; | |||
472 | } | |||
473 | ||||
474 | int | |||
475 | main(int argc, char *argv[]) | |||
476 | { | |||
477 | int ai = 1; | |||
478 | int dec_chars = -1; | |||
479 | char *fsource = NULL((void *)0); | |||
480 | FILE *fsource_fp; | |||
481 | int properties; | |||
482 | int default_char; | |||
483 | char *l = NULL((void *)0); | |||
484 | char *t = NULL((void *)0); | |||
485 | const char *nextc = NULL((void *)0); | |||
486 | char *startfont = NULL((void *)0); | |||
487 | char *slant = NULL((void *)0); | |||
| ||||
488 | char *spacing = NULL((void *)0); | |||
489 | char *sc = NULL((void *)0); | |||
490 | int code = -1; | |||
491 | da_t *startchar; | |||
492 | da_t *my_char; | |||
493 | char *fmap = NULL((void *)0); | |||
494 | char *registry = NULL((void *)0); | |||
495 | char *encoding = NULL((void *)0); | |||
496 | char *fontname = NULL((void *)0); | |||
497 | FILE *fmap_fp; | |||
498 | da_t *map; | |||
499 | da_t *headers; | |||
500 | int nextheader = -1; | |||
501 | int default_char_index = -1; | |||
502 | int startproperties_index = -1; | |||
503 | int fontname_index = -1; | |||
504 | int charset_registry_index = -1; | |||
505 | int slant_index = -1; | |||
506 | int spacing_index = -1; | |||
507 | int charset_encoding_index = -1; | |||
508 | int fontboundingbox_index = -1; | |||
509 | int target; | |||
510 | int ucs; | |||
511 | int i; | |||
512 | int j; | |||
513 | int *chars = NULL((void *)0); | |||
514 | bbx_t bbx; | |||
515 | char *fout = NULL((void *)0); | |||
516 | FILE *fout_fp; | |||
517 | int k; | |||
518 | char *registry_encoding = NULL((void *)0); | |||
519 | ||||
520 | my_name = argv[0]; | |||
521 | bbx.cheight = bbx.cxoff = bbx.cyoff = -1; | |||
522 | ||||
523 | startchar = da_new("startchar"); | |||
524 | my_char = da_new("my_char"); | |||
525 | map = da_new("map"); | |||
526 | headers = da_new("headers"); | |||
527 | ||||
528 | if (argc < 2) { | |||
529 | usage(); | |||
530 | exit(0); | |||
531 | } | |||
532 | ||||
533 | /* check options */ | |||
534 | if (strcmp(argv[ai], "+d") == 0) { | |||
535 | ai++; | |||
536 | dec_chars = 1; | |||
537 | } else if (strcmp(argv[ai], "-d") == 0) { | |||
538 | ai++; | |||
539 | dec_chars = 0; | |||
540 | } | |||
541 | if (ai >= argc) { | |||
542 | usage(); | |||
543 | exit(0); | |||
544 | } | |||
545 | ||||
546 | /* open and read source file */ | |||
547 | fsource = argv[ai]; | |||
548 | fsource_fp = fopen(fsource, "r"); | |||
549 | if (fsource_fp == NULL((void *)0)) { | |||
550 | fprintf(stderr__stderrp, "%s: Can't read file '%s': %s!\n", my_name, | |||
551 | fsource, strerror(errno(*__error()))); | |||
552 | exit(1); | |||
553 | } | |||
554 | ||||
555 | /* read header */ | |||
556 | properties = 0; | |||
557 | default_char = 0; | |||
558 | while (read_line(fsource_fp, &l)) { | |||
559 | if (startswith(l, "CHARS")) | |||
560 | break; | |||
561 | if (startswith(l, "STARTFONT")) { | |||
562 | zstrcpy(&startfont, l); | |||
563 | } else if (startswith(l, "_XMBDFED_INFO") || | |||
564 | startswith(l, "XFREE86_GLYPH_RANGES")) | |||
565 | { | |||
566 | properties--; | |||
567 | } else if ((nextc = startswith(l, "DEFAULT_CHAR")) != NULL((void *)0)) | |||
568 | { | |||
569 | default_char = atoi(nextc); | |||
570 | default_char_index = ++nextheader; | |||
571 | da_add_str(headers, default_char_index, NULL((void *)0)); | |||
572 | } else { | |||
573 | if ((nextc = startswith(l, "STARTPROPERTIES")) != NULL((void *)0)) | |||
574 | { | |||
575 | properties = atoi(nextc); | |||
576 | startproperties_index = ++nextheader; | |||
577 | da_add_str(headers, startproperties_index, NULL((void *)0)); | |||
578 | } else if ((nextc = startswith(l, "FONT")) != NULL((void *)0)) | |||
579 | { | |||
580 | char * term; | |||
581 | /* slightly simplistic check ... */ | |||
582 | zquotedcpy(&fontname, nextc); | |||
583 | if ((term = strstr(fontname, "-ISO10646-1")) == NULL((void *)0)) { | |||
584 | fprintf(stderr__stderrp, | |||
585 | "%s: FONT name in '%s' is '%s' and not '*-ISO10646-1'!\n", | |||
586 | my_name, fsource, fontname); | |||
587 | exit(1); | |||
588 | } | |||
589 | *term = '\0'; | |||
590 | fontname_index = ++nextheader; | |||
591 | da_add_str(headers, fontname_index, NULL((void *)0)); | |||
592 | } else if ((nextc = startswith(l, "CHARSET_REGISTRY")) != NULL((void *)0)) | |||
593 | { | |||
594 | if (strcmp(nextc, "\"ISO10646\"") != 0) { | |||
595 | fprintf(stderr__stderrp, | |||
596 | "%s: CHARSET_REGISTRY in '%s' is '%s' and not 'ISO10646'!\n", | |||
597 | my_name, fsource, nextc); | |||
598 | exit(1); | |||
599 | } | |||
600 | charset_registry_index = ++nextheader; | |||
601 | da_add_str(headers, charset_registry_index, NULL((void *)0)); | |||
602 | } else if ((nextc = startswith(l, "CHARSET_ENCODING")) != NULL((void *)0)) | |||
603 | { | |||
604 | if (strcmp(nextc, "\"1\"") != 0) { | |||
605 | fprintf(stderr__stderrp, | |||
606 | "%s: CHARSET_ENCODING in '%s' is '%s' and not '1'!\n", | |||
607 | my_name, fsource, nextc); | |||
608 | exit(1); | |||
609 | } | |||
610 | charset_encoding_index = ++nextheader; | |||
611 | da_add_str(headers, charset_encoding_index, NULL((void *)0)); | |||
612 | } else if (startswith(l, "FONTBOUNDINGBOX")) { | |||
613 | fontboundingbox_index = ++nextheader; | |||
614 | da_add_str(headers, fontboundingbox_index, NULL((void *)0)); | |||
615 | } else if ((nextc = startswith(l, "SLANT")) != NULL((void *)0)) | |||
616 | { | |||
617 | zquotedcpy(&slant, nextc); | |||
618 | slant_index = ++nextheader; | |||
619 | da_add_str(headers, slant_index, NULL((void *)0)); | |||
620 | } else if ((nextc = startswith(l, "SPACING")) != NULL((void *)0)) | |||
621 | { | |||
622 | zquotedcpy(&spacing, nextc); | |||
623 | zstrtoupper(spacing); | |||
624 | spacing_index = ++nextheader; | |||
625 | da_add_str(headers, spacing_index, NULL((void *)0)); | |||
626 | } else if ((nextc = startswith(l, "COMMENT")) != NULL((void *)0)) { | |||
627 | if (strncmp(nextc, "$Id: ", 5)==0) { | |||
628 | char *header = NULL((void *)0); | |||
629 | char *id = NULL((void *)0), *end = NULL((void *)0); | |||
630 | id = zstrdup(nextc + 5); | |||
631 | end = strrchr(id, '$'); | |||
632 | if (end) *end = '\0'; | |||
633 | zstrcpy(&header, "COMMENT Derived from "); | |||
634 | zstrcat(&header, id); | |||
635 | zstrcat(&header, "\n"); | |||
636 | free(id); | |||
637 | da_add_str(headers, ++nextheader, header); | |||
638 | free(header); | |||
639 | } else { | |||
640 | da_add_str(headers, ++nextheader, l); | |||
641 | } | |||
642 | } else { | |||
643 | da_add_str(headers, ++nextheader, l); | |||
644 | } | |||
645 | } | |||
646 | free(l); | |||
647 | } | |||
648 | ||||
649 | if (startfont == NULL((void *)0)) { | |||
650 | fprintf(stderr__stderrp, "%s: No STARTFONT line found in '%s'!\n", | |||
651 | my_name, fsource); | |||
652 | exit(1); | |||
653 | } | |||
654 | ||||
655 | /* read characters */ | |||
656 | while (read_line(fsource_fp, &l)) { | |||
657 | if (startswith(l, "STARTCHAR")) { | |||
658 | zstrcpy(&sc, l); | |||
659 | zstrcat(&sc, "\n"); | |||
660 | code = -1; | |||
661 | } else if ((nextc = startswith(l, "ENCODING")) != NULL((void *)0)) { | |||
662 | code = atoi(nextc); | |||
663 | da_add_str(startchar, code, sc); | |||
664 | da_add_str(my_char, code, ""); | |||
665 | } else if (strcmp(l, "ENDFONT")==0) { | |||
666 | code = -1; | |||
667 | zstrcpy(&sc, "STARTCHAR ???\n"); | |||
668 | } else { | |||
669 | zstrcpy(&t, da_fetch_str(my_char, code)(char *)da_fetch(my_char,code)); | |||
670 | zstrcat(&t, l); | |||
671 | zstrcat(&t, "\n"); | |||
672 | da_add_str(my_char, code, t); | |||
673 | if (strcmp(l, "ENDCHAR")==0) { | |||
674 | code = -1; | |||
675 | zstrcpy(&sc, "STARTCHAR ???\n"); | |||
676 | } | |||
677 | } | |||
678 | free(l); | |||
679 | } | |||
680 | ||||
681 | fclose(fsource_fp); | |||
682 | ||||
683 | ai++; | |||
684 | while (ai < argc) { | |||
685 | zstrcpy(&fmap, argv[ai]); | |||
686 | i = ai + 1; | |||
687 | if (i < argc) { | |||
688 | char *temp = NULL((void *)0); | |||
689 | char * hyphen = strchr(argv[i], '-'); | |||
690 | if (!hyphen || strchr(hyphen+1, '-') != NULL((void *)0)) { | |||
691 | fprintf(stderr__stderrp, | |||
692 | "%s: Argument registry-encoding '%s' not in expected format!\n", | |||
693 | my_name, i < argc ? fmap : ""); | |||
694 | exit(1); | |||
695 | } | |||
696 | temp = zstrdup(argv[i]); | |||
697 | hyphen = strchr(temp, '-'); | |||
698 | if (hyphen) *hyphen = 0; | |||
699 | zstrcpy(®istry, temp); | |||
700 | zstrcpy(&encoding, hyphen+1); | |||
701 | free(temp); | |||
702 | } else { | |||
703 | fprintf(stderr__stderrp, "map file argument \"%s\" needs a " | |||
704 | "coresponding registry-encoding argument\n", fmap); | |||
705 | exit(0); | |||
706 | } | |||
707 | ||||
708 | ai++; | |||
709 | ai++; | |||
710 | ||||
711 | /* open and read source file */ | |||
712 | fmap_fp = fopen(fmap, "r"); | |||
713 | if (fmap_fp == NULL((void *)0)) { | |||
714 | fprintf(stderr__stderrp, | |||
715 | "%s: Can't read mapping file '%s': %s!\n", | |||
716 | my_name, fmap, strerror(errno(*__error()))); | |||
717 | exit(1); | |||
718 | } | |||
719 | ||||
720 | da_clear(map); | |||
721 | ||||
722 | for (;read_line(fmap_fp, &l); free(l)) { | |||
723 | char *p, *endp; | |||
724 | ||||
725 | for (p = l; isspace(p[0]); p++) | |||
726 | ; | |||
727 | if (p[0] == '\0' || p[0] == '#') | |||
728 | continue; | |||
729 | if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) { | |||
730 | target = (int) strtol(p+2, &endp, 16); | |||
731 | if (*endp == '\0') goto bad; | |||
732 | p = endp; | |||
733 | } else | |||
734 | goto bad; | |||
735 | for (; isspace(p[0]); p++) | |||
736 | ; | |||
737 | if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) { | |||
738 | ucs = (int) strtol(p+2, &endp, 16); | |||
739 | if (*endp == '\0') goto bad; | |||
740 | } else | |||
741 | goto bad; | |||
742 | ||||
743 | if (!is_control(ucs)) { | |||
744 | if (zs_true(da_fetch_str(startchar, ucs))((char *)da_fetch(startchar,ucs) != ((void *)0) && strcmp ((char *)da_fetch(startchar,ucs), "0") != 0)) | |||
745 | { | |||
746 | da_add_int(map, target, ucs); | |||
747 | } else { | |||
748 | if (!((is_blockgraphics(ucs) && | |||
749 | strcmp(slant, "R") != 0) || | |||
750 | (ucs >= 0x200e && | |||
751 | ucs <= 0x200f))) { | |||
752 | fprintf(stderr__stderrp, | |||
753 | "No glyph for character U+%04X (0x%02x) available.\n", | |||
754 | ucs, target); | |||
755 | } | |||
756 | } | |||
757 | } | |||
758 | continue; | |||
759 | bad: | |||
760 | fprintf(stderr__stderrp, "Unrecognized line in '%s':\n%s\n", fmap, l); | |||
761 | } | |||
762 | fclose(fmap_fp); | |||
763 | ||||
764 | /* add default character */ | |||
765 | if (!zi_true(da_fetch_int(map, 0))(da_fetch_int(map, 0) == 1)) { | |||
766 | if (zs_true(da_fetch_str(startchar, default_char))((char *)da_fetch(startchar,default_char) != ((void *)0) && strcmp((char *)da_fetch(startchar,default_char), "0") != 0)) { | |||
767 | da_add_int(map, 0, default_char); | |||
768 | da_add_str(startchar, default_char, | |||
769 | "STARTCHAR defaultchar\n"); | |||
770 | } else { | |||
771 | fprintf(stderr__stderrp, "%s", | |||
772 | "No default character defined.\n"); | |||
773 | } | |||
774 | } | |||
775 | ||||
776 | if (dec_chars == 1 || | |||
777 | (dec_chars == -1 && strcmp(slant, "R") == 0 && | |||
| ||||
778 | strcmp(spacing, "C") == 0)) | |||
779 | { | |||
780 | /* add DEC VT100 graphics characters in the range 1-31 | |||
781 | (as expected by some old xterm versions) */ | |||
782 | for (i = 0; i < decmap_size31; i++) { | |||
783 | if (zs_true(da_fetch_str(startchar, decmap[i]))((char *)da_fetch(startchar,decmap[i]) != ((void *)0) && strcmp((char *)da_fetch(startchar,decmap[i]), "0") != 0)) | |||
784 | { | |||
785 | da_add_int(map, i + 1, decmap[i]); | |||
786 | } | |||
787 | } | |||
788 | } | |||
789 | ||||
790 | /* list of characters that will be written out */ | |||
791 | j = da_count(map)(map->count); | |||
792 | if (j < 0) { | |||
793 | fprintf(stderr__stderrp, | |||
794 | "No characters found for %s-%s.\n", | |||
795 | registry, encoding); | |||
796 | continue; | |||
797 | } | |||
798 | if (chars != NULL((void *)0)) | |||
799 | free(chars); | |||
800 | chars = zmalloc(j * sizeof(int)); | |||
801 | memset(chars, 0, j * sizeof(int))__builtin___memset_chk (chars, 0, j * sizeof(int), __builtin_object_size (chars, 0)); | |||
802 | for (k = 0, i = 0; k < da_count(map)(map->count) && i < da_size(map)(map->size); i++) { | |||
803 | if (da_fetch(map, i) != NULL((void *)0)) | |||
804 | chars[k++] = i; | |||
805 | } | |||
806 | qsort(chars, j, sizeof(int), chars_compare); | |||
807 | ||||
808 | /* find overall font bounding box */ | |||
809 | bbx.cwidth = -1; | |||
810 | for (i = 0; i < j; i++) { | |||
811 | ucs = da_fetch_int(map, chars[i]); | |||
812 | zstrcpy(&t, da_fetch_str(my_char, ucs)(char *)da_fetch(my_char,ucs)); | |||
813 | if ((nextc = startswith(t, "BBX")) != NULL((void *)0) | |||
814 | || (nextc = strstr(t, "\nBBX")) != NULL((void *)0)) | |||
815 | { | |||
816 | char *endp; | |||
817 | int w, h, x, y; | |||
818 | ||||
819 | if (*nextc == '\n') { | |||
820 | nextc += 4; | |||
821 | while (isspace(*nextc)) | |||
822 | nextc++; | |||
823 | } | |||
824 | for (;isspace(*nextc);) | |||
825 | nextc++; | |||
826 | w = (int) strtol(nextc, &endp, 10); | |||
827 | nextc = endp; | |||
828 | if (*nextc == '\0') goto bbxbad; | |||
829 | for (;isspace(*nextc);) | |||
830 | nextc++; | |||
831 | h = (int) strtol(nextc, &endp, 10); | |||
832 | nextc = endp; | |||
833 | if (*nextc == '\0') goto bbxbad; | |||
834 | for (;isspace(*nextc);) | |||
835 | nextc++; | |||
836 | x = (int) strtol(nextc, &endp, 10); | |||
837 | nextc = endp; | |||
838 | if (*nextc == '\0') goto bbxbad; | |||
839 | for (;isspace(*nextc);) | |||
840 | nextc++; | |||
841 | y = (int) strtol(nextc, &endp, 10); | |||
842 | if (bbx.cwidth == -1) { | |||
843 | bbx.cwidth = w; | |||
844 | bbx.cheight = h; | |||
845 | bbx.cxoff = x; | |||
846 | bbx.cyoff = y; | |||
847 | } else { | |||
848 | combine_bbx(bbx.cwidth, bbx.cheight, | |||
849 | bbx.cxoff, bbx.cyoff, | |||
850 | w, h, x, y, &bbx); | |||
851 | } | |||
852 | continue; | |||
853 | bbxbad: | |||
854 | fprintf(stderr__stderrp, "Unparsable BBX found for U+%04x!\n", ucs); | |||
855 | } else { | |||
856 | fprintf(stderr__stderrp, | |||
857 | "Warning: No BBX found for U+%04X!\n", | |||
858 | ucs); | |||
859 | } | |||
860 | } | |||
861 | ||||
862 | if (!registry) registry = zstrdup(""); | |||
863 | if (!encoding) encoding = zstrdup(""); | |||
864 | ||||
865 | /* generate output file name */ | |||
866 | zstrcpy(®istry_encoding, "-"); | |||
867 | zstrcat(®istry_encoding, registry); | |||
868 | zstrcat(®istry_encoding, "-"); | |||
869 | zstrcat(®istry_encoding, encoding); | |||
870 | ||||
871 | { | |||
872 | char * p = strstr(fsource, ".bdf"); | |||
873 | if (p) { | |||
874 | zstrcpy(&fout, fsource); | |||
875 | p = strstr(fout, ".bdf"); | |||
876 | *p = 0; | |||
877 | zstrcat(&fout, registry_encoding); | |||
878 | zstrcat(&fout, ".bdf"); | |||
879 | } else { | |||
880 | zstrcpy(&fout, fsource); | |||
881 | zstrcat(&fout, registry_encoding); | |||
882 | } | |||
883 | } | |||
884 | ||||
885 | /* remove path prefix */ | |||
886 | zstrcpy(&t, basename(fout)); | |||
887 | zstrcpy(&fout, t); | |||
888 | ||||
889 | /* write new BDF file */ | |||
890 | fprintf(stderr__stderrp, "Writing %d characters into file '%s'.\n", | |||
891 | j, fout); | |||
892 | fout_fp = fopen(fout, "w"); | |||
893 | if (fout_fp == NULL((void *)0)) { | |||
894 | fprintf(stderr__stderrp, "%s: Can't write file '%s': %s!\n", | |||
895 | my_name, fout, strerror(errno(*__error()))); | |||
896 | exit(1); | |||
897 | } | |||
898 | ||||
899 | fprintf(fout_fp, "%s\n", startfont); | |||
900 | fprintf(fout_fp, "%s", | |||
901 | "COMMENT AUTOMATICALLY GENERATED FILE. DO NOT EDIT!\n"); | |||
902 | fprintf(fout_fp, | |||
903 | "COMMENT Generated with 'ucs2any %s %s %s-%s'\n", | |||
904 | fsource, fmap, registry, encoding); | |||
905 | fprintf(fout_fp, "%s", | |||
906 | "COMMENT from an ISO10646-1 encoded source BDF font.\n"); | |||
907 | fprintf(fout_fp, "%s", | |||
908 | "COMMENT ucs2any by Ben Collver <collver1@attbi.com>, 2003, based on\n"); | |||
909 | fprintf(fout_fp, "%s", | |||
910 | "COMMENT ucs2any.pl by Markus Kuhn <http://www.cl.cam.ac.uk/~mgk25/>, 2000.\n"); | |||
911 | ||||
912 | for (i = 0; i <= nextheader; i++) { | |||
913 | if (i == default_char_index) | |||
914 | fprintf(fout_fp, "DEFAULT_CHAR %d\n", default_char); | |||
915 | else if (i == startproperties_index) | |||
916 | fprintf(fout_fp, "STARTPROPERTIES %d\n", properties); | |||
917 | else if (i == fontname_index) { | |||
918 | fprintf(fout_fp, "FONT %s%s\n", fontname, registry_encoding); | |||
919 | } | |||
920 | else if (i == charset_registry_index) | |||
921 | fprintf(fout_fp, "CHARSET_REGISTRY \"%s\"\n", registry); | |||
922 | else if (i == slant_index) | |||
923 | fprintf(fout_fp, "SLANT \"%s\"\n", slant); | |||
924 | else if (i == charset_encoding_index) | |||
925 | fprintf(fout_fp, "CHARSET_ENCODING \"%s\"\n", encoding); | |||
926 | else if (i == fontboundingbox_index) | |||
927 | fprintf(fout_fp, "FONTBOUNDINGBOX %d %d %d %d\n", bbx.cwidth, bbx.cheight, bbx.cxoff, bbx.cyoff); | |||
928 | else if (i == spacing_index) | |||
929 | fprintf(fout_fp, "SPACING \"%s\"\n", spacing); | |||
930 | else | |||
931 | fprintf(fout_fp, "%s\n", da_fetch_str(headers, i)(char *)da_fetch(headers,i)); | |||
932 | } | |||
933 | ||||
934 | fprintf(fout_fp, "CHARS %d\n", j); | |||
935 | ||||
936 | /* Write characters */ | |||
937 | for (i = 0; i < j; i++) { | |||
938 | ucs = da_fetch_int(map, chars[i]); | |||
939 | fprintf(fout_fp, "%s", da_fetch_str(startchar,(char *)da_fetch(startchar,ucs) | |||
940 | ucs)(char *)da_fetch(startchar,ucs)); | |||
941 | fprintf(fout_fp, "ENCODING %d\n", chars[i]); | |||
942 | fprintf(fout_fp, "%s", da_fetch_str(my_char,(char *)da_fetch(my_char,ucs) | |||
943 | ucs)(char *)da_fetch(my_char,ucs)); | |||
944 | } | |||
945 | fprintf(fout_fp, "%s", "ENDFONT\n"); | |||
946 | fclose(fout_fp); | |||
947 | } | |||
948 | ||||
949 | exit(0); | |||
950 | } |