/TeXmacs-1.0.7.11-src/src/Plugins/Pdf/dvipdfmx/pst_obj.c
C | 894 lines | 717 code | 119 blank | 58 comment | 113 complexity | 9d31d0a017f203e577c40597ef682328 MD5 | raw file
Possible License(s): GPL-3.0, GPL-2.0, MPL-2.0-no-copyleft-exception
1/* $Header: /home/cvsroot/dvipdfmx/src/pst_obj.c,v 1.9 2008/11/30 21:12:27 matthias Exp $
2
3 This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
4
5 Copyright (C) 2002 by Jin-Hwan Cho and Shunsaku Hirata,
6 the dvipdfmx project team <dvipdfmx@project.ktug.or.kr>
7
8 Copyright (C) 1998, 1999 by Mark A. Wicks <mwicks@kettering.edu>
9
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.
14
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.
19
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.
23*/
24
25#include <string.h>
26#include <stdlib.h>
27#include <errno.h>
28
29#include "system.h"
30#include "mem.h"
31#include "error.h"
32#include "dpxutil.h"
33#include "pst.h"
34#include "pst_obj.h"
35
36struct pst_obj
37{
38 pst_type type;
39 void *data;
40};
41
42static const char *pst_const_null = "null";
43static const char *pst_const_mark = "mark";
44/*
45static const char *pst_const_true = "true";
46static const char *pst_const_false = "false";
47*/
48
49typedef char * pst_null;
50typedef struct { char value; } pst_boolean;
51typedef struct { long value; } pst_integer;
52typedef struct { double value; } pst_real;
53typedef struct { char *value; } pst_name;
54typedef struct
55{
56 long length;
57 unsigned char *value;
58} pst_string;
59
60
61/* BOOLEAN */
62static pst_boolean *pst_boolean_new (char value) ;
63static void pst_boolean_release (pst_boolean *obj);
64static long pst_boolean_IV (pst_boolean *obj);
65static double pst_boolean_RV (pst_boolean *obj);
66static unsigned char *pst_boolean_SV (pst_boolean *obj);
67static long pst_boolean_length (pst_boolean *obj);
68static void *pst_boolean_data_ptr(pst_boolean *obj);
69
70/* NUMBERS */
71static pst_integer *pst_integer_new (long value) ;
72static void pst_integer_release (pst_integer *obj);
73static long pst_integer_IV (pst_integer *obj);
74static double pst_integer_RV (pst_integer *obj);
75static unsigned char *pst_integer_SV (pst_integer *obj);
76static unsigned int pst_integer_length (pst_integer *obj);
77static void *pst_integer_data_ptr(pst_integer *obj);
78
79static pst_real *pst_real_new (double value) ;
80static void pst_real_release (pst_real *obj);
81static long pst_real_IV (pst_real *obj);
82static double pst_real_RV (pst_real *obj);
83static unsigned char *pst_real_SV (pst_real *obj);
84static void *pst_real_data_ptr (pst_real *obj);
85static unsigned int pst_real_length (pst_real *obj);
86
87/* NAME */
88static pst_name *pst_name_new (const char *name) ;
89static void pst_name_release (pst_name *obj);
90static long pst_name_IV (pst_name *obj);
91static double pst_name_RV (pst_name *obj);
92static unsigned char *pst_name_SV (pst_name *obj);
93static void *pst_name_data_ptr (pst_name *obj);
94static unsigned int pst_name_length (pst_name *obj);
95
96/* STRING */
97static pst_string *pst_string_parse_literal (unsigned char **inbuf, unsigned char *inbufend);
98static pst_string *pst_string_parse_hex (unsigned char **inbuf, unsigned char *inbufend);
99
100static pst_string *pst_string_new (unsigned char *str, unsigned int len);
101static void pst_string_release (pst_string *obj) ;
102static long pst_string_IV (pst_string *obj) ;
103static double pst_string_RV (pst_string *obj) ;
104static unsigned char *pst_string_SV (pst_string *obj) ;
105static void *pst_string_data_ptr (pst_string *obj) ;
106static unsigned int pst_string_length (pst_string *obj) ;
107
108
109#define TYPE_ERROR() ERROR("Operation not defined for this type of object.")
110
111pst_obj *
112pst_new_obj (pst_type type, void *data)
113{
114 pst_obj *obj;
115
116 obj = NEW(1, struct pst_obj);
117 obj->type = type;
118 obj->data = data;
119
120 return obj;
121}
122
123pst_obj *
124pst_new_mark (void)
125{
126 return pst_new_obj(PST_TYPE_MARK, (void *)pst_const_mark);
127}
128
129void
130pst_release_obj (pst_obj *obj)
131{
132 ASSERT(obj);
133 switch (obj->type) {
134 case PST_TYPE_BOOLEAN: pst_boolean_release(obj->data); break;
135 case PST_TYPE_INTEGER: pst_integer_release(obj->data); break;
136 case PST_TYPE_REAL: pst_real_release(obj->data); break;
137 case PST_TYPE_NAME: pst_name_release(obj->data); break;
138 case PST_TYPE_STRING: pst_string_release(obj->data); break;
139 case PST_TYPE_NULL:
140 case PST_TYPE_MARK:
141 break;
142 case PST_TYPE_UNKNOWN:
143 if (obj->data)
144 RELEASE(obj->data);
145 break;
146 default:
147 ERROR("Unrecognized object type: %d", obj->type);
148 }
149 RELEASE(obj);
150}
151
152pst_type
153pst_type_of (pst_obj *obj)
154{
155 ASSERT(obj);
156 return obj->type;
157}
158
159long
160pst_length_of (pst_obj *obj)
161{
162 long len = 0;
163
164 ASSERT(obj);
165 switch (obj->type) {
166 case PST_TYPE_BOOLEAN: len = pst_boolean_length(obj->data); break;
167 case PST_TYPE_INTEGER: len = pst_integer_length(obj->data); break;
168 case PST_TYPE_REAL: len = pst_real_length(obj->data); break;
169 case PST_TYPE_NAME: len = pst_name_length(obj->data); break;
170 case PST_TYPE_STRING: len = pst_string_length(obj->data); break;
171 case PST_TYPE_NULL:
172 case PST_TYPE_MARK:
173 TYPE_ERROR();
174 break;
175 case PST_TYPE_UNKNOWN:
176 len = strlen(obj->data);
177 break;
178 default:
179 ERROR("Unrecognized object type: %d", obj->type);
180 }
181
182 return len;
183}
184
185long
186pst_getIV (pst_obj *obj)
187{
188 long iv = 0;
189
190 ASSERT(obj);
191 switch (obj->type) {
192 case PST_TYPE_BOOLEAN: iv = pst_boolean_IV(obj->data); break;
193 case PST_TYPE_INTEGER: iv = pst_integer_IV(obj->data); break;
194 case PST_TYPE_REAL: iv = pst_real_IV(obj->data); break;
195 case PST_TYPE_NAME: iv = pst_name_IV(obj->data); break;
196 case PST_TYPE_STRING: iv = pst_string_IV(obj->data); break;
197 case PST_TYPE_NULL:
198 case PST_TYPE_MARK:
199 TYPE_ERROR();
200 break;
201 case PST_TYPE_UNKNOWN:
202 ERROR("Cannot convert object of type UNKNOWN to integer value.");
203 break;
204 default:
205 ERROR("Unrecognized object type: %d", obj->type);
206 }
207
208 return iv;
209}
210
211double
212pst_getRV (pst_obj *obj)
213{
214 double rv = 0.0;
215
216 ASSERT(obj);
217 switch (obj->type) {
218 case PST_TYPE_BOOLEAN: rv = pst_boolean_RV(obj->data); break;
219 case PST_TYPE_INTEGER: rv = pst_integer_RV(obj->data); break;
220 case PST_TYPE_REAL: rv = pst_real_RV(obj->data); break;
221 case PST_TYPE_NAME: rv = pst_name_RV(obj->data); break;
222 case PST_TYPE_STRING: rv = pst_string_RV(obj->data); break;
223 case PST_TYPE_NULL:
224 case PST_TYPE_MARK:
225 TYPE_ERROR();
226 break;
227 case PST_TYPE_UNKNOWN:
228 ERROR("Cannot convert object of type UNKNOWN to real value.");
229 break;
230 default:
231 ERROR("Unrecognized object type: %d", obj->type);
232 }
233
234 return rv;
235}
236
237/* Length can be obtained by pst_length_of(). */
238unsigned char *
239pst_getSV (pst_obj *obj)
240{
241 unsigned char *sv = NULL;
242
243 ASSERT(obj);
244 switch (obj->type) {
245 case PST_TYPE_BOOLEAN: sv = pst_boolean_SV(obj->data); break;
246 case PST_TYPE_INTEGER: sv = pst_integer_SV(obj->data); break;
247 case PST_TYPE_REAL: sv = pst_real_SV(obj->data); break;
248 case PST_TYPE_NAME: sv = pst_name_SV(obj->data); break;
249 case PST_TYPE_STRING: sv = pst_string_SV(obj->data); break;
250 case PST_TYPE_NULL:
251 case PST_TYPE_MARK:
252 TYPE_ERROR();
253 break;
254 case PST_TYPE_UNKNOWN:
255 {
256 long len;
257
258 len = strlen((char *) obj->data);
259 if (len > 0) {
260 sv = NEW(len+1, unsigned char);
261 memcpy(sv, obj->data, len);
262 sv[len] = '\0';
263 } else {
264 sv = NULL;
265 }
266 break;
267 }
268 default:
269 ERROR("Unrecognized object type: %d", obj->type);
270 }
271
272 return sv;
273}
274
275void *
276pst_data_ptr (pst_obj *obj)
277{
278 char *p = NULL;
279
280 ASSERT(obj);
281 switch (obj->type) {
282 case PST_TYPE_BOOLEAN: p = pst_boolean_data_ptr(obj->data); break;
283 case PST_TYPE_INTEGER: p = pst_integer_data_ptr(obj->data); break;
284 case PST_TYPE_REAL: p = pst_real_data_ptr(obj->data); break;
285 case PST_TYPE_NAME: p = pst_name_data_ptr(obj->data); break;
286 case PST_TYPE_STRING: p = pst_string_data_ptr(obj->data); break;
287 case PST_TYPE_NULL:
288 case PST_TYPE_MARK:
289 TYPE_ERROR();
290 break;
291 case PST_TYPE_UNKNOWN:
292 p = obj->data;
293 break;
294 default:
295 ERROR("Unrecognized object type: %d", obj->type);
296 }
297
298 return (void *)p;
299}
300
301/* BOOLEAN */
302static pst_boolean *
303pst_boolean_new (char value)
304{
305 pst_boolean *obj;
306 obj = NEW(1, pst_boolean);
307 obj->value = value;
308 return obj;
309}
310
311static void
312pst_boolean_release (pst_boolean *obj)
313{
314 ASSERT(obj);
315 RELEASE(obj);
316}
317
318static long
319pst_boolean_IV (pst_boolean *obj)
320{
321 ASSERT(obj);
322 return (long) obj->value;
323}
324
325static double
326pst_boolean_RV (pst_boolean *obj)
327{
328 ASSERT(obj);
329 return (double) obj->value;
330}
331
332static unsigned char *
333pst_boolean_SV (pst_boolean *obj)
334{
335 unsigned char *str;
336
337 ASSERT(obj);
338
339 if (obj->value) {
340 str = NEW(5, unsigned char);
341 memcpy(str, "true", 4);
342 str[4] = '\0';
343 } else {
344 str = NEW(6, unsigned char);
345 memcpy(str, "false", 5);
346 str[5] = '\0';
347 }
348
349 return str;
350}
351
352static long
353pst_boolean_length (pst_boolean *obj)
354{
355 TYPE_ERROR();
356 return 0;
357}
358
359static void *
360pst_boolean_data_ptr (pst_boolean *obj)
361{
362 ASSERT(obj);
363 return (void*) &(obj->value);
364}
365
366pst_obj *
367pst_parse_boolean (unsigned char **inbuf, unsigned char *inbufend)
368{
369 if (*inbuf + 4 <= inbufend &&
370 memcmp(*inbuf, "true", 4) == 0 &&
371 PST_TOKEN_END(*inbuf + 4, inbufend)) {
372 *inbuf += 4;
373 return pst_new_obj(PST_TYPE_BOOLEAN, pst_boolean_new(1));
374 } else if (*inbuf + 5 <= inbufend &&
375 memcmp(*inbuf, "false", 5) == 0 &&
376 PST_TOKEN_END(*inbuf + 5, inbufend)) {
377 *inbuf += 5;
378 return pst_new_obj(PST_TYPE_BOOLEAN, pst_boolean_new(0));
379 } else
380 return NULL;
381}
382
383
384/* NULL */
385pst_obj *
386pst_parse_null (unsigned char **inbuf, unsigned char *inbufend)
387{
388 if (*inbuf + 4 <= inbufend &&
389 memcmp(*inbuf, "null", 4) == 0 &&
390 PST_TOKEN_END(*inbuf+4, inbufend)) {
391 *inbuf += 4;
392 return pst_new_obj(PST_TYPE_NULL, (void*)pst_const_null);
393 } else
394 return NULL;
395}
396
397/* INTEGER */
398static pst_integer *
399pst_integer_new (long value)
400{
401 pst_integer *obj;
402 obj = NEW(1, pst_integer);
403 obj->value = value;
404 return obj;
405}
406
407static void
408pst_integer_release (pst_integer *obj)
409{
410 ASSERT(obj);
411 RELEASE(obj);
412}
413
414static long
415pst_integer_IV (pst_integer *obj)
416{
417 ASSERT(obj);
418 return (long) obj->value;
419}
420
421static double
422pst_integer_RV (pst_integer *obj)
423{
424 ASSERT(obj);
425 return (double) obj->value;
426}
427
428static unsigned char *
429pst_integer_SV (pst_integer *obj)
430{
431 char *value;
432 int len;
433 char fmt_buf[PST_MAX_DIGITS+5];
434
435 ASSERT(obj);
436
437 len = sprintf(fmt_buf, "%ld", obj->value);
438
439 value = NEW(len, char);
440 strcpy(value, fmt_buf);
441
442 return (unsigned char *) value;
443}
444
445static void *
446pst_integer_data_ptr (pst_integer *obj)
447{
448 ASSERT(obj);
449 return (void*) &(obj->value);
450}
451
452static unsigned int
453pst_integer_length (pst_integer *obj)
454{
455 TYPE_ERROR();
456 return 0;
457}
458
459/* REAL */
460static pst_real *
461pst_real_new (double value)
462{
463 pst_real *obj;
464
465 obj = NEW(1, pst_real);
466 obj->value = value;
467
468 return obj;
469}
470
471static void
472pst_real_release (pst_real *obj)
473{
474 ASSERT(obj);
475 RELEASE(obj);
476}
477
478static long
479pst_real_IV (pst_real *obj)
480{
481 ASSERT(obj);
482 return (long) obj->value;
483}
484
485static double
486pst_real_RV (pst_real *obj)
487{
488 ASSERT(obj);
489 return (double) obj->value;
490}
491
492static unsigned char *
493pst_real_SV (pst_real *obj)
494{
495 char *value;
496 int len;
497 char fmt_buf[PST_MAX_DIGITS+5];
498
499 ASSERT(obj);
500
501 len = sprintf(fmt_buf, "%.5g", obj->value);
502
503 value = NEW(len, char);
504 strcpy(value, fmt_buf);
505
506 return (unsigned char *) value;
507}
508
509static void *
510pst_real_data_ptr (pst_real *obj)
511{
512 ASSERT(obj);
513
514 return (void*) &(obj->value);
515}
516
517static unsigned int
518pst_real_length (pst_real *obj)
519{
520 TYPE_ERROR();
521 return 0;
522}
523
524/* NOTE: the input buffer must be null-terminated, i.e., *inbufend == 0 */
525/* leading white-space is ignored */
526pst_obj *
527pst_parse_number (unsigned char **inbuf, unsigned char *inbufend)
528{
529 unsigned char *cur;
530 long lval;
531 double dval;
532
533 errno = 0;
534 lval = strtol((char *) *inbuf, (char **) (void *) &cur, 10);
535 if (errno || *cur == '.' || *cur == 'e' || *cur == 'E') {
536 /* real */
537 errno = 0;
538 dval = strtod((char *) *inbuf, (char **) (void *) &cur);
539 if (!errno && PST_TOKEN_END(cur, inbufend)) {
540 *inbuf = cur;
541 return pst_new_obj(PST_TYPE_REAL, pst_real_new(dval));
542 }
543 } else if (cur != *inbuf && PST_TOKEN_END(cur, inbufend)) {
544 /* integer */
545 *inbuf = cur;
546 return pst_new_obj(PST_TYPE_INTEGER, pst_integer_new(lval));
547 } else if (lval >= 2 && lval <= 36 && *cur == '#' && isalnum(*++cur) &&
548 /* strtod allows leading "0x" for hex numbers, but we don't */
549 (lval != 16 || (cur[1] != 'x' && cur[1] != 'X'))) {
550 /* integer with radix */
551 /* Can the base have a (plus) sign? I think yes. */
552 errno = 0;
553 lval = strtol((char *) cur, (char **) (void *) &cur, lval);
554 if (!errno && PST_TOKEN_END(cur, inbufend)) {
555 *inbuf = cur;
556 return pst_new_obj(PST_TYPE_INTEGER, pst_integer_new(lval));
557 }
558 }
559 /* error */
560 return NULL;
561}
562
563/* NAME */
564
565/*
566 * \0 is not allowed for name object.
567 */
568
569static pst_name *
570pst_name_new (const char *name)
571{
572 pst_name *obj;
573
574 obj = NEW(1, pst_name);
575 obj->value = NEW(strlen(name)+1, char);
576 strcpy(obj->value, name);
577
578 return obj;
579}
580
581static void
582pst_name_release (pst_name *obj)
583{
584 ASSERT(obj);
585 if (obj->value)
586 RELEASE(obj->value);
587 RELEASE(obj);
588}
589
590#if 0
591int
592pst_name_is_valid (const char *name)
593{
594 static const char *valid_chars =
595 "!\"#$&'*+,-.0123456789:;=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\\^_`abcdefghijklmnopqrstuvwxyz|~";
596 if (strspn(name, valid_chars) == strlen(name))
597 return 1;
598 else
599 return 0;
600}
601
602char *
603pst_name_encode (const char *name)
604{
605 char *encoded_name, *p;
606 int i, len;
607 char c;
608
609 len = strlen(name);
610 if (len > PST_NAME_LEN_MAX) {
611 WARN("Input string too long for name object. String will be truncated.");
612 len = PST_NAME_LEN_MAX;
613 }
614
615 p = encoded_name = NEW(3*len+1, char);
616 for (i = 0; i < len; i++) {
617 c = name[i];
618 if (c < '!' || c > '~' ||
619 c == '#' || is_delim(c) || is_space(c)) {
620 *p++ = '#';
621 putxpair(c, &p);
622 } else {
623 *p++ = c;
624 }
625 }
626 *p = '\0';
627
628 return encoded_name;
629}
630#endif
631
632pst_obj *
633pst_parse_name (unsigned char **inbuf, unsigned char *inbufend) /* / is required */
634{
635 unsigned char wbuf[PST_NAME_LEN_MAX+1];
636 unsigned char c, *p = wbuf, *cur = *inbuf;
637 int len = 0;
638
639 if (*cur != '/')
640 return NULL;
641 cur++;
642
643 while (!PST_TOKEN_END(cur, inbufend)) {
644 c = *cur++;
645 if (c == '#') {
646 int val;
647 if (cur + 2 >= inbufend) {
648 WARN("Premature end of input name string.");
649 break;
650 }
651 val = getxpair(&cur);
652 if (val <= 0) {
653 WARN("Invalid char for name object. (ignored)");
654 continue;
655 } else
656 c = (unsigned char) val;
657 }
658 if (len < PST_NAME_LEN_MAX)
659 *p++ = c;
660 len++;
661 }
662 *p = '\0';
663
664 if (len > PST_NAME_LEN_MAX)
665 WARN("String too long for name object. Output will be truncated.");
666
667 *inbuf = cur;
668 return pst_new_obj(PST_TYPE_NAME, pst_name_new((char *)wbuf));
669}
670
671static long
672pst_name_IV (pst_name *obj)
673{
674 TYPE_ERROR();
675 return 0;
676}
677
678static double
679pst_name_RV (pst_name *obj)
680{
681 TYPE_ERROR();
682 return 0;
683}
684
685static unsigned char *
686pst_name_SV (pst_name *obj)
687{
688 char *value;
689
690 value = NEW(strlen(obj->value)+1, char);
691 strcpy(value, obj->value);
692
693 return (unsigned char *) value;
694}
695
696static void *
697pst_name_data_ptr (pst_name *obj)
698{
699 ASSERT(obj);
700 return obj->value;
701}
702
703static unsigned int
704pst_name_length (pst_name *obj)
705{
706 ASSERT(obj);
707 return strlen(obj->value);
708}
709
710
711/* STRING */
712
713/*
714 * TODO: ascii85 string <~ .... ~>
715 */
716static pst_string *
717pst_string_new (unsigned char *str, unsigned int len)
718{
719 pst_string *obj;
720 obj = NEW(1, pst_string);
721 obj->length = len;
722 obj->value = NULL;
723 if (len > 0) {
724 obj->value = NEW(len, unsigned char);
725 if (str)
726 memcpy(obj->value, str, len);
727 }
728 return obj;
729}
730
731static void
732pst_string_release (pst_string *obj)
733{
734 ASSERT(obj);
735 if (obj->value)
736 RELEASE(obj->value);
737 RELEASE(obj);
738}
739
740pst_obj *
741pst_parse_string (unsigned char **inbuf, unsigned char *inbufend)
742{
743 if (*inbuf + 2 >= inbufend) {
744 return NULL;
745 } else if (**inbuf == '(')
746 return pst_new_obj(PST_TYPE_STRING, pst_string_parse_literal(inbuf, inbufend));
747 else if (**inbuf == '<' && *(*inbuf+1) == '~')
748 ERROR("ASCII85 string not supported yet.");
749 else if (**inbuf == '<')
750 return pst_new_obj(PST_TYPE_STRING, pst_string_parse_hex(inbuf, inbufend));
751 return NULL;
752}
753
754static pst_string *
755pst_string_parse_literal (unsigned char **inbuf, unsigned char *inbufend)
756{
757 unsigned char wbuf[PST_STRING_LEN_MAX];
758 unsigned char *cur = *inbuf, c = 0;
759 long len = 0, balance = 1;
760
761 if (cur + 2 > inbufend || *cur != '(')
762 return NULL;
763
764 cur++;
765 while (cur < inbufend && len < PST_STRING_LEN_MAX && balance > 0) {
766 c = *(cur++);
767 switch (c) {
768 case '\\':
769 {
770 unsigned char unescaped, valid;
771 unescaped = esctouc(&cur, inbufend, &valid);
772 if (valid)
773 wbuf[len++] = unescaped;
774 }
775 break;
776 case '(':
777 balance++;
778 wbuf[len++] = '(';
779 break;
780 case ')':
781 balance--;
782 if (balance > 0)
783 wbuf[len++] = ')';
784 break;
785 /*
786 * An end-of-line marker (\n, \r or \r\n), not preceeded by a backslash,
787 * must be converted to single \n.
788 */
789 case '\r':
790 if (cur < inbufend && *cur == '\n')
791 cur++;
792 wbuf[len++] = '\n';
793 break;
794 default:
795 wbuf[len++] = c;
796 }
797 }
798 if (c != ')')
799 return NULL;
800
801 *inbuf = cur;
802 return pst_string_new(wbuf, len);
803}
804
805static pst_string *
806pst_string_parse_hex (unsigned char **inbuf, unsigned char *inbufend)
807{
808 unsigned char wbuf[PST_STRING_LEN_MAX];
809 unsigned char *cur = *inbuf;
810 unsigned long len = 0;
811
812 if (cur + 2 > inbufend || *cur != '<' ||
813 (*cur == '<' && *(cur+1) == '<'))
814 return NULL;
815
816 cur++;
817 /* PDF Reference does not specify how to treat invalid char */
818 while (cur < inbufend && len < PST_STRING_LEN_MAX) {
819 int hi, lo;
820 skip_white_spaces(&cur, inbufend);
821 if (*cur == '>')
822 break;
823 hi = xtoi(*(cur++));
824 if (hi < 0) {
825 WARN("Invalid char for hex string <%x> treated as <0>.", *(cur-1));
826 hi = 0;
827 }
828 skip_white_spaces(&cur, inbufend);
829 if (*cur == '>')
830 break;
831 /* 0 is appended if final hex digit is missing */
832 lo = (cur < inbufend) ? xtoi(*(cur++)) : 0;
833 if (lo < 0) {
834 WARN("Invalid char for hex string <%x> treated as <0>.", *(cur-1));
835 lo = 0;
836 }
837 wbuf[len++] = (hi << 4) | lo;
838 }
839 if (*cur++ != '>')
840 return NULL;
841
842 *inbuf = cur;
843 return pst_string_new(wbuf, len);
844}
845
846static long
847pst_string_IV (pst_string *obj)
848{
849 return (long) pst_string_RV(obj);
850}
851
852static double
853pst_string_RV (pst_string *obj)
854{
855 pst_obj *nobj;
856 unsigned char *p, *end;
857 double rv;
858
859 ASSERT(obj);
860 p = obj->value;
861 end = p + obj->length;
862 nobj = pst_parse_number(&p, end);
863 if (nobj == NULL || p != end)
864 ERROR("Cound not convert string to real value.");
865 rv = pst_getRV(nobj);
866 pst_release_obj(nobj);
867
868 return rv;
869}
870
871static unsigned char *
872pst_string_SV (pst_string *obj)
873{
874 unsigned char *str = NULL;
875 ASSERT(obj);
876 str = NEW(obj->length + 1, unsigned char);
877 memcpy(str, obj->value, obj->length);
878 str[obj->length] = '\0';
879 return str;
880}
881
882static void *
883pst_string_data_ptr (pst_string *obj)
884{
885 ASSERT(obj);
886 return obj->value;
887}
888
889static unsigned int
890pst_string_length (pst_string *obj)
891{
892 ASSERT(obj);
893 return obj->length;
894}