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