encparse.c revision 48c85eb7
13da084b3Smrg/* 23da084b3SmrgCopyright (c) 1998-2001 by Juliusz Chroboczek 33da084b3Smrg 43da084b3SmrgPermission is hereby granted, free of charge, to any person obtaining a copy 53da084b3Smrgof this software and associated documentation files (the "Software"), to deal 63da084b3Smrgin the Software without restriction, including without limitation the rights 73da084b3Smrgto use, copy, modify, merge, publish, distribute, sublicense, and/or sell 83da084b3Smrgcopies of the Software, and to permit persons to whom the Software is 93da084b3Smrgfurnished to do so, subject to the following conditions: 103da084b3Smrg 113da084b3SmrgThe above copyright notice and this permission notice shall be included in 123da084b3Smrgall copies or substantial portions of the Software. 133da084b3Smrg 143da084b3SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 153da084b3SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 163da084b3SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 173da084b3SmrgAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 183da084b3SmrgLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 193da084b3SmrgOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 203da084b3SmrgTHE SOFTWARE. 213da084b3Smrg*/ 223da084b3Smrg 233da084b3Smrg/* Parser for encoding files */ 243da084b3Smrg 253da084b3Smrg/* This code assumes that we are using ASCII. We don't use the ctype 263da084b3Smrg functions, as they depend on the current locale. On the other 273da084b3Smrg hand, we do use strcasecmp, but only on strings that we've checked 283da084b3Smrg to be pure ASCII. Bloody ``Code Set Independence''. */ 293da084b3Smrg 303da084b3Smrg#include <string.h> 313da084b3Smrg#include <strings.h> 3248c85eb7Smrg#include <stdio.h> 333da084b3Smrg 343da084b3Smrg#include <stdlib.h> 353da084b3Smrg 363da084b3Smrg#include "zlib.h" 373da084b3Smrgtypedef gzFile FontFilePtr; 383da084b3Smrg#define FontFileGetc(f) gzgetc(f) 393da084b3Smrg#define FontFileOpen(filename) gzopen(filename, "rb") 403da084b3Smrg#define FontFileClose(f) gzclose(f) 413da084b3Smrg 423da084b3Smrg#define MAXFONTFILENAMELEN 1024 433da084b3Smrg#define MAXFONTNAMELEN 1024 443da084b3Smrg 453da084b3Smrg#include <X11/fonts/fontenc.h> 463da084b3Smrg#include "fontencI.h" 473da084b3Smrg 483da084b3Smrg#define MAXALIASES 20 493da084b3Smrg 503da084b3Smrg#define EOF_TOKEN -1 513da084b3Smrg#define ERROR_TOKEN -2 523da084b3Smrg#define EOL_TOKEN 0 533da084b3Smrg#define NUMBER_TOKEN 1 543da084b3Smrg#define KEYWORD_TOKEN 2 553da084b3Smrg 563da084b3Smrg#define EOF_LINE -1 573da084b3Smrg#define ERROR_LINE -2 583da084b3Smrg#define STARTENCODING_LINE 1 593da084b3Smrg#define STARTMAPPING_LINE 2 603da084b3Smrg#define ENDMAPPING_LINE 3 613da084b3Smrg#define CODE_LINE 4 623da084b3Smrg#define CODE_RANGE_LINE 5 633da084b3Smrg#define CODE_UNDEFINE_LINE 6 643da084b3Smrg#define NAME_LINE 7 653da084b3Smrg#define SIZE_LINE 8 663da084b3Smrg#define ALIAS_LINE 9 673da084b3Smrg#define FIRSTINDEX_LINE 10 683da084b3Smrg 693da084b3Smrg/* Return from lexer */ 703da084b3Smrg#define MAXKEYWORDLEN 100 713da084b3Smrg 723da084b3Smrgstatic long number_value; 733da084b3Smrgstatic char keyword_value[MAXKEYWORDLEN+1]; 743da084b3Smrg 753da084b3Smrgstatic long value1, value2, value3; 763da084b3Smrg 773da084b3Smrg/* Lexer code */ 783da084b3Smrg 793da084b3Smrg/* Skip to the beginning of new line */ 803da084b3Smrgstatic void 813da084b3SmrgskipEndOfLine(FontFilePtr f, int c) 823da084b3Smrg{ 833da084b3Smrg if(c == 0) 843da084b3Smrg c = FontFileGetc(f); 8548c85eb7Smrg 863da084b3Smrg for(;;) 873da084b3Smrg if(c <= 0 || c == '\n') 883da084b3Smrg return; 893da084b3Smrg else 903da084b3Smrg c = FontFileGetc(f); 913da084b3Smrg} 923da084b3Smrg 933da084b3Smrg/* Get a number; we're at the first digit. */ 943da084b3Smrgstatic unsigned 953da084b3Smrggetnum(FontFilePtr f, int c, int *cp) 963da084b3Smrg{ 973da084b3Smrg unsigned n = 0; 983da084b3Smrg int base = 10; 993da084b3Smrg 1003da084b3Smrg /* look for `0' or `0x' prefix */ 1013da084b3Smrg if(c == '0') { 1023da084b3Smrg c = FontFileGetc(f); 1033da084b3Smrg base = 8; 1043da084b3Smrg if(c == 'x' || c == 'X') { 1053da084b3Smrg base = 16; 1063da084b3Smrg c = FontFileGetc(f); 1073da084b3Smrg } 1083da084b3Smrg } 1093da084b3Smrg 1103da084b3Smrg /* accumulate digits */ 1113da084b3Smrg for(;;) { 1123da084b3Smrg if ('0' <= c && c <= '9') { 1133da084b3Smrg n *= base; n += c - '0'; 1143da084b3Smrg } else if('a' <= c && c <= 'f') { 1153da084b3Smrg n *= base; n += c - 'a' + 10; 1163da084b3Smrg } else if('A' <=c && c <= 'F') { 1173da084b3Smrg n *= base; n += c - 'A' + 10; 1183da084b3Smrg } else 1193da084b3Smrg break; 1203da084b3Smrg c = FontFileGetc(f); 1213da084b3Smrg } 1223da084b3Smrg 1233da084b3Smrg *cp = c; return n; 1243da084b3Smrg} 12548c85eb7Smrg 1263da084b3Smrg/* Skip to beginning of new line; return 1 if only whitespace was found. */ 1273da084b3Smrgstatic int 1283da084b3SmrgendOfLine(FontFilePtr f, int c) 1293da084b3Smrg{ 1303da084b3Smrg if(c == 0) 1313da084b3Smrg c = FontFileGetc(f); 1323da084b3Smrg 1333da084b3Smrg for(;;) { 1343da084b3Smrg if(c <= 0 || c == '\n') 1353da084b3Smrg return 1; 1363da084b3Smrg else if(c == '#') { 1373da084b3Smrg skipEndOfLine(f,c); 1383da084b3Smrg return 1; 1393da084b3Smrg } 1403da084b3Smrg else if(c == ' ' || c == '\t') { 1413da084b3Smrg skipEndOfLine(f,c); 1423da084b3Smrg return 0; 1433da084b3Smrg } 1443da084b3Smrg c = FontFileGetc(f); 1453da084b3Smrg } 1463da084b3Smrg} 1473da084b3Smrg 1483da084b3Smrg/* Get a token; we're at first char */ 1493da084b3Smrgstatic int 1503da084b3Smrggettoken(FontFilePtr f, int c, int *cp) 1513da084b3Smrg{ 1523da084b3Smrg char *p; 1533da084b3Smrg 1543da084b3Smrg if(c <= 0) 1553da084b3Smrg c = FontFileGetc(f); 1563da084b3Smrg 1573da084b3Smrg if(c <= 0) { 1583da084b3Smrg return EOF_TOKEN; 1593da084b3Smrg } 1603da084b3Smrg 1613da084b3Smrg while(c == ' ' || c == '\t') 1623da084b3Smrg c = FontFileGetc(f); 1633da084b3Smrg 1643da084b3Smrg if(c=='\n') { 1653da084b3Smrg return EOL_TOKEN; 1663da084b3Smrg } else if(c == '#') { 1673da084b3Smrg skipEndOfLine(f,c); 1683da084b3Smrg return EOL_TOKEN; 1693da084b3Smrg } else if(c >= '0' && c <= '9') { 1703da084b3Smrg number_value = getnum(f,c,cp); 1713da084b3Smrg return NUMBER_TOKEN; 1723da084b3Smrg } else if((c >= 'A' && c <= 'Z') || 1733da084b3Smrg (c >= 'a' && c <= 'z') || 1743da084b3Smrg c == '/' || c == '_' || c == '-' || c == '.') { 1753da084b3Smrg p = keyword_value; 1763da084b3Smrg *p++ = c; 1773da084b3Smrg while(p-keyword_value < MAXKEYWORDLEN) { 1783da084b3Smrg c = FontFileGetc(f); 1793da084b3Smrg if(c <= ' ' || c > '~' || c == '#') 1803da084b3Smrg break; 1813da084b3Smrg *p++ = c; 1823da084b3Smrg } 1833da084b3Smrg *cp = c; 1843da084b3Smrg *p = '\0'; 1853da084b3Smrg return KEYWORD_TOKEN; 1863da084b3Smrg } else { 1873da084b3Smrg *cp = c; 1883da084b3Smrg return ERROR_TOKEN; 1893da084b3Smrg } 1903da084b3Smrg} 1913da084b3Smrg 1923da084b3Smrg/* Parse a line. 1933da084b3Smrg * Always skips to the beginning of a new line, even if an error occurs */ 1943da084b3Smrgstatic int 1953da084b3Smrggetnextline(FontFilePtr f) 1963da084b3Smrg{ 1973da084b3Smrg int c, token; 1983da084b3Smrg c = FontFileGetc(f); 1993da084b3Smrg if(c <= 0) 2003da084b3Smrg return EOF_LINE; 2013da084b3Smrg 2023da084b3Smrg again: 2033da084b3Smrg token=gettoken(f,c,&c); 2043da084b3Smrg 2053da084b3Smrg switch(token) { 2063da084b3Smrg case EOF_TOKEN: 2073da084b3Smrg return EOF_LINE; 2083da084b3Smrg case EOL_TOKEN: 2093da084b3Smrg /* empty line */ 2103da084b3Smrg c = FontFileGetc(f); 2113da084b3Smrg goto again; 2123da084b3Smrg case NUMBER_TOKEN: 2133da084b3Smrg value1 = number_value; 2143da084b3Smrg token = gettoken(f,c,&c); 2153da084b3Smrg switch(token) { 2163da084b3Smrg case NUMBER_TOKEN: 2173da084b3Smrg value2 = number_value; 2183da084b3Smrg token = gettoken(f,c,&c); 2193da084b3Smrg switch(token) { 2203da084b3Smrg case NUMBER_TOKEN: 2213da084b3Smrg value3 = number_value; 2223da084b3Smrg return CODE_RANGE_LINE; 2233da084b3Smrg case EOL_TOKEN: 2243da084b3Smrg return CODE_LINE; 2253da084b3Smrg default: 2263da084b3Smrg skipEndOfLine(f,c); 2273da084b3Smrg return ERROR_LINE; 2283da084b3Smrg } 2293da084b3Smrg case KEYWORD_TOKEN: 2303da084b3Smrg if(!endOfLine(f,c)) 2313da084b3Smrg return ERROR_LINE; 2323da084b3Smrg else 2333da084b3Smrg return NAME_LINE; 2343da084b3Smrg default: 2353da084b3Smrg skipEndOfLine(f,c); 2363da084b3Smrg return ERROR_LINE; 2373da084b3Smrg } 2383da084b3Smrg case KEYWORD_TOKEN: 2393da084b3Smrg if(!strcasecmp(keyword_value, "STARTENCODING")) { 2403da084b3Smrg token = gettoken(f,c,&c); 2413da084b3Smrg if(token == KEYWORD_TOKEN) { 2423da084b3Smrg if(endOfLine(f,c)) 2433da084b3Smrg return STARTENCODING_LINE; 2443da084b3Smrg else 2453da084b3Smrg return ERROR_LINE; 2463da084b3Smrg } else { 2473da084b3Smrg skipEndOfLine(f,c); 2483da084b3Smrg return ERROR_LINE; 2493da084b3Smrg } 2503da084b3Smrg } else if(!strcasecmp(keyword_value, "ALIAS")) { 2513da084b3Smrg token = gettoken(f,c,&c); 2523da084b3Smrg if(token == KEYWORD_TOKEN) { 2533da084b3Smrg if(endOfLine(f,c)) 2543da084b3Smrg return ALIAS_LINE; 2553da084b3Smrg else 2563da084b3Smrg return ERROR_LINE; 2573da084b3Smrg } else { 2583da084b3Smrg skipEndOfLine(f,c); 2593da084b3Smrg return ERROR_LINE; 2603da084b3Smrg } 2613da084b3Smrg } else if(!strcasecmp(keyword_value, "SIZE")) { 2623da084b3Smrg token = gettoken(f,c,&c); 2633da084b3Smrg if(token == NUMBER_TOKEN) { 2643da084b3Smrg value1 = number_value; 2653da084b3Smrg token = gettoken(f,c,&c); 2663da084b3Smrg switch(token) { 2673da084b3Smrg case NUMBER_TOKEN: 2683da084b3Smrg value2 = number_value; 2693da084b3Smrg return SIZE_LINE; 2703da084b3Smrg case EOL_TOKEN: 2713da084b3Smrg value2=0; 2723da084b3Smrg return SIZE_LINE; 2733da084b3Smrg default: 2743da084b3Smrg skipEndOfLine(f,c); 2753da084b3Smrg return ERROR_LINE; 2763da084b3Smrg } 2773da084b3Smrg } else { 2783da084b3Smrg skipEndOfLine(f,c); 2793da084b3Smrg return ERROR_LINE; 2803da084b3Smrg } 2813da084b3Smrg } else if(!strcasecmp(keyword_value, "FIRSTINDEX")) { 2823da084b3Smrg token = gettoken(f,c,&c); 2833da084b3Smrg if(token == NUMBER_TOKEN) { 2843da084b3Smrg value1 = number_value; 2853da084b3Smrg token = gettoken(f,c,&c); 2863da084b3Smrg switch(token) { 2873da084b3Smrg case NUMBER_TOKEN: 2883da084b3Smrg value2 = number_value; 2893da084b3Smrg return FIRSTINDEX_LINE; 2903da084b3Smrg case EOL_TOKEN: 2913da084b3Smrg value2 = 0; 2923da084b3Smrg return FIRSTINDEX_LINE; 2933da084b3Smrg default: 2943da084b3Smrg skipEndOfLine(f,c); 2953da084b3Smrg return ERROR_LINE; 2963da084b3Smrg } 2973da084b3Smrg } else { 2983da084b3Smrg skipEndOfLine(f,c); 2993da084b3Smrg return ERROR_LINE; 3003da084b3Smrg } 3013da084b3Smrg } else if(!strcasecmp(keyword_value, "STARTMAPPING")) { 3023da084b3Smrg keyword_value[0] = 0; 3033da084b3Smrg value1 = 0; value1 = 0; 3043da084b3Smrg /* first a keyword */ 3053da084b3Smrg token = gettoken(f,c,&c); 3063da084b3Smrg if(token != KEYWORD_TOKEN) { 3073da084b3Smrg skipEndOfLine(f, c); 3083da084b3Smrg return ERROR_LINE; 3093da084b3Smrg } 3103da084b3Smrg 3113da084b3Smrg /* optional first integer */ 3123da084b3Smrg token = gettoken(f,c,&c); 3133da084b3Smrg if(token == NUMBER_TOKEN) { 3143da084b3Smrg value1 = number_value; 3153da084b3Smrg } else if(token == EOL_TOKEN) { 3163da084b3Smrg return STARTMAPPING_LINE; 3173da084b3Smrg } else { 3183da084b3Smrg skipEndOfLine(f, c); 3193da084b3Smrg return ERROR_LINE; 3203da084b3Smrg } 3213da084b3Smrg 3223da084b3Smrg /* optional second integer */ 3233da084b3Smrg token = gettoken(f,c,&c); 3243da084b3Smrg if(token == NUMBER_TOKEN) { 3253da084b3Smrg value2 = number_value; 3263da084b3Smrg } else if(token == EOL_TOKEN) { 3273da084b3Smrg return STARTMAPPING_LINE; 3283da084b3Smrg } else { 3293da084b3Smrg skipEndOfLine(f, c); 3303da084b3Smrg return ERROR_LINE; 3313da084b3Smrg } 3323da084b3Smrg 3333da084b3Smrg if(!endOfLine(f,c)) 3343da084b3Smrg return ERROR_LINE; 3353da084b3Smrg else { 3363da084b3Smrg return STARTMAPPING_LINE; 3373da084b3Smrg } 3383da084b3Smrg } else if(!strcasecmp(keyword_value, "UNDEFINE")) { 3393da084b3Smrg /* first integer */ 3403da084b3Smrg token = gettoken(f,c,&c); 3413da084b3Smrg if(token != NUMBER_TOKEN) { 3423da084b3Smrg skipEndOfLine(f,c); 3433da084b3Smrg return ERROR_LINE; 3443da084b3Smrg } 3453da084b3Smrg value1 = number_value; 3463da084b3Smrg /* optional second integer */ 3473da084b3Smrg token = gettoken(f,c,&c); 3483da084b3Smrg if(token == EOL_TOKEN) { 3493da084b3Smrg value2 = value1; 3503da084b3Smrg return CODE_UNDEFINE_LINE; 3513da084b3Smrg } else if(token == NUMBER_TOKEN) { 3523da084b3Smrg value2 = number_value; 3533da084b3Smrg if(endOfLine(f,c)) { 3543da084b3Smrg return CODE_UNDEFINE_LINE; 3553da084b3Smrg } else 3563da084b3Smrg return ERROR_LINE; 3573da084b3Smrg } else { 3583da084b3Smrg skipEndOfLine(f,c); 3593da084b3Smrg return ERROR_LINE; 3603da084b3Smrg } 3613da084b3Smrg } else if(!strcasecmp(keyword_value, "ENDENCODING")) { 36248c85eb7Smrg if(endOfLine(f,c)) 3633da084b3Smrg return EOF_LINE; 3643da084b3Smrg else 3653da084b3Smrg return ERROR_LINE; 3663da084b3Smrg } else if(!strcasecmp(keyword_value, "ENDMAPPING")) { 3673da084b3Smrg if(endOfLine(f,c)) 3683da084b3Smrg return ENDMAPPING_LINE; 3693da084b3Smrg else 3703da084b3Smrg return ERROR_LINE; 3713da084b3Smrg } else { 3723da084b3Smrg skipEndOfLine(f,c); 3733da084b3Smrg return ERROR_LINE; 3743da084b3Smrg } 3753da084b3Smrg default: 3763da084b3Smrg return ERROR_LINE; 3773da084b3Smrg } 3783da084b3Smrg} 3793da084b3Smrg 38048c85eb7Smrgstatic void 3813da084b3Smrginstall_mapping(FontEncPtr encoding, FontMapPtr mapping) 3823da084b3Smrg{ 3833da084b3Smrg FontMapPtr m; 3843da084b3Smrg 3853da084b3Smrg if(encoding->mappings == NULL) 3863da084b3Smrg encoding->mappings = mapping; 3873da084b3Smrg else { 3883da084b3Smrg m = encoding->mappings; 3893da084b3Smrg while(m->next != NULL) 3903da084b3Smrg m = m->next; 3913da084b3Smrg m->next = mapping; 3923da084b3Smrg } 3933da084b3Smrg mapping->next = NULL; 3943da084b3Smrg mapping->encoding = encoding; 3953da084b3Smrg} 3963da084b3Smrg 3973da084b3Smrgstatic int 3983da084b3SmrgsetCode(unsigned from, unsigned to, unsigned row_size, 3993da084b3Smrg unsigned *first, unsigned *last, 4003da084b3Smrg unsigned *encsize, unsigned short **enc) 4013da084b3Smrg{ 4023da084b3Smrg unsigned index, i; 4033da084b3Smrg unsigned short *newenc; 4043da084b3Smrg 4053da084b3Smrg if(from>0xFFFF) 4063da084b3Smrg return 0; /* success */ 4073da084b3Smrg 4083da084b3Smrg if(row_size==0) 4093da084b3Smrg index=from; 4103da084b3Smrg else { 4113da084b3Smrg if((value1 & 0xFF) >= row_size) 4123da084b3Smrg return 0; /* ignore out of range mappings */ 4133da084b3Smrg index = (from>>8) * row_size + (from&0xFF); 4143da084b3Smrg } 4153da084b3Smrg 4163da084b3Smrg /* Optimize away useless identity mappings. This is only expected 4173da084b3Smrg to be useful with linear encodings. */ 4183da084b3Smrg if(index == to && (index < *first || index > *last)) 4193da084b3Smrg return 0; 4203da084b3Smrg if(*encsize == 0) { 4213da084b3Smrg *encsize = (index < 256) ? 256 : 0x10000; 42255acc8fcSmrg *enc = malloc((*encsize) * sizeof(unsigned short)); 4233da084b3Smrg if(*enc == NULL) { 4243da084b3Smrg *encsize = 0; 4253da084b3Smrg return 1; 4263da084b3Smrg } 4273da084b3Smrg } else if(*encsize <= index) { 4283da084b3Smrg *encsize = 0x10000; 42948c85eb7Smrg if((newenc = realloc(*enc, (*encsize) * sizeof(unsigned short)))==NULL) 4303da084b3Smrg return 1; 4313da084b3Smrg *enc = newenc; 4323da084b3Smrg } 4333da084b3Smrg if(*first > *last) { 4343da084b3Smrg *first = *last = index; 4353da084b3Smrg } 4363da084b3Smrg if(index < *first) { 4373da084b3Smrg for(i = index; i < *first; i++) 4383da084b3Smrg (*enc)[i] = i; 4393da084b3Smrg *first = index; 4403da084b3Smrg } 4413da084b3Smrg if(index > *last) { 4423da084b3Smrg for(i = *last + 1; i <= index; i++) 4433da084b3Smrg (*enc)[i] = i; 4443da084b3Smrg *last = index; 4453da084b3Smrg } 4463da084b3Smrg (*enc)[index] = to; 4473da084b3Smrg return 0; 4483da084b3Smrg} 4493da084b3Smrg 4503da084b3Smrg/* Parser. If headerOnly is true, we're only interested in the 4513da084b3Smrg data contained in the encoding file's header. */ 4523da084b3Smrg 4533da084b3Smrg/* As font encodings are currently never freed, the allocations done 4543da084b3Smrg by this function are mostly its private business. Note, however, 4553da084b3Smrg that FontEncIdentify needs to free the header fields -- so if you 4563da084b3Smrg change this function, you may need to change FontEncIdentify. */ 4573da084b3Smrg 4583da084b3Smrg/* I want a garbage collector. */ 4593da084b3Smrg 4603da084b3Smrgstatic FontEncPtr 4613da084b3SmrgparseEncodingFile(FontFilePtr f, int headerOnly) 4623da084b3Smrg{ 4633da084b3Smrg int line; 4643da084b3Smrg 4653da084b3Smrg unsigned short *enc=NULL; 4663da084b3Smrg char **nam = NULL, **newnam; 4673da084b3Smrg unsigned i, first = 0xFFFF, last=0, encsize=0, namsize=0; 4683da084b3Smrg FontEncPtr encoding = NULL; 4693da084b3Smrg FontMapPtr mapping = NULL; 4703da084b3Smrg FontEncSimpleMapPtr sm; 4713da084b3Smrg FontEncSimpleNamePtr sn; 4723da084b3Smrg char *aliases[MAXALIASES]; 4733da084b3Smrg int numaliases=0; 4743da084b3Smrg 4753da084b3Smrg#if 0 4763da084b3Smrg /* GCC complains about unused labels. Please fix GCC rather than 4773da084b3Smrg obfuscating my code. */ 4783da084b3Smrg no_encoding: 4793da084b3Smrg#endif 4803da084b3Smrg line = getnextline(f); 4813da084b3Smrg switch(line) { 4823da084b3Smrg case EOF_LINE: 4833da084b3Smrg goto error; 4843da084b3Smrg case STARTENCODING_LINE: 48555acc8fcSmrg encoding = malloc(sizeof(FontEncRec)); 4863da084b3Smrg if(encoding == NULL) 4873da084b3Smrg goto error; 48855acc8fcSmrg encoding->name = strdup(keyword_value); 4893da084b3Smrg if(encoding->name == NULL) 4903da084b3Smrg goto error; 4913da084b3Smrg encoding->size = 256; 4923da084b3Smrg encoding->row_size = 0; 4933da084b3Smrg encoding->mappings = NULL; 4943da084b3Smrg encoding->next = NULL; 4953da084b3Smrg encoding->first = encoding->first_col=0; 4963da084b3Smrg goto no_mapping; 4973da084b3Smrg default: 4983da084b3Smrg goto error; 4993da084b3Smrg } 5003da084b3Smrg 5013da084b3Smrg no_mapping: 5023da084b3Smrg line = getnextline(f); 5033da084b3Smrg switch(line) { 5043da084b3Smrg case EOF_LINE: goto done; 5053da084b3Smrg case ALIAS_LINE: 5063da084b3Smrg if(numaliases < MAXALIASES) { 50755acc8fcSmrg aliases[numaliases] = strdup(keyword_value); 5083da084b3Smrg if(aliases[numaliases] == NULL) 5093da084b3Smrg goto error; 5103da084b3Smrg numaliases++; 5113da084b3Smrg } 5123da084b3Smrg goto no_mapping; 5133da084b3Smrg case SIZE_LINE: 5143da084b3Smrg encoding->size = value1; 5153da084b3Smrg encoding->row_size = value2; 5163da084b3Smrg goto no_mapping; 5173da084b3Smrg case FIRSTINDEX_LINE: 5183da084b3Smrg encoding->first = value1; 5193da084b3Smrg encoding->first_col = value2; 5203da084b3Smrg goto no_mapping; 5213da084b3Smrg case STARTMAPPING_LINE: 5223da084b3Smrg if(headerOnly) 5233da084b3Smrg goto done; 5243da084b3Smrg if(!strcasecmp(keyword_value, "unicode")) { 52555acc8fcSmrg mapping = malloc(sizeof(FontMapRec)); 5263da084b3Smrg if(mapping == NULL) 5273da084b3Smrg goto error; 5283da084b3Smrg mapping->type = FONT_ENCODING_UNICODE; 5293da084b3Smrg mapping->pid = 0; 5303da084b3Smrg mapping->eid = 0; 5313da084b3Smrg mapping->recode = NULL; 5323da084b3Smrg mapping->name = NULL; 5333da084b3Smrg mapping->client_data = NULL; 5343da084b3Smrg mapping->next = NULL; 5353da084b3Smrg goto mapping; 5363da084b3Smrg } else if(!strcasecmp(keyword_value, "cmap")) { 53755acc8fcSmrg mapping = malloc(sizeof(FontMapRec)); 5383da084b3Smrg if(mapping == NULL) 5393da084b3Smrg goto error; 5403da084b3Smrg mapping->type = FONT_ENCODING_TRUETYPE; 5413da084b3Smrg mapping->pid = value1; 5423da084b3Smrg mapping->eid = value2; 5433da084b3Smrg mapping->recode = NULL; 5443da084b3Smrg mapping->name = NULL; 5453da084b3Smrg mapping->client_data = NULL; 5463da084b3Smrg mapping->next = NULL; 5473da084b3Smrg goto mapping; 5483da084b3Smrg } else if(!strcasecmp(keyword_value, "postscript")) { 54955acc8fcSmrg mapping = malloc(sizeof(FontMapRec)); 5503da084b3Smrg if(mapping == NULL) 5513da084b3Smrg goto error; 5523da084b3Smrg mapping->type = FONT_ENCODING_POSTSCRIPT; 5533da084b3Smrg mapping->pid = 0; 5543da084b3Smrg mapping->eid = 0; 5553da084b3Smrg mapping->recode = NULL; 5563da084b3Smrg mapping->name = NULL; 5573da084b3Smrg mapping->client_data = NULL; 5583da084b3Smrg mapping->next = NULL; 5593da084b3Smrg goto string_mapping; 5603da084b3Smrg } else { /* unknown mapping type -- ignore */ 5613da084b3Smrg goto skipmapping; 5623da084b3Smrg } 5633da084b3Smrg /* NOTREACHED */ 5643da084b3Smrg goto error; 5653da084b3Smrg default: goto no_mapping; /* ignore unknown lines */ 5663da084b3Smrg } 5673da084b3Smrg 5683da084b3Smrg skipmapping: 5693da084b3Smrg line = getnextline(f); 5703da084b3Smrg switch(line) { 5713da084b3Smrg case ENDMAPPING_LINE: 5723da084b3Smrg goto no_mapping; 5733da084b3Smrg case EOF_LINE: 5743da084b3Smrg goto error; 5753da084b3Smrg default: 5763da084b3Smrg goto skipmapping; 5773da084b3Smrg } 5783da084b3Smrg 5793da084b3Smrg mapping: 5803da084b3Smrg line = getnextline(f); 5813da084b3Smrg switch(line) { 5823da084b3Smrg case EOF_LINE: goto error; 5833da084b3Smrg case ENDMAPPING_LINE: 5843da084b3Smrg mapping->recode = FontEncSimpleRecode; 5853da084b3Smrg mapping->name = FontEncUndefinedName; 58655acc8fcSmrg mapping->client_data = sm = malloc(sizeof(FontEncSimpleMapRec)); 5873da084b3Smrg if(sm == NULL) 5883da084b3Smrg goto error; 5893da084b3Smrg sm->row_size = encoding->row_size; 5903da084b3Smrg if(first <= last) { 5913da084b3Smrg unsigned short *newmap; 5923da084b3Smrg 5933da084b3Smrg sm->first = first; 5943da084b3Smrg sm->len=last-first+1; 59555acc8fcSmrg newmap = malloc(sm->len * sizeof(unsigned short)); 5963da084b3Smrg if(newmap == NULL) { 59755acc8fcSmrg free(sm); 5983da084b3Smrg mapping->client_data = sm = NULL; 5993da084b3Smrg goto error; 6003da084b3Smrg } 6013da084b3Smrg for(i=0; i < sm->len; i++) 6023da084b3Smrg newmap[i] = enc[first+i]; 6033da084b3Smrg sm->map = newmap; 6043da084b3Smrg } else { 6053da084b3Smrg sm->first = 0; 6063da084b3Smrg sm->len = 0; 6073da084b3Smrg sm->map = NULL; 6083da084b3Smrg } 6093da084b3Smrg install_mapping(encoding, mapping); 6103da084b3Smrg mapping = NULL; 6113da084b3Smrg first = 0xFFFF; last=0; 6123da084b3Smrg goto no_mapping; 6133da084b3Smrg 6143da084b3Smrg case CODE_LINE: 6153da084b3Smrg if(setCode(value1, value2, encoding->row_size, 6163da084b3Smrg &first, &last, &encsize, &enc)) 6173da084b3Smrg goto error; 6183da084b3Smrg goto mapping; 6193da084b3Smrg 6203da084b3Smrg case CODE_RANGE_LINE: 6213da084b3Smrg if(value1 > 0x10000) 6223da084b3Smrg value1 = 0x10000; 6233da084b3Smrg if(value2 > 0x10000) 6243da084b3Smrg value2 = 0x10000; 6253da084b3Smrg if(value2 < value1) 6263da084b3Smrg goto mapping; 6273da084b3Smrg /* Do the last value first to avoid having to realloc() */ 6283da084b3Smrg if(setCode(value2, value3+(value2-value1), encoding->row_size, 6293da084b3Smrg &first, &last, &encsize, &enc)) 6303da084b3Smrg goto error; 6313da084b3Smrg for(i=value1; i<value2; i++) { 6323da084b3Smrg if(setCode(i, value3+(i-value1), encoding->row_size, 6333da084b3Smrg &first, &last, &encsize, &enc)) 6343da084b3Smrg goto error; 6353da084b3Smrg } 6363da084b3Smrg goto mapping; 63748c85eb7Smrg 6383da084b3Smrg case CODE_UNDEFINE_LINE: 6393da084b3Smrg if(value1 > 0x10000) 6403da084b3Smrg value1 = 0x10000; 6413da084b3Smrg if(value2 > 0x10000) 6423da084b3Smrg value2 = 0x10000; 6433da084b3Smrg if(value2 < value1) 6443da084b3Smrg goto mapping; 6453da084b3Smrg /* Do the last value first to avoid having to realloc() */ 6463da084b3Smrg if(setCode(value2, 0, encoding->row_size, 6473da084b3Smrg &first, &last, &encsize, &enc)) 6483da084b3Smrg goto error; 6493da084b3Smrg for(i = value1; i < value2; i++) { 6503da084b3Smrg if(setCode(i, 0, encoding->row_size, 6513da084b3Smrg &first, &last, &encsize, &enc)) 6523da084b3Smrg goto error; 6533da084b3Smrg } 6543da084b3Smrg goto mapping; 6553da084b3Smrg 6563da084b3Smrg default: goto mapping; /* ignore unknown lines */ 6573da084b3Smrg } 65848c85eb7Smrg 6593da084b3Smrg string_mapping: 6603da084b3Smrg line = getnextline(f); 6613da084b3Smrg switch(line) { 6623da084b3Smrg case EOF_LINE: goto error; 6633da084b3Smrg case ENDMAPPING_LINE: 6643da084b3Smrg mapping->recode = FontEncUndefinedRecode; 6653da084b3Smrg mapping->name = FontEncSimpleName; 66655acc8fcSmrg mapping->client_data = sn = malloc(sizeof(FontEncSimpleNameRec)); 6673da084b3Smrg if(sn == NULL) 6683da084b3Smrg goto error; 6693da084b3Smrg if(first > last) { 67055acc8fcSmrg free(sn); 6713da084b3Smrg mapping->client_data = sn = NULL; 6723da084b3Smrg goto error; 6733da084b3Smrg } 6743da084b3Smrg sn->first = first; 6753da084b3Smrg sn->len = last - first + 1; 67655acc8fcSmrg sn->map = malloc(sn->len*sizeof(char*)); 6773da084b3Smrg if(sn->map == NULL) { 67855acc8fcSmrg free(sn); 6793da084b3Smrg mapping->client_data = sn = NULL; 6803da084b3Smrg goto error; 6813da084b3Smrg } 6823da084b3Smrg for(i = 0; i < sn->len; i++) 6833da084b3Smrg sn->map[i] = nam[first+i]; 6843da084b3Smrg install_mapping(encoding,mapping); 6853da084b3Smrg mapping = NULL; 6863da084b3Smrg first = 0xFFFF; last=0; 6873da084b3Smrg goto no_mapping; 6883da084b3Smrg case NAME_LINE: 6893da084b3Smrg if(value1 >= 0x10000) goto string_mapping; 6903da084b3Smrg if(namsize == 0) { 6913da084b3Smrg namsize = (value1) < 256 ? 256 : 0x10000; 69255acc8fcSmrg nam = malloc(namsize * sizeof(char*)); 6933da084b3Smrg if(nam == NULL) { 6943da084b3Smrg namsize=0; 6953da084b3Smrg goto error; 6963da084b3Smrg } 6973da084b3Smrg } else if(namsize <= value1) { 6983da084b3Smrg namsize = 0x10000; 69955acc8fcSmrg if((newnam = (char**)realloc(nam, namsize)) == NULL) 7003da084b3Smrg goto error; 7013da084b3Smrg nam = newnam; 7023da084b3Smrg } 7033da084b3Smrg if(first > last) { 7043da084b3Smrg first = last = value1; 7053da084b3Smrg } 7063da084b3Smrg if(value1 < first) { 7073da084b3Smrg for(i = value1; i < first; i++) 7083da084b3Smrg nam[i] = NULL; 7093da084b3Smrg first = value1; 7103da084b3Smrg } 7113da084b3Smrg if(value1 > last) { 7123da084b3Smrg for(i=last+1; i <= value1; i++) 7133da084b3Smrg nam[i]=NULL; 7143da084b3Smrg last = value1; 7153da084b3Smrg } 71655acc8fcSmrg nam[value1] = strdup(keyword_value); 7173da084b3Smrg if(nam[value1] == NULL) { 7183da084b3Smrg goto error; 7193da084b3Smrg } 7203da084b3Smrg goto string_mapping; 7213da084b3Smrg 7223da084b3Smrg default: goto string_mapping; /* ignore unknown lines */ 7233da084b3Smrg } 7243da084b3Smrg 7253da084b3Smrg done: 72655acc8fcSmrg if(encsize) free(enc); encsize=0; enc = NULL; 72755acc8fcSmrg if(namsize) free(nam); namsize=0; nam = NULL; /* don't free entries! */ 7283da084b3Smrg 7293da084b3Smrg encoding->aliases=NULL; 7303da084b3Smrg if(numaliases) { 73155acc8fcSmrg encoding->aliases = malloc((numaliases+1)*sizeof(char*)); 7323da084b3Smrg if(encoding->aliases == NULL) 7333da084b3Smrg goto error; 7343da084b3Smrg for(i=0; i<numaliases; i++) 7353da084b3Smrg encoding->aliases[i] = aliases[i]; 7363da084b3Smrg encoding->aliases[numaliases]=NULL; 7373da084b3Smrg } 7383da084b3Smrg 7393da084b3Smrg return encoding; 7403da084b3Smrg 7413da084b3Smrgerror: 74255acc8fcSmrg if(encsize) free(enc); encsize=0; 7433da084b3Smrg if(namsize) { 7443da084b3Smrg for(i = first; i <= last; i++) 74555acc8fcSmrg free(nam[i]); 74655acc8fcSmrg free(nam); 7473da084b3Smrg } 7483da084b3Smrg if(mapping) { 74955acc8fcSmrg free(mapping->client_data); 75055acc8fcSmrg free(mapping); 7513da084b3Smrg } 7523da084b3Smrg if(encoding) { 7533da084b3Smrg FontMapPtr nextmap; 75455acc8fcSmrg free(encoding->name); 7553da084b3Smrg for (mapping = encoding->mappings; mapping; mapping = nextmap) { 75655acc8fcSmrg free(mapping->client_data); 7573da084b3Smrg nextmap = mapping->next; 75855acc8fcSmrg free(mapping); 7593da084b3Smrg } 76055acc8fcSmrg free(encoding); 7613da084b3Smrg } 7623da084b3Smrg for(i = 0; i < numaliases; i++) 76355acc8fcSmrg free(aliases[i]); 7643da084b3Smrg /* We don't need to free sn and sm as they handled locally in the body.*/ 7653da084b3Smrg return NULL; 7663da084b3Smrg} 7673da084b3Smrg 7683da084b3Smrgchar* 7693da084b3SmrgFontEncDirectory(void) 7703da084b3Smrg{ 7713da084b3Smrg static char* dir = NULL; 7723da084b3Smrg 7733da084b3Smrg if(dir == NULL) { 7743da084b3Smrg char *c = getenv("FONT_ENCODINGS_DIRECTORY"); 7753da084b3Smrg if(c) { 77655acc8fcSmrg dir = strdup(c); 7773da084b3Smrg if(!dir) 7783da084b3Smrg return NULL; 7793da084b3Smrg } else { 7803da084b3Smrg dir = FONT_ENCODINGS_DIRECTORY; 7813da084b3Smrg } 7823da084b3Smrg } 7833da084b3Smrg return dir; 7843da084b3Smrg} 7853da084b3Smrg 7863da084b3Smrgstatic void 7873da084b3SmrgparseFontFileName(const char *fontFileName, char *buf, char *dir) 7883da084b3Smrg{ 7893da084b3Smrg const char *p; 7903da084b3Smrg char *q, *lastslash; 79148c85eb7Smrg 7923da084b3Smrg for(p = fontFileName, q = dir, lastslash = NULL; *p; p++, q++) { 7933da084b3Smrg *q = *p; 7943da084b3Smrg if(*p == '/') 7953da084b3Smrg lastslash = q+1; 7963da084b3Smrg } 79748c85eb7Smrg 7983da084b3Smrg if(!lastslash) 7993da084b3Smrg lastslash = dir; 80048c85eb7Smrg 8013da084b3Smrg *lastslash = '\0'; 8023da084b3Smrg 8033da084b3Smrg if(buf && strlen(dir) + 14 < MAXFONTFILENAMELEN) { 8043da084b3Smrg strcpy(buf, dir); 8053da084b3Smrg strcat(buf, "encodings.dir"); 8063da084b3Smrg } 8073da084b3Smrg} 8083da084b3Smrg 8093da084b3Smrgstatic FontEncPtr 81048c85eb7SmrgFontEncReallyReallyLoad(const char *charset, 8113da084b3Smrg const char *dirname, const char *dir) 8123da084b3Smrg{ 8133da084b3Smrg FontFilePtr f; 8143da084b3Smrg FILE *file; 8153da084b3Smrg FontEncPtr encoding; 8163da084b3Smrg char file_name[MAXFONTFILENAMELEN], encoding_name[MAXFONTNAMELEN], 8173da084b3Smrg buf[MAXFONTFILENAMELEN]; 8183da084b3Smrg int count, n; 8193da084b3Smrg static char format[24] = ""; 82048c85eb7Smrg 8213da084b3Smrg /* As we don't really expect to open encodings that often, we don't 8223da084b3Smrg take the trouble of caching encodings directories. */ 8233da084b3Smrg 8243da084b3Smrg if((file = fopen(dirname, "r")) == NULL) { 8253da084b3Smrg return NULL; 8263da084b3Smrg } 82748c85eb7Smrg 8283da084b3Smrg count = fscanf(file, "%d\n", &n); 8293da084b3Smrg if(count == EOF || count != 1) { 8303da084b3Smrg fclose(file); 8313da084b3Smrg return NULL; 8323da084b3Smrg } 8333da084b3Smrg 8343da084b3Smrg encoding = NULL; 8353da084b3Smrg if (!format[0]) { 8363da084b3Smrg sprintf(format, "%%%ds %%%d[^\n]\n", (int)sizeof(encoding_name) - 1, 8373da084b3Smrg (int)sizeof(file_name) - 1); 8383da084b3Smrg } 8393da084b3Smrg for(;;) { 8403da084b3Smrg count = fscanf(file, format, encoding_name, file_name); 8413da084b3Smrg if(count == EOF) 8423da084b3Smrg break; 8433da084b3Smrg if(count != 2) 8443da084b3Smrg break; 8453da084b3Smrg 8463da084b3Smrg if(!strcasecmp(encoding_name, charset)) { 8473da084b3Smrg /* Found it */ 8483da084b3Smrg if(file_name[0] != '/') { 8493da084b3Smrg if(strlen(dir) + strlen(file_name) >= MAXFONTFILENAMELEN) { 8503da084b3Smrg fclose(file); 8513da084b3Smrg return NULL; 8523da084b3Smrg } 8533da084b3Smrg strcpy(buf, dir); 8543da084b3Smrg strcat(buf, file_name); 8553da084b3Smrg } else { 8563da084b3Smrg strcpy(buf , file_name); 8573da084b3Smrg } 8583da084b3Smrg 8593da084b3Smrg f = FontFileOpen(buf); 8603da084b3Smrg if(f == NULL) { 86148c85eb7Smrg fclose(file); 8623da084b3Smrg return NULL; 8633da084b3Smrg } 8643da084b3Smrg encoding = parseEncodingFile(f, 0); 8653da084b3Smrg FontFileClose(f); 8663da084b3Smrg break; 8673da084b3Smrg } 8683da084b3Smrg } 8693da084b3Smrg 8703da084b3Smrg fclose(file); 8713da084b3Smrg 8723da084b3Smrg return encoding; 8733da084b3Smrg} 8743da084b3Smrg 87548c85eb7Smrg/* Parser ntrypoint -- used by FontEncLoad */ 8763da084b3SmrgFontEncPtr 8773da084b3SmrgFontEncReallyLoad(const char *charset, const char *fontFileName) 8783da084b3Smrg{ 8793da084b3Smrg FontEncPtr encoding; 8803da084b3Smrg char dir[MAXFONTFILENAMELEN], dirname[MAXFONTFILENAMELEN]; 8813da084b3Smrg char *d; 8823da084b3Smrg 8833da084b3Smrg if(fontFileName) { 8843da084b3Smrg parseFontFileName(fontFileName, dirname, dir); 8853da084b3Smrg encoding = FontEncReallyReallyLoad(charset, dirname, dir); 8863da084b3Smrg if(encoding) 8873da084b3Smrg return(encoding); 8883da084b3Smrg } 88948c85eb7Smrg 8903da084b3Smrg d = FontEncDirectory(); 8913da084b3Smrg if(d) { 8923da084b3Smrg parseFontFileName(d, NULL, dir); 8933da084b3Smrg encoding = FontEncReallyReallyLoad(charset, d, dir); 8943da084b3Smrg return encoding; 8953da084b3Smrg } 89648c85eb7Smrg 8973da084b3Smrg return NULL; 8983da084b3Smrg} 8993da084b3Smrg 9003da084b3Smrg/* Return a NULL-terminated array of encoding names. Note that this 9013da084b3Smrg * function has incestuous knowledge of the allocations done by 9023da084b3Smrg * parseEncodingFile. */ 9033da084b3Smrg 9043da084b3Smrgchar ** 9053da084b3SmrgFontEncIdentify(const char *fileName) 9063da084b3Smrg{ 9073da084b3Smrg FontFilePtr f; 9083da084b3Smrg FontEncPtr encoding; 9093da084b3Smrg char **names, **name, **alias; 9103da084b3Smrg int numaliases; 91148c85eb7Smrg 9123da084b3Smrg if((f = FontFileOpen(fileName))==NULL) { 9133da084b3Smrg return NULL; 9143da084b3Smrg } 9153da084b3Smrg encoding = parseEncodingFile(f, 1); 9163da084b3Smrg FontFileClose(f); 9173da084b3Smrg 9183da084b3Smrg if(!encoding) 9193da084b3Smrg return NULL; 9203da084b3Smrg 9213da084b3Smrg numaliases = 0; 9223da084b3Smrg if(encoding->aliases) 9233da084b3Smrg for(alias = encoding->aliases; *alias; alias++) 9243da084b3Smrg numaliases++; 9253da084b3Smrg 92655acc8fcSmrg names = malloc((numaliases+2)*sizeof(char*)); 9273da084b3Smrg if(names == NULL) { 92855acc8fcSmrg free(encoding->aliases); 92955acc8fcSmrg free(encoding); 9303da084b3Smrg return NULL; 9313da084b3Smrg } 9323da084b3Smrg 9333da084b3Smrg name = names; 9343da084b3Smrg *(name++) = encoding->name; 9353da084b3Smrg if(numaliases > 0) 9363da084b3Smrg for(alias = encoding->aliases; *alias; alias++, name++) 9373da084b3Smrg *name = *alias; 9383da084b3Smrg 9393da084b3Smrg *name = NULL; 94055acc8fcSmrg free(encoding->aliases); 94155acc8fcSmrg free(encoding); 9423da084b3Smrg 9433da084b3Smrg return names; 9443da084b3Smrg} 945