/* * 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); }