1 /* This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
2
3 Copyright (C) 2002-2014 by Jin-Hwan Cho and Shunsaku Hirata,
4 the dvipdfmx project team.
5
6 Copyright (C) 1998, 1999 by Mark A. Wicks <mwicks@kettering.edu>
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <stdarg.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <time.h>
32
33 #include "system.h"
34 #include "mem.h"
35 #include "error.h"
36
37 #include "dpxutil.h"
38
39 int
xtoi(char c)40 xtoi (char c)
41 {
42 if (c >= '0' && c <= '9')
43 return (c - '0');
44 else if (c >= 'a' && c <= 'f')
45 return (c - 'W');
46 else if (c >= 'A' && c <= 'F')
47 return (c - '7');
48 else
49 return -1;
50 }
51
52 int
sputx(unsigned char c,char ** s,char * end)53 sputx (unsigned char c, char **s, char *end)
54 {
55 char hi = (c >> 4), lo = c & 0x0f;
56
57 if (*s + 2 > end)
58 ERROR("Buffer overflow.");
59 **s = (hi < 10) ? hi + '0' : hi + '7';
60 *(*s+1) = (lo < 10) ? lo + '0' : lo + '7';
61 *s += 2;
62
63 return 2;
64 }
65
66 int
getxpair(unsigned char ** s)67 getxpair (unsigned char **s)
68 {
69 int hi, lo;
70 hi = xtoi(**s);
71 if (hi < 0)
72 return hi;
73 (*s)++;
74 lo = xtoi(**s);
75 if (lo < 0)
76 return lo;
77 (*s)++;
78 return ((hi << 4)| lo);
79 }
80
81 int
putxpair(unsigned char c,char ** s)82 putxpair (unsigned char c, char **s)
83 {
84 char hi = (c >> 4), lo = c & 0x0f;
85
86 **s = (hi < 10) ? hi + '0' : hi + '7';
87 *(*s+1) = (lo < 10) ? lo + '0' : lo + '7';
88 *s += 2;
89
90 return 2;
91 }
92
93 /* Overflowed value is set to invalid char. */
94 unsigned char
ostrtouc(unsigned char ** inbuf,unsigned char * inbufend,unsigned char * valid)95 ostrtouc (unsigned char **inbuf, unsigned char *inbufend, unsigned char *valid)
96 {
97 unsigned char *cur = *inbuf;
98 unsigned int val = 0;
99
100 while (cur < inbufend && cur < *inbuf + 3 &&
101 (*cur >= '0' && *cur <= '7')) {
102 val = (val << 3) | (*cur - '0');
103 cur++;
104 }
105 if (val > 255 || cur == *inbuf)
106 *valid = 0;
107 else
108 *valid = 1;
109
110 *inbuf = cur;
111 return (unsigned char) val;
112 }
113
114 unsigned char
esctouc(unsigned char ** inbuf,unsigned char * inbufend,unsigned char * valid)115 esctouc (unsigned char **inbuf, unsigned char *inbufend, unsigned char *valid)
116 {
117 unsigned char unescaped, escaped;
118
119 escaped = **inbuf;
120 *valid = 1;
121 switch (escaped) {
122 /* Backslash, unbalanced paranthes */
123 case '\\': case ')': case '(':
124 unescaped = escaped;
125 (*inbuf)++;
126 break;
127 /* Other escaped char */
128 case 'n': unescaped = '\n'; (*inbuf)++; break;
129 case 'r': unescaped = '\r'; (*inbuf)++; break;
130 case 't': unescaped = '\t'; (*inbuf)++; break;
131 case 'b': unescaped = '\b'; (*inbuf)++; break;
132 case 'f': unescaped = '\f'; (*inbuf)++; break;
133 /*
134 * An end-of-line marker preceeded by backslash is not part of a
135 * literal string
136 */
137 case '\r':
138 unescaped = 0;
139 *valid = 0;
140 *inbuf += (*inbuf < inbufend - 1 && *(*inbuf+1) == '\n') ? 2 : 1;
141 break;
142 case '\n':
143 unescaped = 0;
144 *valid = 0;
145 (*inbuf)++;
146 break;
147 /* Possibly octal notion */
148 default:
149 unescaped = ostrtouc(inbuf, inbufend, valid);
150 }
151
152 return unescaped;
153 }
154
155 void
skip_white_spaces(unsigned char ** s,unsigned char * endptr)156 skip_white_spaces (unsigned char **s, unsigned char *endptr)
157 {
158 while (*s < endptr)
159 if (!is_space(**s))
160 break;
161 else
162 (*s)++;
163 }
164
165 void
ht_init_table(struct ht_table * ht,hval_free_func hval_free_fn)166 ht_init_table (struct ht_table *ht, hval_free_func hval_free_fn)
167 {
168 int i;
169
170 ASSERT(ht);
171
172 for (i = 0; i < HASH_TABLE_SIZE; i++) {
173 ht->table[i] = NULL;
174 }
175 ht->count = 0;
176 ht->hval_free_fn = hval_free_fn;
177 }
178
179 void
ht_clear_table(struct ht_table * ht)180 ht_clear_table (struct ht_table *ht)
181 {
182 int i;
183
184 ASSERT(ht);
185
186 for (i = 0; i < HASH_TABLE_SIZE; i++) {
187 struct ht_entry *hent, *next;
188
189 hent = ht->table[i];
190 while (hent) {
191 if (hent->value && ht->hval_free_fn) {
192 ht->hval_free_fn(hent->value);
193 }
194 hent->value = NULL;
195 if (hent->key) {
196 RELEASE(hent->key);
197 }
198 hent->key = NULL;
199 next = hent->next;
200 RELEASE(hent);
201 hent = next;
202 }
203 ht->table[i] = NULL;
204 }
205 ht->count = 0;
206 ht->hval_free_fn = NULL;
207 }
208
ht_table_size(struct ht_table * ht)209 long ht_table_size (struct ht_table *ht)
210 {
211 ASSERT(ht);
212
213 return ht->count;
214 }
215
216 static unsigned int
get_hash(const void * key,int keylen)217 get_hash (const void *key, int keylen)
218 {
219 unsigned int hkey = 0;
220 int i;
221
222 for (i = 0; i < keylen; i++) {
223 hkey = (hkey << 5) + hkey + ((const char *)key)[i];
224 }
225
226 return (hkey % HASH_TABLE_SIZE);
227 }
228
229 void *
ht_lookup_table(struct ht_table * ht,const void * key,int keylen)230 ht_lookup_table (struct ht_table *ht, const void *key, int keylen)
231 {
232 struct ht_entry *hent;
233 unsigned int hkey;
234
235 ASSERT(ht && key);
236
237 hkey = get_hash(key, keylen);
238 hent = ht->table[hkey];
239 while (hent) {
240 if (hent->keylen == keylen &&
241 !memcmp(hent->key, key, keylen)) {
242 return hent->value;
243 }
244 hent = hent->next;
245 }
246
247 return NULL;
248 }
249
250 int
ht_remove_table(struct ht_table * ht,const void * key,int keylen)251 ht_remove_table (struct ht_table *ht,
252 const void *key, int keylen)
253 /* returns 1 if the element was found and removed and 0 otherwise */
254 {
255 struct ht_entry *hent, *prev;
256 unsigned int hkey;
257
258 ASSERT(ht && key);
259
260 hkey = get_hash(key, keylen);
261 hent = ht->table[hkey];
262 prev = NULL;
263 while (hent) {
264 if (hent->keylen == keylen &&
265 !memcmp(hent->key, key, keylen)) {
266 break;
267 }
268 prev = hent;
269 hent = hent->next;
270 }
271 if (hent) {
272 if (hent->key)
273 RELEASE(hent->key);
274 hent->key = NULL;
275 hent->keylen = 0;
276 if (hent->value && ht->hval_free_fn) {
277 ht->hval_free_fn(hent->value);
278 }
279 hent->value = NULL;
280 if (prev) {
281 prev->next = hent->next;
282 } else {
283 ht->table[hkey] = hent->next;
284 }
285 RELEASE(hent);
286 ht->count--;
287 return 1;
288 } else
289 return 0;
290 }
291
292 /* replace... */
293 void
ht_insert_table(struct ht_table * ht,const void * key,int keylen,void * value)294 ht_insert_table (struct ht_table *ht,
295 const void *key, int keylen, void *value)
296 {
297 struct ht_entry *hent, *prev;
298 unsigned int hkey;
299
300 ASSERT(ht && key);
301
302 hkey = get_hash(key, keylen);
303 hent = ht->table[hkey];
304 prev = NULL;
305 while (hent) {
306 if (hent->keylen == keylen &&
307 !memcmp(hent->key, key, keylen)) {
308 break;
309 }
310 prev = hent;
311 hent = hent->next;
312 }
313 if (hent) {
314 if (hent->value && ht->hval_free_fn)
315 ht->hval_free_fn(hent->value);
316 hent->value = value;
317 } else {
318 hent = NEW(1, struct ht_entry);
319 hent->key = NEW(keylen, char);
320 memcpy(hent->key, key, keylen);
321 hent->keylen = keylen;
322 hent->value = value;
323 hent->next = NULL;
324 if (prev) {
325 prev->next = hent;
326 } else {
327 ht->table[hkey] = hent;
328 }
329 ht->count++;
330 }
331 }
332
333 void
ht_append_table(struct ht_table * ht,const void * key,int keylen,void * value)334 ht_append_table (struct ht_table *ht,
335 const void *key, int keylen, void *value)
336 {
337 struct ht_entry *hent, *last;
338 unsigned int hkey;
339
340 hkey = get_hash(key, keylen);
341 hent = ht->table[hkey];
342 if (!hent) {
343 hent = NEW(1, struct ht_entry);
344 ht->table[hkey] = hent;
345 } else {
346 while (hent) {
347 last = hent;
348 hent = hent->next;
349 }
350 hent = NEW(1, struct ht_entry);
351 last->next = hent;
352 }
353 hent->key = NEW(keylen, char);
354 memcpy(hent->key, key, keylen);
355 hent->keylen = keylen;
356 hent->value = value;
357 hent->next = NULL;
358
359 ht->count++;
360 }
361
362 int
ht_set_iter(struct ht_table * ht,struct ht_iter * iter)363 ht_set_iter (struct ht_table *ht, struct ht_iter *iter)
364 {
365 int i;
366
367 ASSERT(ht && ht->table && iter);
368
369 for (i = 0; i < HASH_TABLE_SIZE; i++) {
370 if (ht->table[i]) {
371 iter->index = i;
372 iter->curr = ht->table[i];
373 iter->hash = ht;
374 return 0;
375 }
376 }
377
378 return -1;
379 }
380
381 void
ht_clear_iter(struct ht_iter * iter)382 ht_clear_iter (struct ht_iter *iter)
383 {
384 if (iter) {
385 iter->index = HASH_TABLE_SIZE;
386 iter->curr = NULL;
387 iter->hash = NULL;
388 }
389 }
390
391 char *
ht_iter_getkey(struct ht_iter * iter,int * keylen)392 ht_iter_getkey (struct ht_iter *iter, int *keylen)
393 {
394 struct ht_entry *hent;
395
396 hent = (struct ht_entry *) iter->curr;
397 if (iter && hent) {
398 *keylen = hent->keylen;
399 return hent->key;
400 } else {
401 *keylen = 0;
402 return NULL;
403 }
404 }
405
406 void *
ht_iter_getval(struct ht_iter * iter)407 ht_iter_getval (struct ht_iter *iter)
408 {
409 struct ht_entry *hent;
410
411 hent = (struct ht_entry *) iter->curr;
412 if (iter && hent) {
413 return hent->value;
414 } else {
415 return NULL;
416 }
417 }
418
419 int
ht_iter_next(struct ht_iter * iter)420 ht_iter_next (struct ht_iter *iter)
421 {
422 struct ht_entry *hent;
423 struct ht_table *ht;
424
425 ASSERT(iter);
426
427 ht = iter->hash;
428 hent = (struct ht_entry *) iter->curr;
429 hent = hent->next;
430 while (!hent &&
431 ++iter->index < HASH_TABLE_SIZE) {
432 hent = ht->table[iter->index];
433 }
434 iter->curr = hent;
435
436 return (hent ? 0 : -1);
437 }
438
439
440 static int
read_c_escchar(char * r,const char ** pp,const char * endptr)441 read_c_escchar (char *r, const char **pp, const char *endptr)
442 {
443 int c = 0, l = 1;
444 const char *p = *pp;
445
446 switch (p[0]) {
447 case 'a' : c = '\a'; p++; break;
448 case 'b' : c = '\b'; p++; break;
449 case 'f' : c = '\f'; p++; break;
450 case 'n' : c = '\n'; p++; break;
451 case 'r' : c = '\r'; p++; break;
452 case 't' : c = '\t'; p++; break;
453 case 'v' : c = '\v'; p++; break;
454 case '\\': case '?': case '\'': case '\"':
455 c = p[0]; p++;
456 break;
457 case '\n': l = 0; p++; break;
458 case '\r':
459 {
460 p++;
461 if (p < endptr && p[0] == '\n')
462 p++;
463 l = 0;
464 }
465 break;
466 case '0': case '1': case '2': case '3':
467 case '4': case '5': case '6': case '7':
468 {
469 int i;
470 for (c = 0, i = 0;
471 i < 3 && p < endptr &&
472 p[0] >= '0' && p[0] <= '7'; i++, p++)
473 c = (c << 3) + (p[0] - '0');
474 }
475 break;
476 case 'x':
477 {
478 int i;
479 for (c = 0, i = 0, p++;
480 i < 2 && p < endptr && isxdigit((unsigned char)p[0]);
481 i++, p++)
482 c = (c << 4) +
483 (isdigit((unsigned char)p[0]) ?
484 p[0] - '0' :
485 (islower((unsigned char)p[0]) ? p[0] - 'a' + 10: p[0] - 'A' + 10));
486 }
487 break;
488 default:
489 WARN("Unknown escape char sequence: \\%c", p[0]);
490 l = 0; p++;
491 break;
492 }
493
494 if (r)
495 *r = (char) c;
496 *pp = p;
497 return l;
498 }
499
500 #define C_QUOTE '"'
501 #define C_ESCAPE '\\'
502 static int
read_c_litstrc(char * q,int len,const char ** pp,const char * endptr)503 read_c_litstrc (char *q, int len, const char **pp, const char *endptr)
504 {
505 const char *p;
506 int l = 0;
507 #define Q_TERM 0
508 #define Q_CONT -1
509 #define Q_ERROR_UNTERM -1
510 #define Q_ERROR_INVAL -2
511 #define Q_ERROR_BUFF -3
512 int s = Q_CONT;
513
514 for (l = 0, p = *pp;
515 s == Q_CONT && p < endptr; ) {
516 switch (p[0]) {
517 case C_QUOTE:
518 s = Q_TERM; p++;
519 break;
520 case C_ESCAPE:
521 if (q && l == len)
522 s = Q_ERROR_BUFF;
523 else {
524 p++;
525 l += read_c_escchar(q ? &q[l] : NULL, &p, endptr);
526 }
527 break;
528 case '\n': case '\r':
529 s = Q_ERROR_INVAL;
530 break;
531 default:
532 if (q && l == len)
533 s = Q_ERROR_BUFF;
534 else {
535 if (!q)
536 l++;
537 else
538 q[l++] = p[0];
539 p++;
540 }
541 break;
542 }
543 }
544 if (s == Q_TERM) {
545 if (q && l == len)
546 s = Q_ERROR_BUFF;
547 else if (q)
548 q[l++] = '\0';
549 }
550
551 *pp = p;
552 return ((s == Q_TERM) ? l : s);
553 }
554
555 char *
parse_c_string(const char ** pp,const char * endptr)556 parse_c_string (const char **pp, const char *endptr)
557 {
558 char *q = NULL;
559 const char *p = *pp;
560 int l = 0;
561
562 if (p >= endptr || p[0] != C_QUOTE)
563 return NULL;
564
565 p++;
566 l = read_c_litstrc(NULL, 0, &p, endptr);
567 if (l >= 0) {
568 q = NEW(l + 1, char);
569 p = *pp + 1;
570 l = read_c_litstrc(q, l + 1, &p, endptr);
571 }
572
573 *pp = p;
574 return q;
575 }
576
577 #define ISCNONDIGITS(c) ( \
578 (c) == '_' || \
579 ((c) >= 'a' && (c) <= 'z') || \
580 ((c) >= 'A' && (c) <= 'Z') \
581 )
582 #define ISCIDENTCHAR(c) ( \
583 ISCNONDIGITS((c)) || \
584 ((c) >= '0' && (c) <= '9') \
585 )
586
587 char *
parse_c_ident(const char ** pp,const char * endptr)588 parse_c_ident (const char **pp, const char *endptr)
589 {
590 char *q = NULL;
591 const char *p = *pp;
592 int n;
593
594 if (p >= endptr || !ISCNONDIGITS(*p))
595 return NULL;
596
597 for (n = 0; p < endptr && ISCIDENTCHAR(*p); p++, n++);
598 q = NEW(n + 1, char);
599 memcpy(q, *pp, n); q[n] = '\0';
600
601 *pp = p;
602 return q;
603 }
604
605 char *
parse_float_decimal(const char ** pp,const char * endptr)606 parse_float_decimal (const char **pp, const char *endptr)
607 {
608 char *q = NULL;
609 const char *p = *pp;
610 int s = 0, n = 0;
611
612 if (p >= endptr)
613 return NULL;
614
615 if (p[0] == '+' || p[0] == '-')
616 p++;
617
618 /* 1. .01 001 001E-001 */
619 for (s = 0, n = 0; p < endptr && s >= 0; ) {
620 switch (p[0]) {
621 case '+': case '-':
622 if (s != 2)
623 s = -1;
624 else {
625 s = 3; p++;
626 }
627 break;
628 case '.':
629 if (s > 0)
630 s = -1;
631 else {
632 s = 1; p++;
633 }
634 break;
635 case '0': case '1': case '2': case '3': case '4':
636 case '5': case '6': case '7': case '8': case '9':
637 n++; p++;
638 break;
639 case 'E': case 'e':
640 if (n == 0 || s == 2)
641 s = -1;
642 else {
643 s = 2; p++;
644 }
645 break;
646 default:
647 s = -1;
648 break;
649 }
650 }
651
652 if (n != 0) {
653 n = (int) (p - *pp);
654 q = NEW(n + 1, char);
655 memcpy(q, *pp, n); q[n] = '\0';
656 }
657
658 *pp = p;
659 return q;
660 }
661