Back to index

texmacs  1.0.7.15
dpxutil.c
Go to the documentation of this file.
00001 /*  $Header: /home/cvsroot/dvipdfmx/src/dpxutil.c,v 1.13 2009/09/20 14:52:41 matthias Exp $
00002 
00003     This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
00004 
00005     Copyright (C) 2002 by Jin-Hwan Cho and Shunsaku Hirata,
00006     the dvipdfmx project team <dvipdfmx@project.ktug.or.kr>
00007 
00008     Copyright (C) 1998, 1999 by Mark A. Wicks <mwicks@kettering.edu>
00009 
00010     This program is free software; you can redistribute it and/or modify
00011     it under the terms of the GNU General Public License as published by
00012     the Free Software Foundation; either version 2 of the License, or
00013     (at your option) any later version.
00014 
00015     This program is distributed in the hope that it will be useful,
00016     but WITHOUT ANY WARRANTY; without even the implied warranty of
00017     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018     GNU General Public License for more details.
00019 
00020     You should have received a copy of the GNU General Public License
00021     along with this program; if not, write to the Free Software
00022     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
00023 */
00024 
00025 #include <stdarg.h>
00026 #include <stdio.h>
00027 #include <stdlib.h>
00028 #include <string.h>
00029 #include <time.h>
00030 
00031 #include "system.h"
00032 #include "mem.h"
00033 #include "error.h"
00034 
00035 #include "dpxutil.h"
00036 
00037 int
00038 xtoi (char c)
00039 {
00040   if (c >= '0' && c <= '9')
00041     return (c - '0');
00042   else if (c >= 'a' && c <= 'f')
00043     return (c - 'W');
00044   else if (c >= 'A' && c <= 'F')
00045     return (c - '7');
00046   else
00047     return -1;
00048 }
00049 
00050 int
00051 sputx (unsigned char c, char **s, char *end)
00052 {
00053   char hi = (c >> 4), lo = c & 0x0f;
00054 
00055   if (*s + 2 > end)
00056     ERROR("Buffer overflow.");
00057   **s = (hi < 10) ? hi + '0' : hi + '7';
00058   *(*s+1) = (lo < 10) ? lo + '0' : lo + '7';
00059   *s += 2;
00060 
00061   return 2;
00062 }
00063 
00064 int
00065 getxpair (unsigned char **s)
00066 {
00067   int hi, lo;
00068   hi = xtoi(**s);
00069   if (hi < 0)
00070     return hi;
00071   (*s)++;
00072   lo = xtoi(**s);
00073   if (lo < 0)
00074     return lo;
00075   (*s)++;
00076   return ((hi << 4)| lo);
00077 }
00078 
00079 int
00080 putxpair (unsigned char c, char **s)
00081 {
00082   char hi = (c >> 4), lo = c & 0x0f;
00083 
00084   **s = (hi < 10) ? hi + '0' : hi + '7';
00085   *(*s+1) = (lo < 10) ? lo + '0' : lo + '7';
00086   *s += 2;
00087 
00088   return 2;
00089 }
00090 
00091 /* Overflowed value is set to invalid char.  */
00092 unsigned char
00093 ostrtouc (unsigned char **inbuf, unsigned char *inbufend, unsigned char *valid)
00094 {
00095   unsigned char *cur = *inbuf;
00096   unsigned int   val = 0;
00097 
00098   while (cur < inbufend && cur < *inbuf + 3 &&
00099         (*cur >= '0' && *cur <= '7')) {
00100     val = (val << 3) | (*cur - '0');
00101     cur++;
00102   }
00103   if (val > 255 || cur == *inbuf)
00104     *valid = 0;
00105   else
00106     *valid = 1;
00107 
00108   *inbuf = cur;
00109   return (unsigned char) val;
00110 }
00111 
00112 unsigned char
00113 esctouc (unsigned char **inbuf, unsigned char *inbufend, unsigned char *valid)
00114 {
00115   unsigned char unescaped, escaped;
00116 
00117   escaped = **inbuf;
00118   *valid    = 1;
00119   switch (escaped) {
00120     /* Backslash, unbalanced paranthes */
00121   case '\\': case ')': case '(':
00122     unescaped = escaped;
00123     (*inbuf)++;
00124     break;
00125     /* Other escaped char */ 
00126   case 'n': unescaped = '\n'; (*inbuf)++; break;
00127   case 'r': unescaped = '\r'; (*inbuf)++; break;
00128   case 't': unescaped = '\t'; (*inbuf)++; break;
00129   case 'b': unescaped = '\b'; (*inbuf)++; break;
00130   case 'f': unescaped = '\f'; (*inbuf)++; break;
00131     /*
00132      * An end-of-line marker preceeded by backslash is not part of a
00133      * literal string
00134      */
00135   case '\r':
00136     unescaped = 0;
00137     *valid    = 0;
00138     *inbuf   += (*inbuf < inbufend - 1 && *(*inbuf+1) == '\n') ? 2 : 1;
00139     break;
00140   case '\n':
00141     unescaped = 0;
00142     *valid    = 0;
00143     (*inbuf)++;
00144     break;
00145     /* Possibly octal notion */ 
00146   default:
00147     unescaped = ostrtouc(inbuf, inbufend, valid);
00148   }
00149 
00150   return unescaped;
00151 }
00152 
00153 void
00154 skip_white_spaces (unsigned char **s, unsigned char *endptr)
00155 {
00156   while (*s < endptr)
00157     if (!is_space(**s))
00158       break;
00159     else
00160       (*s)++;
00161 }
00162 
00163 void
00164 ht_init_table (struct ht_table *ht, void (*hval_free_fn) (void *))
00165 {
00166   int  i;
00167 
00168   ASSERT(ht);
00169 
00170   for (i = 0; i < HASH_TABLE_SIZE; i++) {
00171     ht->table[i] = NULL;
00172   }
00173   ht->count = 0;
00174   ht->hval_free_fn = hval_free_fn;
00175 }
00176 
00177 void
00178 ht_clear_table (struct ht_table *ht)
00179 {
00180   int   i;
00181 
00182   ASSERT(ht);
00183 
00184   for (i = 0; i < HASH_TABLE_SIZE; i++) {
00185     struct ht_entry *hent, *next;
00186 
00187     hent = ht->table[i];
00188     while (hent) {
00189       if (hent->value && ht->hval_free_fn) {
00190        ht->hval_free_fn(hent->value);
00191       }
00192       hent->value  = NULL;
00193       if (hent->key) {
00194        RELEASE(hent->key);
00195       }
00196       hent->key = NULL;
00197       next = hent->next;
00198       RELEASE(hent);
00199       hent = next;
00200     }
00201     ht->table[i] = NULL;
00202   }
00203   ht->count = 0;
00204   ht->hval_free_fn = NULL;
00205 }
00206 
00207 long ht_table_size (struct ht_table *ht)
00208 {
00209   ASSERT(ht);
00210 
00211   return ht->count;
00212 }
00213 
00214 static unsigned int
00215 get_hash (const void *key, int keylen)
00216 {
00217   unsigned int hkey = 0;
00218   int      i;
00219 
00220   for (i = 0; i < keylen; i++) {
00221     hkey = (hkey << 5) + hkey + ((char *)key)[i];
00222   }
00223 
00224   return (hkey % HASH_TABLE_SIZE);
00225 }
00226 
00227 void *
00228 ht_lookup_table (struct ht_table *ht, const void *key, int keylen)
00229 {
00230   struct ht_entry *hent;
00231   unsigned int     hkey;
00232 
00233   ASSERT(ht && key);
00234 
00235   hkey = get_hash(key, keylen);
00236   hent = ht->table[hkey];
00237   while (hent) {
00238     if (hent->keylen == keylen &&
00239        !memcmp(hent->key, key, keylen)) {
00240       return hent->value;
00241     }
00242     hent = hent->next;
00243   }
00244 
00245   return NULL;
00246 }
00247 
00248 int
00249 ht_remove_table (struct ht_table *ht,
00250                const void *key, int keylen)
00251 /* returns 1 if the element was found and removed and 0 otherwise */
00252 {
00253   struct ht_entry *hent, *prev;
00254   unsigned int     hkey;
00255 
00256   ASSERT(ht && key);
00257 
00258   hkey = get_hash(key, keylen);
00259   hent = ht->table[hkey];
00260   prev = NULL;
00261   while (hent) {
00262     if (hent->keylen == keylen &&
00263        !memcmp(hent->key, key, keylen)) {
00264       break;
00265     }
00266     prev = hent;
00267     hent = hent->next;
00268   }
00269   if (hent) {
00270     if (hent->key)
00271       RELEASE(hent->key);
00272     hent->key    = NULL;
00273     hent->keylen = 0;
00274     if (hent->value && ht->hval_free_fn) {
00275       ht->hval_free_fn(hent->value);
00276     }
00277     hent->value  = NULL;
00278     if (prev) {
00279       prev->next = hent->next;
00280     } else {
00281       ht->table[hkey] = hent->next;
00282     }
00283     RELEASE(hent);
00284     ht->count--;
00285     return 1;
00286   } else
00287     return 0;
00288 }
00289 
00290 void
00291 ht_modify_table (struct ht_table *ht,
00292                const void *key, int keylen, void *value, int mode)
00293 {
00294   struct ht_entry *hent, *prev;
00295   unsigned int     hkey;
00296 
00297   ASSERT(ht && key);
00298 
00299   hkey = get_hash(key, keylen);
00300   hent = ht->table[hkey];
00301   prev = NULL;
00302   while (hent) {
00303     if (hent->keylen == keylen &&
00304        !memcmp(hent->key, key, keylen)) {
00305       break;
00306     }
00307     prev = hent;
00308     hent = hent->next;
00309   }
00310   if (hent) {
00311     switch (mode) {
00312     case HT_NEW:
00313       ASSERT(0); /* duplicates not allowed in this mode */
00314       break;
00315     case HT_REPLACE: {
00316       if (hent->value && ht->hval_free_fn)
00317        ht->hval_free_fn(hent->value);
00318       hent->value  = value;
00319       break;
00320     }
00321     case HT_KEEP:
00322       ht->hval_free_fn(value);
00323       break;
00324     }
00325   } else {
00326     hent = NEW(1, struct ht_entry);
00327     hent->key = NEW(keylen, char);
00328     memcpy(hent->key, key, keylen);
00329     hent->keylen = keylen;
00330     hent->value  = value;
00331     hent->next   = NULL;
00332     if (prev) {
00333       prev->next      = hent;
00334     } else {
00335       ht->table[hkey] = hent;
00336     }
00337     ht->count++;
00338   }
00339 }
00340 
00341 int
00342 ht_set_iter (struct ht_table *ht, struct ht_iter *iter)
00343 {
00344   int    i;
00345 
00346   ASSERT(ht && ht->table && iter);
00347 
00348   for (i = 0; i < HASH_TABLE_SIZE; i++) {
00349     if (ht->table[i]) {
00350       iter->index = i;
00351       iter->curr  = ht->table[i];
00352       iter->hash  = ht;
00353       return 0;
00354     }
00355   }
00356 
00357   return -1;
00358 }
00359 
00360 void
00361 ht_clear_iter (struct ht_iter *iter)
00362 {
00363   if (iter) {
00364     iter->index = HASH_TABLE_SIZE;
00365     iter->curr  = NULL;
00366     iter->hash  = NULL;
00367   }
00368 }
00369 
00370 char *
00371 ht_iter_getkey (struct ht_iter *iter, int *keylen)
00372 {
00373   struct ht_entry *hent;
00374 
00375   hent = (struct ht_entry *) iter->curr;
00376   if (iter && hent) {
00377     *keylen = hent->keylen;
00378     return hent->key;
00379   } else {
00380     *keylen = 0;
00381     return NULL;
00382   }
00383 }
00384 
00385 void *
00386 ht_iter_getval (struct ht_iter *iter)
00387 {
00388   struct ht_entry *hent;
00389 
00390   hent = (struct ht_entry *) iter->curr;
00391   if (iter && hent) {
00392     return hent->value;
00393   } else {
00394     return NULL;
00395   }
00396 }
00397 
00398 int
00399 ht_iter_next (struct ht_iter *iter)
00400 {
00401   struct ht_entry *hent;
00402   struct ht_table *ht;
00403 
00404   ASSERT(iter);
00405 
00406   ht   = iter->hash;
00407   hent = (struct ht_entry *) iter->curr;
00408   hent = hent->next;
00409   while (!hent &&
00410          ++iter->index < HASH_TABLE_SIZE) {
00411     hent = ht->table[iter->index];
00412   }
00413   iter->curr = hent;
00414 
00415   return (hent ? 0 : -1);
00416 }
00417 
00418 
00419 static int
00420 read_c_escchar (char *r, char **pp, char *endptr)
00421 {
00422   int   c = 0, l = 1;
00423   char *p = *pp;
00424 
00425   switch (p[0]) {
00426   case 'a' : c = '\a'; p++; break;
00427   case 'b' : c = '\b'; p++; break;
00428   case 'f' : c = '\f'; p++; break;
00429   case 'n' : c = '\n'; p++; break;
00430   case 'r' : c = '\r'; p++; break;
00431   case 't' : c = '\t'; p++; break;
00432   case 'v' : c = '\v'; p++; break;
00433   case '\\': case '?': case '\'': case '\"':
00434     c = p[0]; p++;
00435     break;
00436   case '\n': l = 0; p++; break;
00437   case '\r':
00438     {
00439       p++;
00440       if (p < endptr && p[0] == '\n')
00441         p++;
00442       l = 0;
00443     }
00444     break;
00445   case '0': case '1': case '2': case '3':
00446   case '4': case '5': case '6': case '7':
00447     {
00448       int  i;
00449       for (c = 0, i = 0;
00450            i < 3 && p < endptr &&
00451            p[0] >= '0' && p[0] <= '7'; i++, p++)
00452         c = (c << 3) + (p[0] - '0');
00453     }
00454     break;
00455   case 'x':
00456     {
00457       int  i;
00458       for (c = 0, i = 0, p++;
00459            i < 2 && p < endptr && isxdigit(p[0]);
00460            i++, p++)
00461         c = (c << 4) +
00462             (isdigit(p[0]) ?
00463              p[0] - '0' :
00464              (islower(p[0]) ? p[0] - 'a' + 10: p[0] - 'A' + 10));
00465     }
00466     break;
00467   default:
00468     WARN("Unknown escape char sequence: \\%c", p[0]);
00469     l = 0; p++;
00470     break;
00471   }
00472 
00473   if (r)
00474     *r = (char) c;
00475   *pp  = p;
00476   return  l;
00477 }
00478 
00479 #define C_QUOTE  '"'
00480 #define C_ESCAPE '\\'
00481 static int
00482 read_c_litstrc (char *q, int len, char **pp, char *endptr)
00483 {
00484   char  *p;
00485   int    l = 0;
00486 #define Q_TERM          0
00487 #define Q_CONT         -1
00488 #define Q_ERROR_UNTERM -1
00489 #define Q_ERROR_INVAL  -2
00490 #define Q_ERROR_BUFF   -3
00491   int    s = Q_CONT;
00492 
00493   for (l = 0, p = *pp;
00494        s == Q_CONT && p < endptr; ) {
00495     switch (p[0]) {
00496     case C_QUOTE:
00497       s = Q_TERM; p++;
00498       break;
00499     case C_ESCAPE:
00500       if (q && l == len)
00501         s = Q_ERROR_BUFF;
00502       else {
00503         p++;
00504         l += read_c_escchar(q ? &q[l] : NULL, &p, endptr);
00505       }
00506       break;
00507     case '\n': case '\r':
00508       s = Q_ERROR_INVAL;
00509       break;
00510     default:
00511       if (q && l == len)
00512         s = Q_ERROR_BUFF;
00513       else {
00514         if (!q)
00515           l++;
00516         else
00517           q[l++] = p[0];
00518         p++;
00519       }
00520       break;
00521     }
00522   }
00523   if (s == Q_TERM) {
00524     if (q && l == len)
00525       s = Q_ERROR_BUFF;
00526     else if (q)
00527       q[l++] = '\0';
00528   }
00529 
00530   *pp = p;
00531   return ((s == Q_TERM) ? l : s);
00532 }
00533 
00534 char *
00535 parse_c_string (char **pp, char *endptr)
00536 {
00537   char  *q = NULL;
00538   char  *p = *pp;
00539   int    l = 0;
00540 
00541   if (p >= endptr || p[0] != C_QUOTE)
00542     return NULL;
00543 
00544   p++;
00545   l = read_c_litstrc(NULL, 0, &p, endptr);
00546   if (l >= 0) {
00547     q = NEW(l + 1, char);
00548     p = *pp + 1;
00549     l = read_c_litstrc(q, l + 1, &p, endptr);
00550   }
00551 
00552   *pp = p;
00553   return  q;
00554 }
00555 
00556 #define ISCNONDIGITS(c) ( \
00557   (c) == '_' || \
00558   ((c) >= 'a' && (c) <= 'z') || \
00559   ((c) >= 'A' && (c) <= 'Z') \
00560 )
00561 #define ISCIDENTCHAR(c) ( \
00562   ISCNONDIGITS((c)) || \
00563   ((c) >= '0' && (c) <= '9') \
00564 )
00565 
00566 char *
00567 parse_c_ident (char **pp, char *endptr)
00568 {
00569   char  *q = NULL;
00570   char  *p = *pp;
00571   int    n;
00572 
00573   if (p >= endptr || !ISCNONDIGITS(*p))
00574     return NULL;
00575 
00576   for (n = 0; p < endptr && ISCIDENTCHAR(*p); p++, n++);
00577   q = NEW(n + 1, char);
00578   memcpy(q, *pp, n); q[n] = '\0';
00579 
00580   *pp = p;
00581   return  q;
00582 }
00583 
00584 char *
00585 parse_float_decimal (char **pp, char *endptr)
00586 {
00587   char  *q = NULL;
00588   char  *p = *pp;
00589   int    s = 0, n = 0;
00590 
00591   if (p >= endptr)
00592     return NULL;
00593 
00594   if (p[0] == '+' || p[0] == '-')
00595     p++;
00596 
00597   /* 1. .01 001 001E-001 */
00598   for (s = 0, n = 0; p < endptr && s >= 0; ) {
00599     switch (p[0]) {
00600     case '+': case '-':
00601       if (s != 2)
00602         s = -1;
00603       else {
00604         s = 3; p++;
00605       }
00606       break;
00607     case '.':
00608       if (s > 0)
00609         s = -1;
00610       else {
00611         s =  1; p++;
00612       }
00613       break;
00614     case '0': case '1': case '2': case '3': case '4':
00615     case '5': case '6': case '7': case '8': case '9':
00616       n++; p++;
00617       break;
00618     case 'E': case 'e':
00619       if (n == 0 || s == 2)
00620         s = -1;
00621       else {
00622         s = 2; p++;
00623       }
00624       break;
00625     default:
00626       s = -1;
00627       break;
00628     }
00629   }
00630 
00631   if (n != 0) {
00632     n = (int) (p - *pp);
00633     q = NEW(n + 1, char);
00634     memcpy(q, *pp, n); q[n] = '\0';
00635   }
00636 
00637   *pp = p;
00638   return  q;
00639 }