1
/* $Header: /home/cvsroot/dvipdfmx/src/dpxutil.c,v 1.14 2011/03/06 03:14:13 chofchof Exp $
3
This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
5
Copyright (C) 2002 by Jin-Hwan Cho and Shunsaku Hirata,
6
the dvipdfmx project team <dvipdfmx@project.ktug.or.kr>
8
Copyright (C) 1998, 1999 by Mark A. Wicks <mwicks@kettering.edu>
10
This program is free software; you can redistribute it and/or modify
11
it under the terms of the GNU General Public License as published by
12
the Free Software Foundation; either version 2 of the License, or
13
(at your option) any later version.
15
This program is distributed in the hope that it will be useful,
16
but WITHOUT ANY WARRANTY; without even the implied warranty of
17
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
GNU General Public License for more details.
20
You should have received a copy of the GNU General Public License
21
along with this program; if not, write to the Free Software
22
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
40
if (c >= '0' && c <= '9')
42
else if (c >= 'a' && c <= 'f')
44
else if (c >= 'A' && c <= 'F')
51
sputx (unsigned char c, char **s, char *end)
53
char hi = (c >> 4), lo = c & 0x0f;
56
ERROR("Buffer overflow.");
57
**s = (hi < 10) ? hi + '0' : hi + '7';
58
*(*s+1) = (lo < 10) ? lo + '0' : lo + '7';
65
getxpair (unsigned char **s)
76
return ((hi << 4)| lo);
80
putxpair (unsigned char c, char **s)
82
char hi = (c >> 4), lo = c & 0x0f;
84
**s = (hi < 10) ? hi + '0' : hi + '7';
85
*(*s+1) = (lo < 10) ? lo + '0' : lo + '7';
91
/* Overflowed value is set to invalid char. */
93
ostrtouc (unsigned char **inbuf, unsigned char *inbufend, unsigned char *valid)
95
unsigned char *cur = *inbuf;
98
while (cur < inbufend && cur < *inbuf + 3 &&
99
(*cur >= '0' && *cur <= '7')) {
100
val = (val << 3) | (*cur - '0');
103
if (val > 255 || cur == *inbuf)
109
return (unsigned char) val;
113
esctouc (unsigned char **inbuf, unsigned char *inbufend, unsigned char *valid)
115
unsigned char unescaped, escaped;
120
/* Backslash, unbalanced paranthes */
121
case '\\': case ')': case '(':
125
/* Other escaped char */
126
case 'n': unescaped = '\n'; (*inbuf)++; break;
127
case 'r': unescaped = '\r'; (*inbuf)++; break;
128
case 't': unescaped = '\t'; (*inbuf)++; break;
129
case 'b': unescaped = '\b'; (*inbuf)++; break;
130
case 'f': unescaped = '\f'; (*inbuf)++; break;
132
* An end-of-line marker preceeded by backslash is not part of a
138
*inbuf += (*inbuf < inbufend - 1 && *(*inbuf+1) == '\n') ? 2 : 1;
145
/* Possibly octal notion */
147
unescaped = ostrtouc(inbuf, inbufend, valid);
154
skip_white_spaces (unsigned char **s, unsigned char *endptr)
164
ht_init_table (struct ht_table *ht, void (*hval_free_fn) (void *))
170
for (i = 0; i < HASH_TABLE_SIZE; i++) {
174
ht->hval_free_fn = hval_free_fn;
178
ht_clear_table (struct ht_table *ht)
184
for (i = 0; i < HASH_TABLE_SIZE; i++) {
185
struct ht_entry *hent, *next;
189
if (hent->value && ht->hval_free_fn) {
190
ht->hval_free_fn(hent->value);
204
ht->hval_free_fn = NULL;
207
long ht_table_size (struct ht_table *ht)
215
get_hash (const void *key, int keylen)
217
unsigned int hkey = 0;
220
for (i = 0; i < keylen; i++) {
221
hkey = (hkey << 5) + hkey + ((const char *)key)[i];
224
return (hkey % HASH_TABLE_SIZE);
228
ht_lookup_table (struct ht_table *ht, const void *key, int keylen)
230
struct ht_entry *hent;
235
hkey = get_hash(key, keylen);
236
hent = ht->table[hkey];
238
if (hent->keylen == keylen &&
239
!memcmp(hent->key, key, keylen)) {
249
ht_remove_table (struct ht_table *ht,
250
const void *key, int keylen)
251
/* returns 1 if the element was found and removed and 0 otherwise */
253
struct ht_entry *hent, *prev;
258
hkey = get_hash(key, keylen);
259
hent = ht->table[hkey];
262
if (hent->keylen == keylen &&
263
!memcmp(hent->key, key, keylen)) {
274
if (hent->value && ht->hval_free_fn) {
275
ht->hval_free_fn(hent->value);
279
prev->next = hent->next;
281
ht->table[hkey] = hent->next;
291
ht_modify_table (struct ht_table *ht,
292
const void *key, int keylen, void *value, int mode)
294
struct ht_entry *hent, *prev;
299
hkey = get_hash(key, keylen);
300
hent = ht->table[hkey];
303
if (hent->keylen == keylen &&
304
!memcmp(hent->key, key, keylen)) {
313
ASSERT(0); /* duplicates not allowed in this mode */
316
if (hent->value && ht->hval_free_fn)
317
ht->hval_free_fn(hent->value);
322
ht->hval_free_fn(value);
326
hent = NEW(1, struct ht_entry);
327
hent->key = NEW(keylen, char);
328
memcpy(hent->key, key, keylen);
329
hent->keylen = keylen;
335
ht->table[hkey] = hent;
342
ht_set_iter (struct ht_table *ht, struct ht_iter *iter)
346
ASSERT(ht && ht->table && iter);
348
for (i = 0; i < HASH_TABLE_SIZE; i++) {
351
iter->curr = ht->table[i];
361
ht_clear_iter (struct ht_iter *iter)
364
iter->index = HASH_TABLE_SIZE;
371
ht_iter_getkey (struct ht_iter *iter, int *keylen)
373
struct ht_entry *hent;
375
hent = (struct ht_entry *) iter->curr;
377
*keylen = hent->keylen;
386
ht_iter_getval (struct ht_iter *iter)
388
struct ht_entry *hent;
390
hent = (struct ht_entry *) iter->curr;
399
ht_iter_next (struct ht_iter *iter)
401
struct ht_entry *hent;
407
hent = (struct ht_entry *) iter->curr;
410
++iter->index < HASH_TABLE_SIZE) {
411
hent = ht->table[iter->index];
415
return (hent ? 0 : -1);
420
read_c_escchar (char *r, const char **pp, const char *endptr)
426
case 'a' : c = '\a'; p++; break;
427
case 'b' : c = '\b'; p++; break;
428
case 'f' : c = '\f'; p++; break;
429
case 'n' : c = '\n'; p++; break;
430
case 'r' : c = '\r'; p++; break;
431
case 't' : c = '\t'; p++; break;
432
case 'v' : c = '\v'; p++; break;
433
case '\\': case '?': case '\'': case '\"':
436
case '\n': l = 0; p++; break;
440
if (p < endptr && p[0] == '\n')
445
case '0': case '1': case '2': case '3':
446
case '4': case '5': case '6': case '7':
450
i < 3 && p < endptr &&
451
p[0] >= '0' && p[0] <= '7'; i++, p++)
452
c = (c << 3) + (p[0] - '0');
458
for (c = 0, i = 0, p++;
459
i < 2 && p < endptr && isxdigit(p[0]);
464
(islower(p[0]) ? p[0] - 'a' + 10: p[0] - 'A' + 10));
468
WARN("Unknown escape char sequence: \\%c", p[0]);
480
#define C_ESCAPE '\\'
482
read_c_litstrc (char *q, int len, const char **pp, const char *endptr)
488
#define Q_ERROR_UNTERM -1
489
#define Q_ERROR_INVAL -2
490
#define Q_ERROR_BUFF -3
494
s == Q_CONT && p < endptr; ) {
504
l += read_c_escchar(q ? &q[l] : NULL, &p, endptr);
507
case '\n': case '\r':
531
return ((s == Q_TERM) ? l : s);
535
parse_c_string (const char **pp, const char *endptr)
541
if (p >= endptr || p[0] != C_QUOTE)
545
l = read_c_litstrc(NULL, 0, &p, endptr);
547
q = NEW(l + 1, char);
549
l = read_c_litstrc(q, l + 1, &p, endptr);
556
#define ISCNONDIGITS(c) ( \
558
((c) >= 'a' && (c) <= 'z') || \
559
((c) >= 'A' && (c) <= 'Z') \
561
#define ISCIDENTCHAR(c) ( \
562
ISCNONDIGITS((c)) || \
563
((c) >= '0' && (c) <= '9') \
567
parse_c_ident (const char **pp, const char *endptr)
573
if (p >= endptr || !ISCNONDIGITS(*p))
576
for (n = 0; p < endptr && ISCIDENTCHAR(*p); p++, n++);
577
q = NEW(n + 1, char);
578
memcpy(q, *pp, n); q[n] = '\0';
585
parse_float_decimal (const char **pp, const char *endptr)
594
if (p[0] == '+' || p[0] == '-')
597
/* 1. .01 001 001E-001 */
598
for (s = 0, n = 0; p < endptr && s >= 0; ) {
614
case '0': case '1': case '2': case '3': case '4':
615
case '5': case '6': case '7': case '8': case '9':
619
if (n == 0 || s == 2)
633
q = NEW(n + 1, char);
634
memcpy(q, *pp, n); q[n] = '\0';