remap.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623
  1. /*
  2. * Copyright 2008 Department of Mathematical Sciences, New Mexico State University
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is 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
  17. * DEPARTMENT OF MATHEMATICAL SCIENCES OR NEW MEXICO STATE UNIVERSITY BE
  18. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
  19. * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  20. * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  21. */
  22. #include <stdio.h>
  23. #include <string.h>
  24. #ifdef WIN32
  25. #include <windows.h>
  26. #else
  27. #include <stdlib.h>
  28. #include <unistd.h>
  29. #endif
  30. /*
  31. * Structure for managing simple lists in place.
  32. */
  33. typedef struct {
  34. unsigned char *bfield;
  35. unsigned long bsize;
  36. unsigned long bused;
  37. unsigned char **field;
  38. unsigned long size;
  39. unsigned long used;
  40. } list_t;
  41. /*
  42. * Callback type used with the high speed text file reader function.
  43. */
  44. typedef int (*scanlines_callback_t)(unsigned char *line, unsigned long linelen,
  45. unsigned long lineno, void *client_data);
  46. /*
  47. * Various utility routines.
  48. */
  49. #define setsbit(m, cc) (m[(cc) >> 3] |= (1 << ((cc) & 7)))
  50. #define sbitset(m, cc) (m[(cc) >> 3] & (1 << ((cc) & 7)))
  51. /*
  52. * An empty string for empty fields.
  53. */
  54. static unsigned char empty[1] = { 0 };
  55. /*
  56. * Assume the line is NULL terminated and that the `list' parameter was
  57. * initialized the first time it was used.
  58. */
  59. static void
  60. splitline(unsigned char *separators, unsigned char *line,
  61. unsigned long linelen, list_t *list)
  62. {
  63. int mult, final_empty;
  64. unsigned char *sp, *ep, *end;
  65. unsigned char seps[32];
  66. /*
  67. * Initialize the list.
  68. */
  69. list->used = list->bused = 0;
  70. /*
  71. * If the line is empty, then simply return.
  72. */
  73. if (linelen == 0 || line[0] == 0)
  74. return;
  75. /*
  76. * If the `separators' parameter is NULL or empty, split the list into
  77. * individual bytes.
  78. */
  79. if (separators == 0 || *separators == 0) {
  80. if (linelen > list->bsize) {
  81. if (list->bsize)
  82. list->bfield = (unsigned char *) malloc(linelen);
  83. else
  84. list->bfield = (unsigned char *) realloc(list->bfield, linelen);
  85. list->bsize = linelen;
  86. }
  87. list->bused = linelen;
  88. (void) memcpy(list->bfield, line, linelen);
  89. return;
  90. }
  91. /*
  92. * Prepare the separator bitmap.
  93. */
  94. (void) memset((char *) seps, 0, 32);
  95. /*
  96. * If the very last character of the separator string is a plus, then set
  97. * the `mult' flag to indicate that multiple separators should be
  98. * collapsed into one.
  99. */
  100. for (mult = 0, sp = separators; sp && *sp; sp++) {
  101. if (*sp == '+' && *(sp + 1) == 0)
  102. mult = 1;
  103. else
  104. setsbit(seps, *sp);
  105. }
  106. /*
  107. * Break the line up into fields.
  108. */
  109. for (final_empty = 0, sp = ep = line, end = sp + linelen;
  110. sp < end && *sp;) {
  111. /*
  112. * Collect everything that is not a separator.
  113. */
  114. for (; ep < end && *ep && !sbitset(seps, *ep); ep++) ;
  115. /*
  116. * Resize the list if necessary.
  117. */
  118. if (list->used == list->size) {
  119. if (list->size == 0)
  120. list->field = (unsigned char **)
  121. malloc(sizeof(unsigned char *) << 3);
  122. else
  123. list->field = (unsigned char **)
  124. realloc((char *) list->field,
  125. sizeof(unsigned char *) * (list->size + 8));
  126. list->size += 8;
  127. }
  128. /*
  129. * Assign the field appropriately.
  130. */
  131. list->field[list->used++] = (ep > sp) ? sp : empty;
  132. sp = ep;
  133. if (mult) {
  134. /*
  135. * If multiple separators should be collapsed, do it now by
  136. * setting all the separator characters to 0.
  137. */
  138. for (; ep < end && *ep && sbitset(seps, *ep); ep++)
  139. *ep = 0;
  140. } else
  141. /*
  142. * Don't collapse multiple separators by making them 0, so just
  143. * make the one encountered 0.
  144. */
  145. *ep++ = 0;
  146. final_empty = (ep > sp && *ep == 0);
  147. sp = ep;
  148. }
  149. /*
  150. * Finally, NULL terminate the list.
  151. */
  152. if (list->used + final_empty + 1 >= list->size) {
  153. if (list->used == list->size) {
  154. if (list->size == 0)
  155. list->field = (unsigned char **)
  156. malloc(sizeof(unsigned char *) << 3);
  157. else
  158. list->field = (unsigned char **)
  159. realloc((unsigned char *) list->field,
  160. sizeof(char *) * (list->size + 8));
  161. list->size += 8;
  162. }
  163. }
  164. if (final_empty)
  165. list->field[list->used++] = empty;
  166. if (list->used == list->size) {
  167. if (list->size == 0)
  168. list->field = (unsigned char **)
  169. malloc(sizeof(unsigned char *) << 3);
  170. else
  171. list->field = (unsigned char **)
  172. realloc((char *) list->field,
  173. sizeof(unsigned char *) * (list->size + 8));
  174. list->size += 8;
  175. }
  176. list->field[list->used] = 0;
  177. }
  178. static int
  179. scanlines(int fd, scanlines_callback_t callback, void *client_data,
  180. unsigned long *lineno)
  181. {
  182. unsigned long lno;
  183. int n, res, done, refill, bytes, hold;
  184. char *ls, *le, *pp, *pe, *hp;
  185. char buf[65536];
  186. if (callback == 0)
  187. return -1;
  188. lno = 1;
  189. (void) memset(buf, 0, 65536);
  190. res = done = 0;
  191. pp = ls = le = buf;
  192. bytes = 65536;
  193. while (!done && (n = read(fd, pp, bytes)) > 0) {
  194. /*
  195. * Determine the new end of the buffer pages.
  196. */
  197. pe = pp + n;
  198. for (refill = 0; done == 0 && refill == 0; ) {
  199. while (le < pe && *le != '\n' && *le != '\r')
  200. le++;
  201. if (le == pe) {
  202. /*
  203. * Hit the end of the last page in the buffer.
  204. * Need to find out how many pages to shift
  205. * and how many pages need to be read in.
  206. * Adjust the line start and end pointers down
  207. * to point to the right places in the pages.
  208. */
  209. pp = buf + (((ls - buf) >> 13) << 13);
  210. n = pp - buf;
  211. ls -= n;
  212. le -= n;
  213. n = pe - pp;
  214. (void) memcpy(buf, pp, n);
  215. pp = buf + n;
  216. bytes = 65536 - n;
  217. refill = 1;
  218. } else {
  219. /*
  220. * Temporarily NULL terminate the line.
  221. */
  222. hp = le;
  223. hold = *le;
  224. *le = 0;
  225. if (callback && *ls != '#' && *ls != 0x1a && le > ls &&
  226. (res = (*callback)((unsigned char *) ls, le - ls, lno,
  227. client_data)) != 0)
  228. done = 1;
  229. else {
  230. ls = ++le;
  231. /*
  232. * Handle the case of DOS CRLF sequences.
  233. */
  234. if (le < pe && hold == '\n' && *le =='\r')
  235. ls = ++le;
  236. }
  237. /*
  238. * Increment the line number.
  239. */
  240. lno++;
  241. /*
  242. * Restore the character at the end of the line.
  243. */
  244. *hp = hold;
  245. }
  246. }
  247. }
  248. /*
  249. * Return with the last line number processed.
  250. */
  251. *lineno = lno;
  252. return res;
  253. }
  254. static unsigned char a2i[128] = {
  255. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  256. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  257. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  258. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  259. 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x00, 0x00,
  260. 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00,
  261. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  262. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  263. 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
  264. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  265. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  266. };
  267. static unsigned char odigits[32] = {
  268. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
  269. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  270. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  271. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  272. };
  273. static unsigned char ddigits[32] = {
  274. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03,
  275. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  276. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  277. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  278. };
  279. static unsigned char hdigits[32] = {
  280. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03,
  281. 0x7e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00,
  282. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  283. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  284. };
  285. #define isdigok(m, d) (m[(d) >> 3] & (1 << ((d) & 7)))
  286. static unsigned short
  287. my_atous(unsigned char *s, unsigned char **end, int base)
  288. {
  289. unsigned short v;
  290. unsigned char *dmap;
  291. if (s == 0 || *s == 0)
  292. return 0;
  293. /*
  294. * Make sure the radix is something recognizable. Default to 10.
  295. */
  296. switch (base) {
  297. case 8: dmap = odigits; break;
  298. case 16: dmap = hdigits; break;
  299. default: base = 10; dmap = ddigits; break;
  300. }
  301. /*
  302. * Check for the special hex prefix.
  303. */
  304. if (*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X')) {
  305. base = 16;
  306. dmap = hdigits;
  307. s += 2;
  308. }
  309. for (v = 0; isdigok(dmap, *s); s++)
  310. v = (v * base) + a2i[(int) *s];
  311. if (end != 0)
  312. *end = s;
  313. return v;
  314. }
  315. /********************************************************************
  316. *
  317. * Routines to load, unload, and use mapping tables to remap BDF fonts
  318. * during generation by otf2bdf.
  319. *
  320. ********************************************************************/
  321. /*
  322. * Strings used to store the registry and encoding values specified
  323. * in the mapping table.
  324. */
  325. static char *registry;
  326. static char *encoding;
  327. /*
  328. * Trie node structure.
  329. */
  330. typedef struct {
  331. unsigned short key; /* Key value. */
  332. unsigned short val; /* Data for the key. */
  333. unsigned long sibs; /* Offset of siblings from trie beginning. */
  334. unsigned long kids; /* Offset of children from trie beginning. */
  335. } node_t;
  336. /*
  337. * The trie used for remapping codes.
  338. */
  339. static node_t *nodes;
  340. static unsigned long nodes_size = 0;
  341. static unsigned long nodes_used = 0;
  342. /*
  343. * Gets the next available node in the trie.
  344. */
  345. static unsigned long
  346. getnode(unsigned short key)
  347. {
  348. unsigned long loc;
  349. node_t *np;
  350. if (nodes_used == nodes_size) {
  351. if (nodes_size == 0)
  352. nodes = (node_t *) malloc(sizeof(node_t) << 7);
  353. else
  354. nodes = (node_t *) realloc((char *) nodes, sizeof(node_t) *
  355. (nodes_size + 128));
  356. np = nodes + nodes_size;
  357. nodes_size += 128;
  358. (void) memset((char *) np, 0, sizeof(node_t) << 7);
  359. }
  360. loc = nodes_used++;
  361. np = nodes + loc;
  362. np->kids = np->sibs = 0;
  363. np->key = key;
  364. return loc;
  365. }
  366. /*
  367. * Inserts a node in the trie.
  368. */
  369. static void
  370. trie_insert(unsigned short key, unsigned short val)
  371. {
  372. unsigned long i, n, t, l;
  373. unsigned short codes[2];
  374. /*
  375. * Convert the incoming key into two codes to make the trie lookup more
  376. * efficient.
  377. */
  378. codes[0] = (key >> 8) & 0xff;
  379. codes[1] = key & 0xff;
  380. for (i = t = 0; i < 2; i++) {
  381. if (nodes[t].kids == 0) {
  382. n = getnode(codes[i]);
  383. nodes[t].kids = n;
  384. t = n;
  385. } else if (nodes[nodes[t].kids].key == codes[i])
  386. t = nodes[t].kids;
  387. else if (nodes[nodes[t].kids].key > codes[i]) {
  388. n = getnode(codes[i]);
  389. nodes[n].sibs = nodes[t].kids;
  390. nodes[t].kids = n;
  391. t = n;
  392. } else {
  393. t = nodes[t].kids;
  394. for (l = t; nodes[t].sibs && nodes[t].key < codes[i]; ) {
  395. l = t;
  396. t = nodes[t].sibs;
  397. }
  398. if (nodes[t].key < codes[i]) {
  399. n = getnode(codes[i]);
  400. nodes[t].sibs = n;
  401. t = n;
  402. } else if (nodes[t].key > codes[i]) {
  403. n = getnode(codes[i]);
  404. nodes[n].sibs = t;
  405. nodes[l].sibs = n;
  406. t = n;
  407. }
  408. }
  409. }
  410. /*
  411. * Set the value in the leaf node.
  412. */
  413. nodes[t].val = val;
  414. }
  415. /*
  416. * List used by the routine that parses the map lines.
  417. */
  418. static list_t list;
  419. /*
  420. * Routine to parse each line of the mapping file.
  421. */
  422. static int
  423. add_mapping(unsigned char *line, unsigned long linelen, unsigned long lineno,
  424. void *client_data)
  425. {
  426. unsigned short key, val;
  427. /*
  428. * Split the line into parts separted by one or more spaces or tabs.
  429. */
  430. splitline((unsigned char *) " \t+", line, linelen, &list);
  431. /*
  432. * Check to see if the line starts with one of the keywords.
  433. */
  434. if (memcmp((char *) list.field[0], "REGISTRY", 8) == 0) {
  435. /*
  436. * Collect the XLFD CHARSET_REGISTRY value.
  437. */
  438. if (registry != 0)
  439. free((char *) registry);
  440. if ((val = strlen((char *) list.field[1])) == 0)
  441. registry = 0;
  442. else {
  443. registry = (char *) malloc(val + 1);
  444. (void) memcpy(registry, (char *) list.field[1], val + 1);
  445. }
  446. return 0;
  447. }
  448. if (memcmp((char *) list.field[0], "ENCODING", 8) == 0) {
  449. /*
  450. * Collect the XLFD CHARSET_ENCODING value.
  451. */
  452. if (encoding != 0)
  453. free((char *) encoding);
  454. if ((val = strlen((char *) list.field[1])) == 0)
  455. encoding = 0;
  456. else {
  457. encoding = (char *) malloc(val + 1);
  458. (void) memcpy(encoding, (char *) list.field[1], val + 1);
  459. }
  460. return 0;
  461. }
  462. /*
  463. * Get the second field value as the key (the Unicode value). Always
  464. * assume the values are in hex.
  465. */
  466. key = my_atous(list.field[1], 0, 16);
  467. val = my_atous(list.field[0], 0, 16);
  468. trie_insert(key, val);
  469. return 0;
  470. }
  471. /********************************************************************
  472. *
  473. * API for mapping table support.
  474. *
  475. ********************************************************************/
  476. int
  477. otf2bdf_load_map(FILE *in)
  478. {
  479. unsigned long lineno;
  480. /*
  481. * Allocate some nodes initially.
  482. */
  483. if (nodes_size == 0) {
  484. nodes = (node_t *) malloc(sizeof(node_t) << 7);
  485. nodes_size = 128;
  486. }
  487. /*
  488. * Reset the trie in case more than one gets loaded for some reason.
  489. */
  490. if (nodes_size > 0)
  491. (void) memset((char *) nodes, 0, sizeof(node_t) * nodes_size);
  492. nodes_used = 1;
  493. return scanlines(fileno(in), add_mapping, 0, &lineno);
  494. }
  495. /*
  496. * Routine that deallocates the mapping trie.
  497. */
  498. void
  499. otf2bdf_free_map(void)
  500. {
  501. if (registry != 0)
  502. free((char *) registry);
  503. if (encoding != 0)
  504. free((char *) encoding);
  505. registry = encoding = 0;
  506. if (list.size > 0)
  507. free((char *) list.field);
  508. list.size = list.used = 0;
  509. if (nodes_size > 0)
  510. free((char *) nodes);
  511. nodes_size = nodes_used = 0;
  512. }
  513. /*
  514. * The routine that actually remaps the code by looking it up in the trie.
  515. */
  516. int
  517. otf2bdf_remap(unsigned short *code)
  518. {
  519. unsigned long i, n, t;
  520. unsigned short c, codes[2];
  521. /*
  522. * If no mapping table was loaded, then simply return the code.
  523. */
  524. if (nodes_used == 0)
  525. return 1;
  526. c = *code;
  527. codes[0] = (c >> 8) & 0xff;
  528. codes[1] = c & 0xff;
  529. for (i = n = 0; i < 2; i++) {
  530. t = nodes[n].kids;
  531. if (t == 0)
  532. return 0;
  533. for (; nodes[t].sibs && nodes[t].key != codes[i]; t = nodes[t].sibs);
  534. if (nodes[t].key != codes[i])
  535. return 0;
  536. n = t;
  537. }
  538. *code = nodes[n].val;
  539. return 1;
  540. }
  541. void
  542. otf2bdf_remap_charset(char **registry_name, char **encoding_name)
  543. {
  544. if (registry_name != 0)
  545. *registry_name = registry;
  546. if (encoding_name != 0)
  547. *encoding_name = encoding;
  548. }