summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvipsk/papersiz.c
blob: ea1d5fddde8c927756a2364f5f294e1168823229 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*
 *   This function calculates approximately (whole + num/den) * sf.
 *   No need for real extreme accuracy; one twenty thousandth of an
 *   inch should be sufficient.
 *
 *   No `sf' parameter means to use an old one; inches are assumed
 *   originally.
 *
 *   Assumptions:
 *
 *      0 <= num < den <= 20000
 *      0 <= whole
 */
#include "dvips.h" /* The copyright notice in that file is included too! */
/*
 *   The external declarations:
 */
#include "protos.h"
static long
scale(long whole, long num, long den, long sf)
{
   long v;

   v = whole * sf + num * (sf / den);
   if (v / sf != whole || v < 0 || v > 0x40000000L)
      error("! arithmetic overflow in parameter");
   sf = sf % den;
   v += (sf * num * 2 + den) / (2 * den);
   return(v);
}
/*
 *   Convert a sequence of digits into a long; return -1 if no digits.
 *   Advance the passed pointer as well.
 */
static long
myatol(char **s)
{
   register char *p;
   register long result;

   result = 0;
   p = *s;
   while ('0' <= *p && *p <= '9') {
      if (result > 100000000)
         error("! arithmetic overflow in parameter");
      result = 10 * result + *p++ - '0';
   }
   if (p == *s && *p == '.') {
      return 0;
   } else if (p == *s) {
#ifdef KPATHSEA
      error(concat3 ("expected number in ", *s, ", returning 10"));
#else
      error("expected number!  returning 10");
#endif
      return 10;
   } else {
      *s = p;
      return(result);
   }
}
/*
 *   Get a dimension, allowing all the various extensions, and
 *   defaults.  Returns a value in scaled points.
 */
static long scalevals[] = { 1864680L, 65536L, 786432L, 186468L,
                            1L, 65782L, 70124L, 841489L, 4736286L };
static const char *scalenames = "cmptpcmmspbpddccin";
static long
myatodim(char **s)
{
   register long w, num, den, sc;
   register const char *q;
   char *p;
   int negative = 0, i;

   p = *s;
   if (**s == '-') {
      p++;
      negative = 1;
   }
   w = myatol(&p);
   if (w < 0) {
      error("number too large; 1000 used");
      w = 1000;
   }
   num = 0;
   den = 1;
   if (*p == '.') {
      p++;
      while ('0' <= *p && *p <= '9') {
         if (den <= 1000) {
            den *= 10;
            num = num * 10 + *p - '0';
         } else if (den == 10000) {
            den *= 2;
            num = num * 2 + (*p - '0') / 5;
         }
         p++;
      }
   }
   while (*p == ' ')
      p++;
   for (i=0, q=scalenames;; i++, q += 2)
      if (*q == 0) {
#ifdef KPATHSEA
         error(concat3 ("expected units in ", *s, ", assuming inches."));
#else
         error("expected units!  assuming inches.");
#endif
         sc = scalevals[8];
         break;
      } else if (*p == *q && p[1] == q[1]) {
         sc = scalevals[i];
         p += 2;
         break;
      }
   w = scale(w, num, den, sc);
   *s = p;
   return(negative?-w:w);
}
/*
 *   The routine where we handle the paper size special.  We need to pass in
 *   the string after the `papersize=' specification.
 */
void
handlepapersize(char *p, integer *x, integer *y)
{
   while (*p == ' ')
      p++;
   *x = myatodim(&p);
   while (*p == ' ' || *p == ',')
      p++;
   *y = myatodim(&p);
}