summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvipdfmx/src/pst_obj.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/dvipdfmx/src/pst_obj.c')
-rw-r--r--Build/source/texk/dvipdfmx/src/pst_obj.c178
1 files changed, 37 insertions, 141 deletions
diff --git a/Build/source/texk/dvipdfmx/src/pst_obj.c b/Build/source/texk/dvipdfmx/src/pst_obj.c
index 55d5773cdd9..5f0a1fc0e1e 100644
--- a/Build/source/texk/dvipdfmx/src/pst_obj.c
+++ b/Build/source/texk/dvipdfmx/src/pst_obj.c
@@ -1,4 +1,4 @@
-/* $Header: /home/cvsroot/dvipdfmx/src/pst_obj.c,v 1.5 2004/07/27 12:08:47 hirata Exp $
+/* $Header: /home/cvsroot/dvipdfmx/src/pst_obj.c,v 1.7 2008/01/13 21:25:31 matthias Exp $
This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
@@ -23,6 +23,9 @@
*/
#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+
#include "system.h"
#include "mem.h"
#include "error.h"
@@ -65,9 +68,6 @@ static long pst_boolean_length (pst_boolean *obj);
static void *pst_boolean_data_ptr(pst_boolean *obj);
/* NUMBERS */
-static long parse_long (unsigned char **inbuf, unsigned char *inbufend, unsigned char base, unsigned char *ndigits);
-static double cvtdbl (long ipart, long dpart, unsigned char nddigits, long epart);
-
static pst_integer *pst_integer_new (long value) ;
static void pst_integer_release (pst_integer *obj);
static long pst_integer_IV (pst_integer *obj);
@@ -521,147 +521,43 @@ pst_real_length (pst_real *obj)
return 0;
}
-/*
- * Does not skip white spaces
- * base number must be greater than 1 and less than 33.
- * TODO: overflow and underflow
- */
-static long
-parse_long (unsigned char **inbuf, unsigned char *inbufend, unsigned char base, unsigned char *ndigits)
-{
- long val = 0, sign = 1;
- unsigned char *cur = *inbuf, c;
- int count = 0;
-
- if (*cur == '+') {
- sign = 1;
- cur++;
- } else if (*cur == '-') {
- sign = -1;
- cur++;
- }
- while (cur < inbufend) {
- c = *cur;
- if (c >= '0' && c <= '0' + ((base <= 10) ? base-1 : 9)) {
- c = c - '0';
- } else if (base > 10) {
- if (c >= 'a' && c <= 'a' + (base - 11)) {
- c = c - 'a' + 10;
- } else if (c >= 'A' && c <= 'A' + (base - 11)) {
- c = c - 'A' + 10;
- } else {
- break;
- }
- } else {
- break;
- }
- val = val * base + c;
- cur++;
- count++;
- }
-
- if (ndigits != NULL)
- *ndigits = count;
- *inbuf = cur;
- return sign*val;
-}
-
-static double
-cvtdbl (long ipart, long dpart, unsigned char nddigits, long epart)
-{
- double dval = 0.0;
- int i;
-
- if (dpart > 0 && nddigits > 0) {
- dval = dpart;
- for (i = 0; i < nddigits; i++) {
- dval *= 0.1;
- }
- }
-
- if (ipart < 0)
- dval = ipart - dval;
- else
- dval = ipart + dval;
-
- if (epart > 0) {
- for (i = 0; i < epart; i++)
- dval *= 10.0;
- } else if (epart < 0) {
- for (i = 0; i < -epart; i++)
- dval *= 0.1;
- }
-
- return dval;
-}
-
+/* NOTE: the input buffer must be null-terminated, i.e., *inbufend == 0 */
+/* leading white-space is ignored */
pst_obj *
pst_parse_number (unsigned char **inbuf, unsigned char *inbufend)
{
- pst_obj *obj = NULL;
- unsigned char *cur = *inbuf;
- unsigned char ndigits = 0, nddigits = 0;
- int type;
- long ipart = 0, dpart = 0, epart = 0;
-
- if (cur >= inbufend)
- return NULL;
-
- ipart = parse_long(&cur, inbufend, 10, &ndigits);
- if (ndigits > 0 && PST_TOKEN_END(cur, inbufend)) {
- type = PST_TYPE_INTEGER;
- dpart = epart = 0;
- } else if (ndigits > 0 && *cur == '#' &&
- ipart >= 2 && ipart <= 36) { /* Radix */
- cur++;
- ipart = parse_long(&cur, inbufend, ipart, NULL);
- if (ipart >= 0 && PST_TOKEN_END(cur, inbufend)) { /* non-negative only ? */
- type = PST_TYPE_INTEGER;
- dpart = epart = 0;
- } else
- type = -1;
- } else if (*cur == '.') {
- cur++;
- dpart = parse_long(&cur, inbufend, 10, &nddigits);
- ndigits += nddigits;
- if (dpart < 0) {
- type = -1;
- } else if (ndigits > 0 && PST_TOKEN_END(cur, inbufend)) {
- type = PST_TYPE_REAL;
- epart = 0;
- } else if (ndigits > 0 && (*cur == 'e' || *cur == 'E')) {
- cur++;
- epart = parse_long(&cur, inbufend, 10, &ndigits);
- if (ndigits > 0 && PST_TOKEN_END(cur, inbufend))
- type = PST_TYPE_REAL;
- else
- type = -1;
- } else
- type = -1;
- } else if (ndigits > 0 && (*cur == 'e' || *cur == 'E')) {
- cur++;
- epart = parse_long(&cur, inbufend, 10, &ndigits);
- if (ndigits > 0 && PST_TOKEN_END(cur, inbufend)) {
- dpart = 0;
- type = PST_TYPE_REAL;
- } else
- type = -1;
- } else {
- type = -1;
+ unsigned char *cur;
+ long lval;
+ double dval;
+
+ errno = 0;
+ lval = strtol(*inbuf, (char **) &cur, 10);
+ if (errno || *cur == '.' || *cur == 'e' || *cur == 'E') {
+ /* real */
+ errno = 0;
+ dval = strtod(*inbuf, (char **) &cur);
+ if (!errno && PST_TOKEN_END(cur, inbufend)) {
+ *inbuf = cur;
+ return pst_new_obj(PST_TYPE_REAL, pst_real_new(dval));
+ }
+ } else if (cur != *inbuf && PST_TOKEN_END(cur, inbufend)) {
+ /* integer */
+ *inbuf = cur;
+ return pst_new_obj(PST_TYPE_INTEGER, pst_integer_new(lval));
+ } else if (lval >= 2 && lval <= 36 && *cur == '#' && isalnum(*++cur) &&
+ /* strtod allows leading "0x" for hex numbers, but we don't */
+ (lval != 16 || (cur[1] != 'x' && cur[1] != 'X'))) {
+ /* integer with radix */
+ /* Can the base have a (plus) sign? I think yes. */
+ errno = 0;
+ lval = strtol(cur, (char **) &cur, lval);
+ if (!errno && PST_TOKEN_END(cur, inbufend)) {
+ *inbuf = cur;
+ return pst_new_obj(PST_TYPE_INTEGER, pst_integer_new(lval));
+ }
}
-
- if (type < 0)
- return NULL;
-
- if (type == PST_TYPE_REAL)
- obj = pst_new_obj(type, pst_real_new(cvtdbl(ipart, dpart, nddigits, epart)));
- else if (type == PST_TYPE_INTEGER)
- obj = pst_new_obj(type, pst_integer_new(ipart));
- else
- return NULL;
-
- *inbuf = cur;
- return obj;
+ /* error */
+ return NULL;
}
/* NAME */