Back to index

texmacs  1.0.7.15
pst_obj.c
Go to the documentation of this file.
00001 /*  $Header: /home/cvsroot/dvipdfmx/src/pst_obj.c,v 1.9 2008/11/30 21:12:27 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 <string.h>
00026 #include <stdlib.h>
00027 #include <errno.h>
00028 
00029 #include "system.h"
00030 #include "mem.h"
00031 #include "error.h"
00032 #include "dpxutil.h"
00033 #include "pst.h"
00034 #include "pst_obj.h"
00035 
00036 struct pst_obj
00037 {
00038   pst_type type;
00039   void    *data;
00040 };
00041 
00042 static const char *pst_const_null  = "null";
00043 static const char *pst_const_mark  = "mark";
00044 /*
00045 static const char *pst_const_true  = "true";
00046 static const char *pst_const_false = "false";
00047 */
00048 
00049 typedef char *                     pst_null;
00050 typedef struct { char    value; }  pst_boolean;
00051 typedef struct { long    value; }  pst_integer;
00052 typedef struct { double  value; }  pst_real;
00053 typedef struct { char   *value; }  pst_name;
00054 typedef struct
00055 {
00056   long    length;
00057   unsigned char *value;
00058 } pst_string;
00059 
00060 
00061 /* BOOLEAN */
00062 static pst_boolean *pst_boolean_new     (char value)      ;
00063 static void         pst_boolean_release (pst_boolean *obj);
00064 static long         pst_boolean_IV      (pst_boolean *obj);
00065 static double       pst_boolean_RV      (pst_boolean *obj);
00066 static unsigned char *pst_boolean_SV      (pst_boolean *obj);
00067 static long         pst_boolean_length  (pst_boolean *obj);
00068 static void        *pst_boolean_data_ptr(pst_boolean *obj);
00069 
00070 /* NUMBERS */
00071 static pst_integer *pst_integer_new     (long value)      ;
00072 static void         pst_integer_release (pst_integer *obj);
00073 static long         pst_integer_IV      (pst_integer *obj);
00074 static double       pst_integer_RV      (pst_integer *obj);
00075 static unsigned char      *pst_integer_SV      (pst_integer *obj);
00076 static unsigned int        pst_integer_length  (pst_integer *obj);
00077 static void        *pst_integer_data_ptr(pst_integer *obj);
00078 
00079 static pst_real *pst_real_new      (double value) ;
00080 static void      pst_real_release  (pst_real *obj);
00081 static long      pst_real_IV       (pst_real *obj);
00082 static double    pst_real_RV       (pst_real *obj);
00083 static unsigned char   *pst_real_SV       (pst_real *obj);
00084 static void     *pst_real_data_ptr (pst_real *obj);
00085 static unsigned int     pst_real_length   (pst_real *obj);
00086 
00087 /* NAME */
00088 static pst_name *pst_name_new      (const char *name) ;
00089 static void      pst_name_release  (pst_name *obj);
00090 static long      pst_name_IV       (pst_name *obj);
00091 static double    pst_name_RV       (pst_name *obj);
00092 static unsigned char   *pst_name_SV       (pst_name *obj);
00093 static void     *pst_name_data_ptr (pst_name *obj);
00094 static unsigned int     pst_name_length   (pst_name *obj);
00095 
00096 /* STRING */
00097 static pst_string *pst_string_parse_literal (unsigned char **inbuf, unsigned char *inbufend);
00098 static pst_string *pst_string_parse_hex     (unsigned char **inbuf, unsigned char *inbufend);
00099 
00100 static pst_string *pst_string_new      (unsigned char *str, unsigned int len);
00101 static void        pst_string_release  (pst_string *obj)       ;
00102 static long        pst_string_IV       (pst_string *obj)       ;
00103 static double      pst_string_RV       (pst_string *obj)       ;
00104 static unsigned char     *pst_string_SV       (pst_string *obj)       ;
00105 static void       *pst_string_data_ptr (pst_string *obj)       ;
00106 static unsigned int       pst_string_length   (pst_string *obj)       ;
00107 
00108 
00109 #define TYPE_ERROR() ERROR("Operation not defined for this type of object.")
00110 
00111 pst_obj *
00112 pst_new_obj (pst_type type, void *data)
00113 {
00114   pst_obj *obj;
00115 
00116   obj = NEW(1, struct pst_obj);
00117   obj->type = type;
00118   obj->data = data;
00119 
00120   return obj;
00121 }
00122 
00123 pst_obj *
00124 pst_new_mark (void)
00125 {
00126   return pst_new_obj(PST_TYPE_MARK, (void *)pst_const_mark);
00127 }
00128 
00129 void
00130 pst_release_obj (pst_obj *obj)
00131 {
00132   ASSERT(obj);
00133   switch (obj->type) {
00134   case PST_TYPE_BOOLEAN: pst_boolean_release(obj->data); break;
00135   case PST_TYPE_INTEGER: pst_integer_release(obj->data); break;
00136   case PST_TYPE_REAL:    pst_real_release(obj->data);    break;
00137   case PST_TYPE_NAME:    pst_name_release(obj->data);    break;
00138   case PST_TYPE_STRING:  pst_string_release(obj->data);  break;
00139   case PST_TYPE_NULL:
00140   case PST_TYPE_MARK:
00141     break;
00142   case PST_TYPE_UNKNOWN:
00143     if (obj->data)
00144       RELEASE(obj->data);
00145     break;
00146   default:
00147     ERROR("Unrecognized object type: %d", obj->type);
00148   }
00149   RELEASE(obj);
00150 }
00151 
00152 pst_type
00153 pst_type_of (pst_obj *obj)
00154 {
00155   ASSERT(obj);
00156   return obj->type;
00157 }
00158 
00159 long
00160 pst_length_of (pst_obj *obj)
00161 {
00162   long len = 0;
00163 
00164   ASSERT(obj);
00165   switch (obj->type) {
00166   case PST_TYPE_BOOLEAN: len = pst_boolean_length(obj->data); break;
00167   case PST_TYPE_INTEGER: len = pst_integer_length(obj->data); break;
00168   case PST_TYPE_REAL:    len = pst_real_length(obj->data);    break;
00169   case PST_TYPE_NAME:    len = pst_name_length(obj->data);    break;
00170   case PST_TYPE_STRING:  len = pst_string_length(obj->data);  break;
00171   case PST_TYPE_NULL:
00172   case PST_TYPE_MARK:
00173     TYPE_ERROR();                     
00174     break;
00175   case PST_TYPE_UNKNOWN:
00176     len = strlen(obj->data);
00177     break;
00178   default:
00179     ERROR("Unrecognized object type: %d", obj->type);
00180   }
00181 
00182   return len;
00183 }
00184 
00185 long
00186 pst_getIV (pst_obj *obj)
00187 {
00188   long iv = 0;
00189 
00190   ASSERT(obj);
00191   switch (obj->type) {
00192   case PST_TYPE_BOOLEAN: iv = pst_boolean_IV(obj->data); break;
00193   case PST_TYPE_INTEGER: iv = pst_integer_IV(obj->data); break;
00194   case PST_TYPE_REAL:    iv = pst_real_IV(obj->data);    break;
00195   case PST_TYPE_NAME:    iv = pst_name_IV(obj->data);    break;
00196   case PST_TYPE_STRING:  iv = pst_string_IV(obj->data);  break;
00197   case PST_TYPE_NULL:
00198   case PST_TYPE_MARK: 
00199     TYPE_ERROR(); 
00200     break;
00201   case PST_TYPE_UNKNOWN:
00202     ERROR("Cannot convert object of type UNKNOWN to integer value.");
00203     break;
00204   default:
00205     ERROR("Unrecognized object type: %d", obj->type);
00206   }
00207 
00208   return iv;
00209 }
00210 
00211 double
00212 pst_getRV (pst_obj *obj)
00213 {
00214   double rv = 0.0;
00215 
00216   ASSERT(obj);
00217   switch (obj->type) {
00218   case PST_TYPE_BOOLEAN: rv = pst_boolean_RV(obj->data); break;
00219   case PST_TYPE_INTEGER: rv = pst_integer_RV(obj->data); break;
00220   case PST_TYPE_REAL:    rv = pst_real_RV(obj->data);    break;
00221   case PST_TYPE_NAME:    rv = pst_name_RV(obj->data);    break;
00222   case PST_TYPE_STRING:  rv = pst_string_RV(obj->data);  break;
00223   case PST_TYPE_NULL:
00224   case PST_TYPE_MARK:
00225     TYPE_ERROR();                  
00226     break;
00227   case PST_TYPE_UNKNOWN:
00228     ERROR("Cannot convert object of type UNKNOWN to real value.");
00229     break;
00230   default:
00231     ERROR("Unrecognized object type: %d", obj->type);
00232   }
00233 
00234   return rv;
00235 }
00236 
00237 /* Length can be obtained by pst_length_of(). */
00238 unsigned char *
00239 pst_getSV (pst_obj *obj)
00240 {
00241   unsigned char *sv = NULL;
00242 
00243   ASSERT(obj);
00244   switch (obj->type) {
00245   case PST_TYPE_BOOLEAN: sv = pst_boolean_SV(obj->data); break;
00246   case PST_TYPE_INTEGER: sv = pst_integer_SV(obj->data); break;
00247   case PST_TYPE_REAL:    sv = pst_real_SV(obj->data);    break;
00248   case PST_TYPE_NAME:    sv = pst_name_SV(obj->data);    break;
00249   case PST_TYPE_STRING:  sv = pst_string_SV(obj->data);  break;
00250   case PST_TYPE_NULL:
00251   case PST_TYPE_MARK:
00252     TYPE_ERROR(); 
00253     break;
00254   case PST_TYPE_UNKNOWN:
00255     {
00256       long len;
00257 
00258       len = strlen((char *) obj->data);
00259       if (len > 0) {
00260        sv = NEW(len+1, unsigned char);
00261        memcpy(sv, obj->data, len);
00262        sv[len] = '\0';
00263       } else {
00264        sv = NULL;
00265       }
00266       break;
00267     }
00268   default:
00269     ERROR("Unrecognized object type: %d", obj->type);
00270   }
00271 
00272   return sv;
00273 }
00274 
00275 void *
00276 pst_data_ptr (pst_obj *obj)
00277 {
00278   char *p = NULL;
00279 
00280   ASSERT(obj);
00281   switch (obj->type) {
00282   case PST_TYPE_BOOLEAN: p = pst_boolean_data_ptr(obj->data); break;
00283   case PST_TYPE_INTEGER: p = pst_integer_data_ptr(obj->data); break;
00284   case PST_TYPE_REAL:    p = pst_real_data_ptr(obj->data);    break;
00285   case PST_TYPE_NAME:    p = pst_name_data_ptr(obj->data);    break;
00286   case PST_TYPE_STRING:  p = pst_string_data_ptr(obj->data);  break;
00287   case PST_TYPE_NULL:
00288   case PST_TYPE_MARK: 
00289     TYPE_ERROR();
00290     break;
00291   case PST_TYPE_UNKNOWN:
00292     p = obj->data;
00293     break;
00294   default:
00295     ERROR("Unrecognized object type: %d", obj->type);
00296   }
00297 
00298   return (void *)p;
00299 }
00300 
00301 /* BOOLEAN */
00302 static pst_boolean *
00303 pst_boolean_new (char value)
00304 {
00305   pst_boolean *obj;
00306   obj = NEW(1, pst_boolean);
00307   obj->value = value;
00308   return obj;
00309 }
00310 
00311 static void
00312 pst_boolean_release (pst_boolean *obj)
00313 {
00314   ASSERT(obj);
00315   RELEASE(obj);
00316 }
00317 
00318 static long
00319 pst_boolean_IV (pst_boolean *obj)
00320 {
00321   ASSERT(obj);
00322   return (long) obj->value;
00323 }
00324 
00325 static double
00326 pst_boolean_RV (pst_boolean *obj)
00327 {
00328   ASSERT(obj);
00329   return (double) obj->value;
00330 }
00331 
00332 static unsigned char *
00333 pst_boolean_SV (pst_boolean *obj)
00334 {
00335   unsigned char *str;
00336 
00337   ASSERT(obj);
00338 
00339   if (obj->value) {
00340     str = NEW(5, unsigned char);
00341     memcpy(str, "true", 4);
00342     str[4] = '\0';
00343   } else {
00344     str = NEW(6, unsigned char);
00345     memcpy(str, "false", 5);
00346     str[5] = '\0';
00347   }
00348 
00349   return str;
00350 }
00351 
00352 static long
00353 pst_boolean_length (pst_boolean *obj)
00354 {
00355   TYPE_ERROR();
00356   return 0;
00357 }
00358 
00359 static void *
00360 pst_boolean_data_ptr (pst_boolean *obj)
00361 {
00362   ASSERT(obj);
00363   return (void*) &(obj->value);
00364 }
00365 
00366 pst_obj *
00367 pst_parse_boolean (unsigned char **inbuf, unsigned char *inbufend)
00368 {
00369   if (*inbuf + 4 <= inbufend &&
00370       memcmp(*inbuf, "true", 4) == 0 &&
00371       PST_TOKEN_END(*inbuf + 4, inbufend)) {
00372     *inbuf += 4;
00373     return pst_new_obj(PST_TYPE_BOOLEAN, pst_boolean_new(1));
00374   } else if (*inbuf + 5 <= inbufend &&
00375             memcmp(*inbuf, "false", 5) == 0 &&
00376             PST_TOKEN_END(*inbuf + 5, inbufend)) {
00377     *inbuf += 5;
00378     return pst_new_obj(PST_TYPE_BOOLEAN, pst_boolean_new(0));
00379   } else
00380     return NULL;
00381 }
00382 
00383 
00384 /* NULL */
00385 pst_obj *
00386 pst_parse_null (unsigned char **inbuf, unsigned char *inbufend)
00387 {
00388   if (*inbuf + 4 <= inbufend &&
00389       memcmp(*inbuf, "null", 4) == 0 &&
00390       PST_TOKEN_END(*inbuf+4, inbufend)) {
00391     *inbuf += 4;
00392     return pst_new_obj(PST_TYPE_NULL, (void*)pst_const_null);
00393   } else
00394     return NULL;
00395 }
00396 
00397 /* INTEGER */
00398 static pst_integer *
00399 pst_integer_new (long value)
00400 {
00401   pst_integer *obj;
00402   obj = NEW(1, pst_integer);
00403   obj->value = value;
00404   return obj;
00405 }
00406 
00407 static void
00408 pst_integer_release (pst_integer *obj)
00409 {
00410   ASSERT(obj);
00411   RELEASE(obj);
00412 }
00413 
00414 static long
00415 pst_integer_IV (pst_integer *obj)
00416 {
00417   ASSERT(obj);
00418   return (long) obj->value;
00419 }
00420 
00421 static double
00422 pst_integer_RV (pst_integer *obj)
00423 {
00424   ASSERT(obj);
00425   return (double) obj->value;
00426 }
00427 
00428 static unsigned char *
00429 pst_integer_SV (pst_integer *obj)
00430 {
00431   char *value;
00432   int   len;
00433   char  fmt_buf[PST_MAX_DIGITS+5];
00434 
00435   ASSERT(obj);
00436 
00437   len = sprintf(fmt_buf, "%ld", obj->value);
00438 
00439   value = NEW(len, char);
00440   strcpy(value, fmt_buf);
00441 
00442   return (unsigned char *) value;
00443 }
00444 
00445 static void *
00446 pst_integer_data_ptr (pst_integer *obj)
00447 {
00448   ASSERT(obj);
00449   return (void*) &(obj->value);
00450 }
00451 
00452 static unsigned int
00453 pst_integer_length (pst_integer *obj)
00454 {
00455   TYPE_ERROR();
00456   return 0;
00457 }
00458 
00459 /* REAL */
00460 static pst_real *
00461 pst_real_new (double value)
00462 {
00463   pst_real *obj;
00464 
00465   obj = NEW(1, pst_real);
00466   obj->value = value;
00467 
00468   return obj;
00469 }
00470 
00471 static void
00472 pst_real_release (pst_real *obj)
00473 {
00474   ASSERT(obj);
00475   RELEASE(obj);
00476 }
00477 
00478 static long
00479 pst_real_IV (pst_real *obj)
00480 {
00481   ASSERT(obj);
00482   return (long) obj->value;
00483 }
00484 
00485 static double
00486 pst_real_RV (pst_real *obj)
00487 {
00488   ASSERT(obj);
00489   return (double) obj->value;
00490 }
00491 
00492 static unsigned char *
00493 pst_real_SV (pst_real *obj)
00494 {
00495   char *value;
00496   int   len;
00497   char  fmt_buf[PST_MAX_DIGITS+5];
00498 
00499   ASSERT(obj);
00500 
00501   len = sprintf(fmt_buf, "%.5g", obj->value);
00502 
00503   value = NEW(len, char);
00504   strcpy(value, fmt_buf);
00505 
00506   return (unsigned char *) value;
00507 }
00508 
00509 static void *
00510 pst_real_data_ptr (pst_real *obj)
00511 {
00512   ASSERT(obj);
00513 
00514   return (void*) &(obj->value);
00515 }
00516 
00517 static unsigned int
00518 pst_real_length (pst_real *obj)
00519 {
00520   TYPE_ERROR();
00521   return 0;
00522 }
00523 
00524 /* NOTE: the input buffer must be null-terminated, i.e., *inbufend == 0 */
00525 /* leading white-space is ignored */
00526 pst_obj *
00527 pst_parse_number (unsigned char **inbuf, unsigned char *inbufend)
00528 {
00529   unsigned char  *cur;
00530   long    lval;
00531   double  dval;
00532 
00533   errno = 0;
00534   lval = strtol((char *) *inbuf, (char **) (void *) &cur, 10);
00535   if (errno || *cur == '.' || *cur == 'e' || *cur == 'E') {
00536     /* real */
00537     errno = 0;
00538     dval = strtod((char *) *inbuf, (char **) (void *) &cur);
00539     if (!errno && PST_TOKEN_END(cur, inbufend)) {
00540       *inbuf = cur;
00541       return pst_new_obj(PST_TYPE_REAL, pst_real_new(dval));
00542     }
00543   } else if (cur != *inbuf && PST_TOKEN_END(cur, inbufend)) {
00544     /* integer */
00545     *inbuf = cur;
00546     return pst_new_obj(PST_TYPE_INTEGER, pst_integer_new(lval));
00547   } else if (lval >= 2 && lval <= 36 && *cur == '#' && isalnum(*++cur) &&
00548             /* strtod allows leading "0x" for hex numbers, but we don't */
00549             (lval != 16 || (cur[1] != 'x' && cur[1] != 'X'))) {
00550     /* integer with radix */
00551     /* Can the base have a (plus) sign? I think yes. */
00552     errno = 0;
00553     lval = strtol((char *) cur, (char **) (void *) &cur, lval);
00554     if (!errno && PST_TOKEN_END(cur, inbufend)) {
00555       *inbuf = cur;
00556       return pst_new_obj(PST_TYPE_INTEGER, pst_integer_new(lval));
00557     }
00558   }
00559   /* error */
00560   return NULL;
00561 }
00562 
00563 /* NAME */
00564 
00565 /*
00566  * \0 is not allowed for name object.
00567  */
00568 
00569 static pst_name *
00570 pst_name_new (const char *name)
00571 {
00572   pst_name *obj;
00573 
00574   obj = NEW(1, pst_name);
00575   obj->value = NEW(strlen(name)+1, char);
00576   strcpy(obj->value, name);
00577 
00578   return obj;
00579 }
00580 
00581 static void
00582 pst_name_release (pst_name *obj)
00583 {
00584   ASSERT(obj);
00585   if (obj->value)
00586     RELEASE(obj->value);
00587   RELEASE(obj);
00588 }
00589 
00590 #if 0
00591 int
00592 pst_name_is_valid (const char *name)
00593 {
00594   static const char *valid_chars =
00595     "!\"#$&'*+,-.0123456789:;=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\\^_`abcdefghijklmnopqrstuvwxyz|~";
00596   if (strspn(name, valid_chars) == strlen(name))
00597     return 1;
00598   else
00599     return 0;
00600 }
00601 
00602 char *
00603 pst_name_encode (const char *name)
00604 {
00605   char *encoded_name, *p;
00606   int   i, len;
00607   char  c;
00608 
00609   len = strlen(name);
00610   if (len > PST_NAME_LEN_MAX) {
00611     WARN("Input string too long for name object. String will be truncated.");
00612     len = PST_NAME_LEN_MAX;
00613   }
00614 
00615   p = encoded_name = NEW(3*len+1, char);
00616   for (i = 0; i < len; i++) {
00617     c = name[i];
00618     if (c < '!'  || c > '~' ||
00619        c == '#' || is_delim(c) || is_space(c)) {
00620       *p++ = '#';
00621       putxpair(c, &p);
00622     } else {
00623       *p++ = c;
00624     }
00625   }
00626   *p = '\0';
00627 
00628   return encoded_name;
00629 }
00630 #endif
00631 
00632 pst_obj *
00633 pst_parse_name (unsigned char **inbuf, unsigned char *inbufend) /* / is required */
00634 {
00635   unsigned char  wbuf[PST_NAME_LEN_MAX+1];
00636   unsigned char  c, *p = wbuf, *cur = *inbuf;
00637   int     len = 0;
00638 
00639   if (*cur != '/')
00640     return NULL;
00641   cur++;
00642 
00643   while (!PST_TOKEN_END(cur, inbufend)) {
00644     c = *cur++;
00645     if (c == '#') {
00646       int val;
00647       if (cur + 2 >= inbufend) {
00648        WARN("Premature end of input name string.");
00649        break;
00650       }
00651       val = getxpair(&cur);
00652       if (val <= 0) {
00653        WARN("Invalid char for name object. (ignored)");
00654        continue;
00655       } else
00656        c = (unsigned char) val;
00657     }
00658     if (len < PST_NAME_LEN_MAX)
00659       *p++ = c;
00660     len++;
00661   }
00662   *p = '\0';
00663 
00664   if (len > PST_NAME_LEN_MAX)
00665     WARN("String too long for name object. Output will be truncated.");
00666 
00667   *inbuf = cur;
00668   return pst_new_obj(PST_TYPE_NAME, pst_name_new((char *)wbuf));
00669 }
00670 
00671 static long
00672 pst_name_IV (pst_name *obj)
00673 {
00674   TYPE_ERROR();
00675   return 0;
00676 }
00677 
00678 static double
00679 pst_name_RV (pst_name *obj)
00680 {
00681   TYPE_ERROR();
00682   return 0;
00683 }
00684 
00685 static unsigned char *
00686 pst_name_SV (pst_name *obj)
00687 {
00688   char *value;
00689 
00690   value = NEW(strlen(obj->value)+1, char);
00691   strcpy(value, obj->value);
00692 
00693   return (unsigned char *) value;
00694 }
00695 
00696 static void *
00697 pst_name_data_ptr (pst_name *obj)
00698 {
00699   ASSERT(obj);
00700   return obj->value;
00701 }
00702 
00703 static unsigned int
00704 pst_name_length (pst_name *obj)
00705 {
00706   ASSERT(obj);
00707   return strlen(obj->value);
00708 }
00709 
00710 
00711 /* STRING */
00712 
00713 /*
00714  * TODO: ascii85 string <~ .... ~>
00715  */
00716 static pst_string *
00717 pst_string_new (unsigned char *str, unsigned int len)
00718 {
00719   pst_string *obj;
00720   obj = NEW(1, pst_string);
00721   obj->length  = len;
00722   obj->value = NULL;
00723   if (len > 0) {
00724     obj->value = NEW(len, unsigned char);
00725     if (str)
00726       memcpy(obj->value, str, len);
00727   }
00728   return obj;
00729 }
00730 
00731 static void
00732 pst_string_release (pst_string *obj)
00733 {
00734   ASSERT(obj);
00735   if (obj->value)
00736     RELEASE(obj->value);
00737   RELEASE(obj);
00738 }
00739 
00740 pst_obj *
00741 pst_parse_string (unsigned char **inbuf, unsigned char *inbufend)
00742 {
00743   if (*inbuf + 2 >= inbufend) {
00744     return NULL;
00745   } else if (**inbuf == '(')
00746     return pst_new_obj(PST_TYPE_STRING, pst_string_parse_literal(inbuf, inbufend));
00747   else if (**inbuf == '<' && *(*inbuf+1) == '~')
00748     ERROR("ASCII85 string not supported yet.");
00749   else if (**inbuf == '<')
00750     return pst_new_obj(PST_TYPE_STRING, pst_string_parse_hex(inbuf, inbufend));
00751   return NULL;
00752 }
00753 
00754 static pst_string *
00755 pst_string_parse_literal (unsigned char **inbuf, unsigned char *inbufend)
00756 {
00757   unsigned char  wbuf[PST_STRING_LEN_MAX];
00758   unsigned char *cur = *inbuf, c = 0;
00759   long    len = 0, balance = 1;
00760 
00761   if (cur + 2 > inbufend || *cur != '(')
00762     return NULL;
00763 
00764   cur++;
00765   while (cur < inbufend && len < PST_STRING_LEN_MAX && balance > 0) {
00766     c = *(cur++);
00767     switch (c) {
00768     case '\\':
00769       {
00770        unsigned char unescaped, valid;
00771        unescaped = esctouc(&cur, inbufend, &valid);
00772        if (valid)
00773          wbuf[len++] = unescaped;
00774       }
00775       break;
00776     case '(':
00777       balance++;
00778       wbuf[len++] = '(';
00779       break;
00780     case ')':
00781       balance--;
00782       if (balance > 0)
00783        wbuf[len++] = ')';
00784       break;
00785       /*
00786        * An end-of-line marker (\n, \r or \r\n), not preceeded by a backslash,
00787        * must be converted to single \n.
00788        */
00789     case '\r':
00790       if (cur < inbufend && *cur == '\n')
00791        cur++;
00792       wbuf[len++] = '\n';
00793       break;
00794     default:
00795       wbuf[len++] = c;
00796     }
00797   }
00798   if (c != ')')
00799     return NULL;
00800 
00801   *inbuf  = cur;
00802   return pst_string_new(wbuf, len);
00803 }
00804 
00805 static pst_string *
00806 pst_string_parse_hex (unsigned char **inbuf, unsigned char *inbufend)
00807 {
00808   unsigned char  wbuf[PST_STRING_LEN_MAX];
00809   unsigned char *cur = *inbuf;
00810   unsigned long  len = 0;
00811 
00812   if (cur + 2 > inbufend || *cur != '<' ||
00813       (*cur == '<' && *(cur+1) == '<'))
00814     return NULL;
00815 
00816   cur++;
00817   /* PDF Reference does not specify how to treat invalid char */  
00818   while (cur < inbufend && len < PST_STRING_LEN_MAX) {
00819     int    hi, lo;
00820     skip_white_spaces(&cur, inbufend);
00821     if (*cur == '>')
00822       break;
00823     hi = xtoi(*(cur++));
00824     if (hi < 0) {
00825       WARN("Invalid char for hex string <%x> treated as <0>.", *(cur-1));
00826       hi = 0;
00827     }
00828     skip_white_spaces(&cur, inbufend);
00829     if (*cur == '>')
00830       break;
00831     /* 0 is appended if final hex digit is missing */
00832     lo = (cur < inbufend) ? xtoi(*(cur++)) : 0;
00833     if (lo < 0) {
00834       WARN("Invalid char for hex string <%x> treated as <0>.", *(cur-1));
00835       lo = 0;
00836     }
00837     wbuf[len++] = (hi << 4) | lo;
00838   }
00839   if (*cur++ != '>')
00840     return NULL;
00841 
00842   *inbuf = cur;
00843   return pst_string_new(wbuf, len);
00844 }
00845 
00846 static long
00847 pst_string_IV (pst_string *obj)
00848 {
00849   return (long) pst_string_RV(obj);
00850 }
00851 
00852 static double
00853 pst_string_RV (pst_string *obj)
00854 {
00855   pst_obj *nobj;
00856   unsigned char  *p, *end;
00857   double   rv;
00858 
00859   ASSERT(obj);
00860   p   = obj->value;
00861   end = p + obj->length;
00862   nobj = pst_parse_number(&p, end);
00863   if (nobj == NULL || p != end)
00864     ERROR("Cound not convert string to real value.");
00865   rv = pst_getRV(nobj);
00866   pst_release_obj(nobj);
00867 
00868   return rv;
00869 }
00870 
00871 static unsigned char *
00872 pst_string_SV (pst_string *obj)
00873 {
00874   unsigned char *str = NULL;
00875   ASSERT(obj);
00876   str = NEW(obj->length + 1, unsigned char);
00877   memcpy(str, obj->value, obj->length);
00878   str[obj->length] = '\0';
00879   return str;
00880 }
00881 
00882 static void *
00883 pst_string_data_ptr (pst_string *obj)
00884 {
00885   ASSERT(obj);
00886   return obj->value;
00887 }
00888 
00889 static unsigned int
00890 pst_string_length (pst_string *obj)
00891 {
00892   ASSERT(obj);
00893   return obj->length;
00894 }