summaryrefslogtreecommitdiff
path: root/Build
diff options
context:
space:
mode:
authorAkira Kakuto <kakuto@fuk.kindai.ac.jp>2018-11-17 07:32:49 +0000
committerAkira Kakuto <kakuto@fuk.kindai.ac.jp>2018-11-17 07:32:49 +0000
commitd7f366bbd6165f743d507912dfcfeb10f2a304ac (patch)
tree1831cfe03ebe08785cb9c80faeaebd799e142de3 /Build
parent7d31f47ebfdd6ef50950dfbe0136e146c1e604bb (diff)
Support some primitives from pdfTeX in XeTeX (Joseph Wright)
git-svn-id: svn://tug.org/texlive/trunk@49176 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build')
-rw-r--r--Build/source/texk/web2c/ChangeLog4
-rw-r--r--Build/source/texk/web2c/lib/ChangeLog4
-rw-r--r--Build/source/texk/web2c/lib/texmfmp.c40
-rw-r--r--Build/source/texk/web2c/texmfmp.h4
-rw-r--r--Build/source/texk/web2c/xetexdir/ChangeLog5
-rw-r--r--Build/source/texk/web2c/xetexdir/xetex.defines5
-rw-r--r--Build/source/texk/web2c/xetexdir/xetex.web961
7 files changed, 813 insertions, 210 deletions
diff --git a/Build/source/texk/web2c/ChangeLog b/Build/source/texk/web2c/ChangeLog
index d5e2fe48e12..d80ed5d7e9c 100644
--- a/Build/source/texk/web2c/ChangeLog
+++ b/Build/source/texk/web2c/ChangeLog
@@ -1,3 +1,7 @@
+2018-11-17 Joseph Wright <joseph.wright@morningstar2.co.uk>
+
+ * texmfmp.h: Support some primitives from pdfTeX in XeTeX.
+
2018-09-09 Karl Berry <karl@tug.org>
* mftraptest.test,
diff --git a/Build/source/texk/web2c/lib/ChangeLog b/Build/source/texk/web2c/lib/ChangeLog
index 37002a0a0f5..823ef735157 100644
--- a/Build/source/texk/web2c/lib/ChangeLog
+++ b/Build/source/texk/web2c/lib/ChangeLog
@@ -1,3 +1,7 @@
+2018-11-17 Joseph Wright <joseph.wright@morningstar2.co.uk>
+
+ * texmfmp.c: Support some primitives from pdfTeX in XeTeX.
+
2018-11-14 Andreas Scherer <https://ascherer.github.io>
* printversion.c: free xmalloc'd prog_name.
diff --git a/Build/source/texk/web2c/lib/texmfmp.c b/Build/source/texk/web2c/lib/texmfmp.c
index 3b5e1ddb235..7a253cf7373 100644
--- a/Build/source/texk/web2c/lib/texmfmp.c
+++ b/Build/source/texk/web2c/lib/texmfmp.c
@@ -151,7 +151,22 @@ char *generic_synctex_get_current_name (void)
#if !IS_pTeX
FILE *Poptr;
#endif
-#endif
+#undef fopen
+#undef xfopen
+#define fopen fsyscp_fopen
+#define xfopen fsyscp_xfopen
+#include <wchar.h>
+int fsyscp_stat(const char *path, struct stat *buffer)
+{
+ wchar_t *wpath;
+ int ret;
+ wpath = get_wstring_from_mbstring(file_system_codepage,
+ path, wpath = NULL);
+ ret = _wstat(wpath, buffer);
+ free(wpath);
+ return ret;
+}
+#endif /* WIN32 */
#if defined(TeX) || (defined(MF) && defined(WIN32))
static int
@@ -1379,24 +1394,6 @@ tcx_get_num (int upb,
/* FIXME: A new format ought to be introduced for these files. */
-#ifdef _WIN32
-#undef fopen
-#undef xfopen
-#define fopen fsyscp_fopen
-#define xfopen fsyscp_xfopen
-#include <wchar.h>
-int fsyscp_stat(const char *path, struct stat *buffer)
-{
- wchar_t *wpath;
- int ret;
- wpath = get_wstring_from_mbstring(file_system_codepage,
- path, wpath = NULL);
- ret = _wstat(wpath, buffer);
- free(wpath);
- return ret;
-}
-#endif /* WIN32 */
-
void
readtcxfile (void)
{
@@ -2322,7 +2319,7 @@ WARNING1 ("invalid value (expected 0 or 1) for environment variable $FORCE_SOURC
}
}
-#if defined(pdfTeX) || defined(epTeX) || defined(eupTeX)
+#if defined(pdfTeX) || defined(epTeX) || defined(eupTeX) || defined(XeTeX)
/*
Getting a high resolution time.
*/
@@ -3010,8 +3007,6 @@ void pdftex_fail(const char *fmt, ...)
}
#endif /* not pdfTeX */
-#if !defined(XeTeX)
-
#define TIME_STR_SIZE 30
char start_time_str[TIME_STR_SIZE];
static char time_str[TIME_STR_SIZE];
@@ -3280,7 +3275,6 @@ void getfiledump(integer s, int offset, int length)
}
xfree(file_name);
}
-#endif /* not XeTeX */
/* Converts any given string in into an allowed PDF string which is
* hexadecimal encoded;
diff --git a/Build/source/texk/web2c/texmfmp.h b/Build/source/texk/web2c/texmfmp.h
index be8311f0e58..1dd7c56d019 100644
--- a/Build/source/texk/web2c/texmfmp.h
+++ b/Build/source/texk/web2c/texmfmp.h
@@ -124,7 +124,6 @@ extern int tfmtemp, texinputtype;
#if !defined (pdfTeX)
extern void pdftex_fail(const char *fmt, ...);
#endif
-#if !defined(XeTeX)
extern char start_time_str[];
extern void initstarttime(void);
extern char *makecstring(integer s);
@@ -133,7 +132,6 @@ extern void getcreationdate(void);
extern void getfilemoddate(integer s);
extern void getfilesize(integer s);
extern void getfiledump(integer s, int offset, int length);
-#endif
extern void convertStringToHexString(const char *in, char *out, int lin);
extern void getmd5sum(integer s, int file);
#endif
@@ -220,7 +218,7 @@ extern boolean input_line (FILE *);
#define dateandtime(i,j,k,l) get_date_and_time (&(i), &(j), &(k), &(l))
extern void get_date_and_time (integer *, integer *, integer *, integer *);
-#if defined(pdfTeX) || defined(epTeX) || defined(eupTeX)
+#if defined(pdfTeX) || defined(epTeX) || defined(eupTeX) || defined(XeTeX)
/* Get high-res time info. */
#define secondsandmicros(i,j) get_seconds_and_micros (&(i), &(j))
extern void get_seconds_and_micros (integer *, integer *);
diff --git a/Build/source/texk/web2c/xetexdir/ChangeLog b/Build/source/texk/web2c/xetexdir/ChangeLog
index dfb445bda64..8ff98249d4f 100644
--- a/Build/source/texk/web2c/xetexdir/ChangeLog
+++ b/Build/source/texk/web2c/xetexdir/ChangeLog
@@ -1,3 +1,8 @@
+2018-11-17 Joseph Wright <joseph.wright@morningstar2.co.uk>
+
+ * xetex.web, xetex.defines: Support some primitives from
+ pdfTeX in XeTeX. Add \expanded and extend \Uchar a bit.
+
2018-10-22 Akira Kakuto <kakuto@fuk.kindai.ac.jp>
* pdfimage.cpp: Cast types to support poppler 0.70.0.
diff --git a/Build/source/texk/web2c/xetexdir/xetex.defines b/Build/source/texk/web2c/xetexdir/xetex.defines
index 8772a82b622..2c5bff5039f 100644
--- a/Build/source/texk/web2c/xetexdir/xetex.defines
+++ b/Build/source/texk/web2c/xetexdir/xetex.defines
@@ -179,4 +179,9 @@ authorization from the copyright holders.
@define function getcpcode();
@define function getnativewordcp();
+@define procedure initstarttime;
+@define procedure getcreationdate;
+@define procedure getfilemoddate();
+@define procedure getfilesize();
+@define procedure getfiledump();
@define procedure getmd5sum();
diff --git a/Build/source/texk/web2c/xetexdir/xetex.web b/Build/source/texk/web2c/xetexdir/xetex.web
index f7b0bbe05cb..e7746844ed2 100644
--- a/Build/source/texk/web2c/xetexdir/xetex.web
+++ b/Build/source/texk/web2c/xetexdir/xetex.web
@@ -2593,6 +2593,367 @@ routines cited there must be modified to allow negative glue ratios.)
@<Types...@>=
@!glue_ratio=real; {one-word representation of a glue expansion factor}
+@* \[7b] Random numbers.
+
+\font\tenlogo=logo10 % font used for the METAFONT logo
+\def\MP{{\tenlogo META}\-{\tenlogo POST}}
+\def\pdfTeX{pdf\TeX}
+
+This section is (almost) straight from MetaPost. I had to change
+the types (use |integer| instead of |fraction|), but that should
+not have any influence on the actual calculations (the original
+comments refer to quantities like |fraction_four| ($2^{30}$), and
+that is the same as the numeric representation of |maxdimen|).
+
+I've copied the low-level variables and routines that are needed, but
+only those (e.g. |m_log|), not the accompanying ones like |m_exp|. Most
+of the following low-level numeric routines are only needed within the
+calculation of |norm_rand|. I've been forced to rename |make_fraction|
+to |make_frac| because TeX already has a routine by that name with
+a wholly different function (it creates a |fraction_noad| for math
+typesetting) -- Taco
+
+And now let's complete our collection of numeric utility routines
+by considering random number generation.
+\MP\ generates pseudo-random numbers with the additive scheme recommended
+in Section 3.6 of {\sl The Art of Computer Programming}; however, the
+results are random fractions between 0 and |fraction_one-1|, inclusive.
+
+There's an auxiliary array |randoms| that contains 55 pseudo-random
+fractions. Using the recurrence $x_n=(x_{n-55}-x_{n-31})\bmod 2^{28}$,
+we generate batches of 55 new $x_n$'s at a time by calling |new_randoms|.
+The global variable |j_random| tells which element has most recently
+been consumed.
+
+@<Glob...@>=
+@!randoms:array[0..54] of integer; {the last 55 random values generated}
+@!j_random:0..54; {the number of unused |randoms|}
+@!random_seed:scaled; {the default random seed}
+
+@ A small bit of metafont is needed.
+
+@d fraction_half==@'1000000000 {$2^{27}$, represents 0.50000000}
+@d fraction_one==@'2000000000 {$2^{28}$, represents 1.00000000}
+@d fraction_four==@'10000000000 {$2^{30}$, represents 4.00000000}
+@d el_gordo == @'17777777777 {$2^{31}-1$, the largest value that \MP\ likes}
+@d halfp(#)==(#) div 2
+@d double(#) == #:=#+# {multiply a variable by two}
+
+@ The |make_frac| routine produces the |fraction| equivalent of
+|p/q|, given integers |p| and~|q|; it computes the integer
+$f=\lfloor2^{28}p/q+{1\over2}\rfloor$, when $p$ and $q$ are
+positive. If |p| and |q| are both of the same scaled type |t|,
+the ``type relation'' |make_frac(t,t)=fraction| is valid;
+and it's also possible to use the subroutine ``backwards,'' using
+the relation |make_frac(t,fraction)=t| between scaled types.
+
+If the result would have magnitude $2^{31}$ or more, |make_frac|
+sets |arith_error:=true|. Most of \MP's internal computations have
+been designed to avoid this sort of error.
+
+If this subroutine were programmed in assembly language on a typical
+machine, we could simply compute |(@t$2^{28}$@>*p)div q|, since a
+double-precision product can often be input to a fixed-point division
+instruction. But when we are restricted to \PASCAL\ arithmetic it
+is necessary either to resort to multiple-precision maneuvering
+or to use a simple but slow iteration. The multiple-precision technique
+would be about three times faster than the code adopted here, but it
+would be comparatively long and tricky, involving about sixteen
+additional multiplications and divisions.
+
+This operation is part of \MP's ``inner loop''; indeed, it will
+consume nearly 10\pct! of the running time (exclusive of input and output)
+if the code below is left unchanged. A machine-dependent recoding
+will therefore make \MP\ run faster. The present implementation
+is highly portable, but slow; it avoids multiplication and division
+except in the initial stage. System wizards should be careful to
+replace it with a routine that is guaranteed to produce identical
+results in all cases.
+@^system dependencies@>
+
+As noted below, a few more routines should also be replaced by machine-dependent
+code, for efficiency. But when a procedure is not part of the ``inner loop,''
+such changes aren't advisable; simplicity and robustness are
+preferable to trickery, unless the cost is too high.
+@^inner loop@>
+
+@p function make_frac(@!p,@!q:integer):integer;
+var @!f:integer; {the fraction bits, with a leading 1 bit}
+@!n:integer; {the integer part of $\vert p/q\vert$}
+@!negative:boolean; {should the result be negated?}
+@!be_careful:integer; {disables certain compiler optimizations}
+begin if p>=0 then negative:=false
+else begin negate(p); negative:=true;
+ end;
+if q<=0 then
+ begin debug if q=0 then confusion("/");@;@+gubed@;@/
+@:this can't happen /}{\quad \./@>
+ negate(q); negative:=not negative;
+ end;
+n:=p div q; p:=p mod q;
+if n>=8 then
+ begin arith_error:=true;
+ if negative then make_frac:=-el_gordo@+else make_frac:=el_gordo;
+ end
+else begin n:=(n-1)*fraction_one;
+ @<Compute $f=\lfloor 2^{28}(1+p/q)+{1\over2}\rfloor$@>;
+ if negative then make_frac:=-(f+n)@+else make_frac:=f+n;
+ end;
+end;
+
+@ The |repeat| loop here preserves the following invariant relations
+between |f|, |p|, and~|q|:
+(i)~|0<=p<q|; (ii)~$fq+p=2^k(q+p_0)$, where $k$ is an integer and
+$p_0$ is the original value of~$p$.
+
+Notice that the computation specifies
+|(p-q)+p| instead of |(p+p)-q|, because the latter could overflow.
+Let us hope that optimizing compilers do not miss this point; a
+special variable |be_careful| is used to emphasize the necessary
+order of computation. Optimizing compilers should keep |be_careful|
+in a register, not store it in memory.
+@^inner loop@>
+
+@<Compute $f=\lfloor 2^{28}(1+p/q)+{1\over2}\rfloor$@>=
+f:=1;
+repeat be_careful:=p-q; p:=be_careful+p;
+if p>=0 then f:=f+f+1
+else begin double(f); p:=p+q;
+ end;
+until f>=fraction_one;
+be_careful:=p-q;
+if be_careful+p>=0 then incr(f)
+
+@
+
+@p function take_frac(@!q:integer;@!f:integer):integer;
+var @!p:integer; {the fraction so far}
+@!negative:boolean; {should the result be negated?}
+@!n:integer; {additional multiple of $q$}
+@!be_careful:integer; {disables certain compiler optimizations}
+begin @<Reduce to the case that |f>=0| and |q>0|@>;
+if f<fraction_one then n:=0
+else begin n:=f div fraction_one; f:=f mod fraction_one;
+ if q<=el_gordo div n then n:=n*q
+ else begin arith_error:=true; n:=el_gordo;
+ end;
+ end;
+f:=f+fraction_one;
+@<Compute $p=\lfloor qf/2^{28}+{1\over2}\rfloor-q$@>;
+be_careful:=n-el_gordo;
+if be_careful+p>0 then
+ begin arith_error:=true; n:=el_gordo-p;
+ end;
+if negative then take_frac:=-(n+p)
+else take_frac:=n+p;
+end;
+
+@ @<Reduce to the case that |f>=0| and |q>0|@>=
+if f>=0 then negative:=false
+else begin negate(f); negative:=true;
+ end;
+if q<0 then
+ begin negate(q); negative:=not negative;
+ end;
+
+@ The invariant relations in this case are (i)~$\lfloor(qf+p)/2^k\rfloor
+=\lfloor qf_0/2^{28}+{1\over2}\rfloor$, where $k$ is an integer and
+$f_0$ is the original value of~$f$; (ii)~$2^k\L f<2^{k+1}$.
+@^inner loop@>
+
+@<Compute $p=\lfloor qf/2^{28}+{1\over2}\rfloor-q$@>=
+p:=fraction_half; {that's $2^{27}$; the invariants hold now with $k=28$}
+if q<fraction_four then
+ repeat if odd(f) then p:=halfp(p+q)@+else p:=halfp(p);
+ f:=halfp(f);
+ until f=1
+else repeat if odd(f) then p:=p+halfp(q-p)@+else p:=halfp(p);
+ f:=halfp(f);
+ until f=1
+
+@ The subroutines for logarithm and exponential involve two tables.
+The first is simple: |two_to_the[k]| equals $2^k$. The second involves
+a bit more calculation, which the author claims to have done correctly:
+|spec_log[k]| is $2^{27}$ times $\ln\bigl(1/(1-2^{-k})\bigr)=
+2^{-k}+{1\over2}2^{-2k}+{1\over3}2^{-3k}+\cdots\,$, rounded to the
+nearest integer.
+
+@<Glob...@>=
+@!two_to_the:array[0..30] of integer; {powers of two}
+@!spec_log:array[1..28] of integer; {special logarithms}
+
+
+@ @<Set init...@>=
+two_to_the[0]:=1;
+for k:=1 to 30 do two_to_the[k]:=2*two_to_the[k-1];
+spec_log[1]:=93032640;
+spec_log[2]:=38612034;
+spec_log[3]:=17922280;
+spec_log[4]:=8662214;
+spec_log[5]:=4261238;
+spec_log[6]:=2113709;
+spec_log[7]:=1052693;
+spec_log[8]:=525315;
+spec_log[9]:=262400;
+spec_log[10]:=131136;
+spec_log[11]:=65552;
+spec_log[12]:=32772;
+spec_log[13]:=16385;
+for k:=14 to 27 do spec_log[k]:=two_to_the[27-k];
+spec_log[28]:=1;
+
+@
+
+@p function m_log(@!x:integer):integer;
+var @!y,@!z:integer; {auxiliary registers}
+@!k:integer; {iteration counter}
+begin if x<=0 then @<Handle non-positive logarithm@>
+else begin y:=1302456956+4-100; {$14\times2^{27}\ln2\approx1302456956.421063$}
+ z:=27595+6553600; {and $2^{16}\times .421063\approx 27595$}
+ while x<fraction_four do
+ begin double(x); y:=y-93032639; z:=z-48782;
+ end; {$2^{27}\ln2\approx 93032639.74436163$
+ and $2^{16}\times.74436163\approx 48782$}
+ y:=y+(z div unity); k:=2;
+ while x>fraction_four+4 do
+ @<Increase |k| until |x| can be multiplied by a
+ factor of $2^{-k}$, and adjust $y$ accordingly@>;
+ m_log:=y div 8;
+ end;
+end;
+
+@ @<Increase |k| until |x| can...@>=
+begin z:=((x-1) div two_to_the[k])+1; {$z=\lceil x/2^k\rceil$}
+while x<fraction_four+z do
+ begin z:=halfp(z+1); k:=k+1;
+ end;
+y:=y+spec_log[k]; x:=x-z;
+end
+
+@ @<Handle non-positive logarithm@>=
+begin print_err("Logarithm of ");
+@.Logarithm...replaced by 0@>
+print_scaled(x); print(" has been replaced by 0");
+help2("Since I don't take logs of non-positive numbers,")@/
+ ("I'm zeroing this one. Proceed, with fingers crossed.");
+error; m_log:=0;
+end
+
+@ The following somewhat different subroutine tests rigorously if $ab$ is
+greater than, equal to, or less than~$cd$,
+given integers $(a,b,c,d)$. In most cases a quick decision is reached.
+The result is $+1$, 0, or~$-1$ in the three respective cases.
+
+@d return_sign(#)==begin ab_vs_cd:=#; return;
+ end
+
+@p function ab_vs_cd(@!a,b,c,d:integer):integer;
+label exit;
+var @!q,@!r:integer; {temporary registers}
+begin @<Reduce to the case that |a,c>=0|, |b,d>0|@>;
+loop@+ begin q := a div d; r := c div b;
+ if q<>r then
+ if q>r then return_sign(1)@+else return_sign(-1);
+ q := a mod d; r := c mod b;
+ if r=0 then
+ if q=0 then return_sign(0)@+else return_sign(1);
+ if q=0 then return_sign(-1);
+ a:=b; b:=q; c:=d; d:=r;
+ end; {now |a>d>0| and |c>b>0|}
+exit:end;
+
+@ @<Reduce to the case that |a...@>=
+if a<0 then
+ begin negate(a); negate(b);
+ end;
+if c<0 then
+ begin negate(c); negate(d);
+ end;
+if d<=0 then
+ begin if b>=0 then
+ if ((a=0)or(b=0))and((c=0)or(d=0)) then return_sign(0)
+ else return_sign(1);
+ if d=0 then
+ if a=0 then return_sign(0)@+else return_sign(-1);
+ q:=a; a:=c; c:=q; q:=-b; b:=-d; d:=q;
+ end
+else if b<=0 then
+ begin if b<0 then if a>0 then return_sign(-1);
+ if c=0 then return_sign(0) else return_sign(-1);
+ end
+
+@ To consume a random integer, the program below will say `|next_random|'
+and then it will fetch |randoms[j_random]|.
+
+@d next_random==if j_random=0 then new_randoms
+ else decr(j_random)
+
+@p procedure new_randoms;
+var @!k:0..54; {index into |randoms|}
+@!x:integer; {accumulator}
+begin for k:=0 to 23 do
+ begin x:=randoms[k]-randoms[k+31];
+ if x<0 then x:=x+fraction_one;
+ randoms[k]:=x;
+ end;
+for k:=24 to 54 do
+ begin x:=randoms[k]-randoms[k-24];
+ if x<0 then x:=x+fraction_one;
+ randoms[k]:=x;
+ end;
+j_random:=54;
+end;
+
+@ To initialize the |randoms| table, we call the following routine.
+
+@p procedure init_randoms(@!seed:integer);
+var @!j,@!jj,@!k:integer; {more or less random integers}
+@!i:0..54; {index into |randoms|}
+begin j:=abs(seed);
+while j>=fraction_one do j:=halfp(j);
+k:=1;
+for i:=0 to 54 do
+ begin jj:=k; k:=j-k; j:=jj;
+ if k<0 then k:=k+fraction_one;
+ randoms[(i*21)mod 55]:=j;
+ end;
+new_randoms; new_randoms; new_randoms; {``warm up'' the array}
+end;
+
+@ To produce a uniform random number in the range |0<=u<x| or |0>=u>x|
+or |0=u=x|, given a |scaled| value~|x|, we proceed as shown here.
+
+Note that the call of |take_frac| will produce the values 0 and~|x|
+with about half the probability that it will produce any other particular
+values between 0 and~|x|, because it rounds its answers.
+
+@p function unif_rand(@!x:integer):integer;
+var @!y:integer; {trial value}
+begin next_random; y:=take_frac(abs(x),randoms[j_random]);
+if y=abs(x) then unif_rand:=0
+else if x>0 then unif_rand:=y
+else unif_rand:=-y;
+end;
+
+@ Finally, a normal deviate with mean zero and unit standard deviation
+can readily be obtained with the ratio method (Algorithm 3.4.1R in
+{\sl The Art of Computer Programming\/}).
+
+@p function norm_rand:integer;
+var @!x,@!u,@!l:integer; {what the book would call $2^{16}X$, $2^{28}U$,
+ and $-2^{24}\ln U$}
+begin repeat
+ repeat next_random;
+ x:=take_frac(112429,randoms[j_random]-fraction_half);
+ {$2^{16}\sqrt{8/e}\approx 112428.82793$}
+ next_random; u:=randoms[j_random];
+ until abs(x)<u;
+x:=make_frac(x,u);
+l:=139548960-m_log(u); {$2^{24}\cdot12\ln2\approx139548959.6165$}
+until ab_vs_cd(1024,l,x,x)>=0;
+norm_rand:=x;
+end;
+
@* \[8] Packed data.
In order to make efficient use of storage space, \TeX\ bases its major data
structures on a |memory_word|, which contains either a (signed) integer,
@@ -3919,6 +4280,8 @@ else
round_xn_over_d:=-u;
end;
+@<Declare procedures that need to be declared forward for \pdfTeX@>@;
+
@* \[12] Displaying boxes.
We can reinforce our knowledge of the data structures just introduced
by considering two procedures that display a list in symbolic form.
@@ -9509,60 +9872,51 @@ the codes for its extensions: |eTeX_version_code|, \dots\ .
@d input_line_no_code=glue_val+2 {code for \.{\\inputlineno}}
@d badness_code=input_line_no_code+1 {code for \.{\\badness}}
@#
-@d eTeX_int=badness_code+1 {first of \eTeX\ codes for integers}
+@d pdftex_first_rint_code = badness_code + 1 {base for \pdfTeX's command codes}
+@d pdf_last_x_pos_code = pdftex_first_rint_code + 6 {code for \.{\\pdflastxpos}}
+@d pdf_last_y_pos_code = pdftex_first_rint_code + 7 {code for \.{\\pdflastypos}}
+@d elapsed_time_code = pdftex_first_rint_code + 10 {code for \.{\\elapsedtime}}
+@d pdf_shell_escape_code = pdftex_first_rint_code + 11 {code for \.{\\shellescape}}
+@d random_seed_code = pdftex_first_rint_code + 12 {code for \.{\\randomseed}}
+@d pdftex_last_item_codes = pdftex_first_rint_code + 13 {end of \pdfTeX's command codes}
@#
-@d XeTeX_int=eTeX_int+8 {first of \XeTeX\ codes for integers}
+@d XeTeX_int = pdftex_last_item_codes + 1 {base for \XeTeX's command codes}
+@d XeTeX_version_code = XeTeX_int + 0 {code for \.{\\XeTeXversion}}
+@d XeTeX_count_glyphs_code = XeTeX_int + 1 {code for \.{\\XeTeXcountglyphs}}
+@d XeTeX_count_variations_code = XeTeX_int + 2 {Deprecated}
+@d XeTeX_variation_code = XeTeX_int + 3 {Deprecated}
+@d XeTeX_find_variation_by_name_code = XeTeX_int + 4 {Deprecated}
+@d XeTeX_variation_min_code = XeTeX_int + 5 {Deprecated}
+@d XeTeX_variation_max_code = XeTeX_int + 6 {Deprecated}
+@d XeTeX_variation_default_code = XeTeX_int + 7 {Deprecated}
+@d XeTeX_count_features_code = XeTeX_int + 8 {code for \.{\\XeTeXcountfeatures}}
+@d XeTeX_feature_code_code = XeTeX_int + 9 {code for \.{\\XeTeXfeaturecode}}
+@d XeTeX_find_feature_by_name_code = XeTeX_int + 10 {code for \.{\\XeTeXfindfeaturebyname}}
+@d XeTeX_is_exclusive_feature_code = XeTeX_int + 11 {code for \.{\\XeTeXisexclusivefeature}}
+@d XeTeX_count_selectors_code = XeTeX_int + 12 {code for \.{\\XeTeXcountselectors}}
+@d XeTeX_selector_code_code = XeTeX_int + 13 {code for \.{\\XeTeXselectorcode}}
+@d XeTeX_find_selector_by_name_code = XeTeX_int + 14 {code for \.{\\XeTeXfindselectorbyname}}
+@d XeTeX_is_default_selector_code = XeTeX_int + 15 {code for \.{\\XeTeXisdefaultselector}}
+@d XeTeX_OT_count_scripts_code = XeTeX_int + 16 {code for \.{\\XeTeXOTcountscripts}}
+@d XeTeX_OT_count_languages_code = XeTeX_int + 17 {code for \.{\\XeTeXOTcountlanguages}}
+@d XeTeX_OT_count_features_code = XeTeX_int + 18 {code for \.{\\XeTeXOTcountfeatures}}
+@d XeTeX_OT_script_code = XeTeX_int + 19 {code for \.{\\XeTeXOTscripttag}}
+@d XeTeX_OT_language_code = XeTeX_int + 20 {code for \.{\\XeTeXOTlanguagetag}}
+@d XeTeX_OT_feature_code = XeTeX_int + 21 {code for \.{\\XeTeXOTfeaturetag}}
+@d XeTeX_map_char_to_glyph_code = XeTeX_int + 22 {code for \.{\\XeTeXcharglyph}}
+@d XeTeX_glyph_index_code = XeTeX_int + 23 {code for \.{\\XeTeXglyphindex}}
+@d XeTeX_font_type_code = XeTeX_int + 24 {code for \.{\\XeTeXfonttype}}
+@d XeTeX_first_char_code = XeTeX_int + 25 {code for \.{\\XeTeXfirstfontchar}}
+@d XeTeX_last_char_code = XeTeX_int + 26 {code for \.{\\XeTeXlastfontchar}}
+@d XeTeX_pdf_page_count_code = XeTeX_int + 27 {code for \.{\\XeTeXpdfpagecount}}
+@d XeTeX_last_item_codes = XeTeX_int + 27 {end of \XeTeX's command codes}
@#
-@d XeTeX_version_code=XeTeX_int {code for \.{\\XeTeXversion}}
-
-@d XeTeX_count_glyphs_code=XeTeX_int+1
-
-@d XeTeX_count_variations_code=XeTeX_int+2 {Deprecated}
-@d XeTeX_variation_code=XeTeX_int+3 {Deprecated}
-@d XeTeX_find_variation_by_name_code=XeTeX_int+4 {Deprecated}
-@d XeTeX_variation_min_code=XeTeX_int+5 {Deprecated}
-@d XeTeX_variation_max_code=XeTeX_int+6 {Deprecated}
-@d XeTeX_variation_default_code=XeTeX_int+7 {Deprecated}
-
-@d XeTeX_count_features_code=XeTeX_int+8
-@d XeTeX_feature_code_code=XeTeX_int+9
-@d XeTeX_find_feature_by_name_code=XeTeX_int+10
-@d XeTeX_is_exclusive_feature_code=XeTeX_int+11
-@d XeTeX_count_selectors_code=XeTeX_int+12
-@d XeTeX_selector_code_code=XeTeX_int+13
-@d XeTeX_find_selector_by_name_code=XeTeX_int+14
-@d XeTeX_is_default_selector_code=XeTeX_int+15
-
-@d XeTeX_OT_count_scripts_code=XeTeX_int+16
-@d XeTeX_OT_count_languages_code=XeTeX_int+17
-@d XeTeX_OT_count_features_code=XeTeX_int+18
-@d XeTeX_OT_script_code=XeTeX_int+19
-@d XeTeX_OT_language_code=XeTeX_int+20
-@d XeTeX_OT_feature_code=XeTeX_int+21
-
-@d XeTeX_map_char_to_glyph_code=XeTeX_int+22
-@d XeTeX_glyph_index_code=XeTeX_int+23
-@d XeTeX_font_type_code=XeTeX_int+24
-
-@d XeTeX_first_char_code=XeTeX_int+25
-@d XeTeX_last_char_code=XeTeX_int+26
-
-@d pdf_last_x_pos_code = XeTeX_int+27
-@d pdf_last_y_pos_code = XeTeX_int+28
-@d pdf_strcmp_code = XeTeX_int+29
-@d pdf_mdfive_sum_code = XeTeX_int+30
-@d pdf_shell_escape_code = XeTeX_int+31
-
-@d XeTeX_pdf_page_count_code = XeTeX_int+32
-
-@#
-@d XeTeX_dim=XeTeX_int+33 {first of \XeTeX\ codes for dimensions}
-
-@d XeTeX_glyph_bounds_code = XeTeX_dim
-
+@d XeTeX_dim = XeTeX_last_item_codes + 1 {first of \XeTeX\ codes for dimensions}
+@d XeTeX_glyph_bounds_code = XeTeX_dim + 0 {code for \.{\\XeTeXglyphbounds}}
+@d XeTeX_last_dim_codes = XeTeX_dim + 0 {end of \XeTeX's command codes}
@#
-@d eTeX_dim=XeTeX_dim+1 {first of \eTeX\ codes for dimensions}
- {changed for \XeTeX\ to make room for \XeTeX\ integers and dimens}
+@d eTeX_int=XeTeX_last_dim_codes+1 {first of \eTeX\ codes for integers}
+@d eTeX_dim=eTeX_int+8 {first of \eTeX\ codes for dimensions}
@d eTeX_glue=eTeX_dim+9 {first of \eTeX\ codes for glue}
@d eTeX_mu=eTeX_glue+1 {first of \eTeX\ codes for muglue}
@d eTeX_expr=eTeX_mu+1 {first of \eTeX\ codes for expressions}
@@ -9592,6 +9946,17 @@ primitive("inputlineno",last_item,input_line_no_code);
@!@:input_line_no_}{\.{\\inputlineno} primitive@>
primitive("badness",last_item,badness_code);
@!@:badness_}{\.{\\badness} primitive@>
+primitive("pdflastxpos",last_item,pdf_last_x_pos_code);@/
+@!@:pdf_last_x_pos_}{\.{\\pdflastxpos} primitive@>
+primitive("pdflastypos",last_item,pdf_last_y_pos_code);@/
+@!@:pdf_last_y_pos_}{\.{\\pdflastypos} primitive@>
+primitive("elapsedtime",last_item,elapsed_time_code);
+@!@:elapsed_time_}{\.{\\elapsedtime} primitive@>
+primitive("shellescape",last_item,pdf_shell_escape_code);
+@!@:pdf_shell_escape_}{\.{\\shellescape} primitive@>
+primitive("randomseed",last_item,random_seed_code);
+@!@:random_seed_}{\.{\\randomseed} primitive@>
+
@ @<Cases of |print_cmd_chr|...@>=
set_aux: if chr_code=vmode then print_esc("prevdepth")
@@ -9607,8 +9972,12 @@ last_item: case chr_code of
dimen_val: print_esc("lastkern");
glue_val: print_esc("lastskip");
input_line_no_code: print_esc("inputlineno");
- pdf_shell_escape_code: print_esc("shellescape");
@/@<Cases of |last_item| for |print_cmd_chr|@>@/
+ pdf_last_x_pos_code: print_esc("pdflastxpos");
+ pdf_last_y_pos_code: print_esc("pdflastypos");
+ elapsed_time_code: print_esc("elapsedtime");
+ pdf_shell_escape_code: print_esc("shellescape");
+ random_seed_code: print_esc("randomseed");
othercases print_esc("badness")
endcases;
@@ -9701,6 +10070,8 @@ if m>=input_line_no_code then
else begin case m of
input_line_no_code: cur_val:=line;
badness_code: cur_val:=last_badness;
+ elapsed_time_code: cur_val := get_microinterval;
+ random_seed_code: cur_val := random_seed;
pdf_shell_escape_code:
begin
if shellenabledp then begin
@@ -10499,6 +10870,7 @@ while k<pool_ptr do
t := @"10000 + (t - @"D800) * @"400 + (so(str_pool[k]) - @"DC00);
end;
if cat=0 then t := other_token + t
+ else if cat=active_char then t := cs_token_flag + active_base + t
else t := max_char_val * cat + t;
end;
fast_store_new_token(t);
@@ -10570,21 +10942,30 @@ end;
@d font_name_code=4 {command code for \.{\\fontname}}
@d etex_convert_base=5 {base for \eTeX's command codes}
@d eTeX_revision_code=etex_convert_base {command code for \.{\\eTeXrevision}}
-
-@d XeTeX_revision_code=6
-@d XeTeX_variation_name_code=7
-@d XeTeX_feature_name_code=8
-@d XeTeX_selector_name_code=9
-@d XeTeX_glyph_name_code=10
-
-@d left_margin_kern_code=11
-@d right_margin_kern_code=12
-
-@d XeTeX_Uchar_code = 13
-@d XeTeX_Ucharcat_code = 14
-
-@d etex_convert_codes=XeTeX_Ucharcat_code+1 {end of \eTeX's command codes}
-@d job_name_code=etex_convert_codes {command code for \.{\\jobname}}
+@d etex_convert_codes=etex_convert_base+1 {end of \eTeX's command codes}
+@d expanded_code=etex_convert_codes {command code for \.{\\expanded}}
+@d pdftex_first_expand_code = expanded_code + 1 {base for \pdfTeX's command codes}
+@d left_margin_kern_code = pdftex_first_expand_code + 9 {command code for \.{\\leftmarginkern}}
+@d right_margin_kern_code = pdftex_first_expand_code + 10 {command code for \.{\\rightmarginkern}}
+@d pdf_strcmp_code = pdftex_first_expand_code + 11 {command code for \.{\\strcmp}}
+@d pdf_creation_date_code = pdftex_first_expand_code + 15 {command code for \.{\\creationdate}}
+@d pdf_file_mod_date_code = pdftex_first_expand_code + 16 {command code for \.{\\filemoddate}}
+@d pdf_file_size_code = pdftex_first_expand_code + 17 {command code for \.{\\filesize}}
+@d pdf_mdfive_sum_code = pdftex_first_expand_code + 18 {command code for \.{\\mdfivesum}}
+@d pdf_file_dump_code = pdftex_first_expand_code + 19 {command code for \.{\\filedump}}
+@d uniform_deviate_code = pdftex_first_expand_code + 22 {command code for \.{\\uniformdeviate}}
+@d normal_deviate_code = pdftex_first_expand_code + 23 {command code for \.{\\normaldeviate}}
+@d pdftex_convert_codes = pdftex_first_expand_code + 26 {end of \pdfTeX's command codes}
+@d XeTeX_first_expand_code = pdftex_convert_codes {base for \XeTeX's command codes}
+@d XeTeX_revision_code = XeTeX_first_expand_code + 0 {command code for \.{\\XeTeXrevision}}
+@d XeTeX_variation_name_code = XeTeX_first_expand_code + 1 {command code for \.{\\XeTeXvariationname}}
+@d XeTeX_feature_name_code = XeTeX_first_expand_code + 2 {command code for \.{\\XeTeXfeaturename}}
+@d XeTeX_selector_name_code = XeTeX_first_expand_code + 3 {command code for \.{\\XeTeXselectornamename}}
+@d XeTeX_glyph_name_code = XeTeX_first_expand_code + 4 {command code for \.{\\XeTeXglyphname}}
+@d XeTeX_Uchar_code = XeTeX_first_expand_code + 5 {command code for \.{\\Uchar}}
+@d XeTeX_Ucharcat_code = XeTeX_first_expand_code + 6 {command code for \.{\\Ucharcat}}
+@d XeTeX_convert_codes = XeTeX_first_expand_code + 7 {end of \XeTeX's command codes}
+@d job_name_code=XeTeX_convert_codes {command code for \.{\\jobname}}
@<Put each...@>=
primitive("number",convert,number_code);@/
@@ -10597,12 +10978,35 @@ primitive("meaning",convert,meaning_code);@/
@!@:meaning_}{\.{\\meaning} primitive@>
primitive("fontname",convert,font_name_code);@/
@!@:font_name_}{\.{\\fontname} primitive@>
-primitive("jobname",convert,job_name_code);@/
-@!@:job_name_}{\.{\\jobname} primitive@>
+@#
+@#
+primitive("expanded",convert,expanded_code);@/
+@!@:expanded_}{\.{\\expanded} primitive@>
+@#
primitive("leftmarginkern",convert,left_margin_kern_code);@/
@!@:left_margin_kern_}{\.{\\leftmarginkern} primitive@>
primitive("rightmarginkern",convert,right_margin_kern_code);@/
@!@:right_margin_kern_}{\.{\\rightmarginkern} primitive@>
+primitive("creationdate",convert,pdf_creation_date_code);@/
+@!@:pdf_creation_date_}{\.{\\creationdate} primitive@>
+primitive("filemoddate",convert,pdf_file_mod_date_code);@/
+@!@:pdf_file_mod_date_}{\.{\\filemoddate} primitive@>
+primitive("filesize",convert,pdf_file_size_code);@/
+@!@:pdf_file_size_}{\.{\\filesize} primitive@>
+primitive("mdfivesum",convert,pdf_mdfive_sum_code);@/
+@!@:pdf_mdfive_sum_}{\.{\\mdfivesum} primitive@>
+primitive("filedump",convert,pdf_file_dump_code);@/
+@!@:pdf_file_dump_}{\.{\\filedump} primitive@>
+primitive("strcmp",convert,pdf_strcmp_code);@/
+@!@:pdf_strcmp_}{\.{\\strcmp} primitive@>
+primitive("uniformdeviate",convert,uniform_deviate_code);@/
+@!@:uniform_deviate_}{\.{\\uniformdeviate} primitive@>
+primitive("normaldeviate",convert,normal_deviate_code);@/
+@!@:normal_deviate_}{\.{\\normaldeviate} primitive@>
+
+@#
+primitive("jobname",convert,job_name_code);@/
+@!@:job_name_}{\.{\\jobname} primitive@>
primitive("Uchar",convert,XeTeX_Uchar_code);@/
@!@:XeTeX_Uchar_}{\.{\\Uchar} primitive@>
@@ -10616,10 +11020,18 @@ convert: case chr_code of
string_code: print_esc("string");
meaning_code: print_esc("meaning");
font_name_code: print_esc("fontname");
- pdf_strcmp_code: print_esc("strcmp");
- pdf_mdfive_sum_code: print_esc("mdfivesum");
+ eTeX_revision_code: print_esc("eTeXrevision");
+ expanded_code: print_esc("expanded");
left_margin_kern_code: print_esc("leftmarginkern");
right_margin_kern_code: print_esc("rightmarginkern");
+ pdf_creation_date_code: print_esc("creationdate");
+ pdf_file_mod_date_code: print_esc("filemoddate");
+ pdf_file_size_code: print_esc("filesize");
+ pdf_mdfive_sum_code: print_esc("mdfivesum");
+ pdf_file_dump_code: print_esc("filedump");
+ pdf_strcmp_code: print_esc("strcmp");
+ uniform_deviate_code: print_esc("uniformdeviate");
+ normal_deviate_code: print_esc("normaldeviate");
@/@<Cases of |convert| for |print_cmd_chr|@>@/
othercases print_esc("jobname")
endcases;
@@ -10641,6 +11053,7 @@ var old_setting:0..max_selector; {holds |selector| setting}
@!boolvar: boolean; {temp boolean}
@!s: str_number;
@!u: str_number;
+@!j: integer;
@!c:small_number; {desired type of conversion}
@!save_scanner_status:small_number; {|scanner_status| upon entry}
@!b:pool_pointer; {base of temporary string}
@@ -10658,7 +11071,7 @@ selector:=old_setting; link(garbage):=str_toks_cat(b,cat); ins_list(link(temp_he
end;
@ Not all catcode values are allowed by \.{\\Ucharcat}:
-@d illegal_Ucharcat_catcode(#)==(#<left_brace)or(#>other_char)or(#=out_param)or(#=ignore)
+@d illegal_Ucharcat_catcode(#)==(#<left_brace)or(#>active_char)or(#=out_param)or(#=ignore)
@<Scan the argument for command |c|@>=
case c of
@@ -10667,6 +11080,197 @@ string_code, meaning_code: begin save_scanner_status:=scanner_status;
scanner_status:=normal; get_token; scanner_status:=save_scanner_status;
end;
font_name_code: scan_font_ident;
+eTeX_revision_code: do_nothing;
+expanded_code:
+ begin
+ save_scanner_status := scanner_status;
+ save_warning_index := warning_index;
+ save_def_ref := def_ref;
+ save_cur_string;
+ scan_pdf_ext_toks;
+ warning_index := save_warning_index;
+ scanner_status := save_scanner_status;
+ ins_list(link(def_ref));
+ def_ref := save_def_ref;
+ restore_cur_string;
+ return;
+ end;
+left_margin_kern_code, right_margin_kern_code: begin
+ scan_register_num;
+ fetch_box(p);
+ if (p = null) or (type(p) <> hlist_node) then
+ pdf_error("marginkern", "a non-empty hbox expected")
+end;
+pdf_creation_date_code:
+ begin
+ b := pool_ptr;
+ getcreationdate;
+ link(garbage) := str_toks(b);
+ ins_list(link(temp_head));
+ return;
+ end;
+pdf_file_mod_date_code:
+ begin
+ save_scanner_status := scanner_status;
+ save_warning_index := warning_index;
+ save_def_ref := def_ref;
+ save_cur_string;
+ scan_pdf_ext_toks;
+
+ if selector = new_string then
+ pdf_error("tokens", "tokens_to_string() called while selector = new_string");
+ old_setting:=selector; selector:=new_string;
+ show_token_list(link(def_ref),null,pool_size-pool_ptr);
+ selector:=old_setting;
+ s:=make_string;
+
+ delete_token_ref(def_ref);
+ def_ref := save_def_ref;
+ warning_index := save_warning_index;
+ scanner_status := save_scanner_status;
+ b := pool_ptr;
+ getfilemoddate(s);
+ link(garbage) := str_toks(b);
+
+ if flushable(s) then
+ flush_string;
+
+ ins_list(link(temp_head));
+ restore_cur_string;
+ return;
+ end;
+pdf_file_size_code:
+ begin
+ save_scanner_status := scanner_status;
+ save_warning_index := warning_index;
+ save_def_ref := def_ref;
+ save_cur_string;
+ scan_pdf_ext_toks;
+
+ if selector = new_string then
+ pdf_error("tokens", "tokens_to_string() called while selector = new_string");
+ old_setting:=selector; selector:=new_string;
+ show_token_list(link(def_ref),null,pool_size-pool_ptr);
+ selector:=old_setting;
+ s:=make_string;
+
+ delete_token_ref(def_ref);
+ def_ref := save_def_ref;
+ warning_index := save_warning_index;
+ scanner_status := save_scanner_status;
+ b := pool_ptr;
+ getfilesize(s);
+ link(garbage) := str_toks(b);
+
+ if flushable(s) then
+ flush_string;
+
+ ins_list(link(temp_head));
+ restore_cur_string;
+ return;
+ end;
+pdf_mdfive_sum_code:
+ begin
+ save_scanner_status := scanner_status;
+ save_warning_index := warning_index;
+ save_def_ref := def_ref;
+ save_cur_string;
+ boolvar := scan_keyword("file");
+ scan_pdf_ext_toks;
+
+ if selector = new_string then
+ pdf_error("tokens", "tokens_to_string() called while selector = new_string");
+ old_setting:=selector; selector:=new_string;
+ show_token_list(link(def_ref),null,pool_size-pool_ptr);
+ selector:=old_setting;
+ s:=make_string;
+
+ delete_token_ref(def_ref);
+ def_ref := save_def_ref;
+ warning_index := save_warning_index;
+ scanner_status := save_scanner_status;
+ b := pool_ptr;
+ getmd5sum(s, boolvar);
+ link(garbage) := str_toks(b);
+
+ if flushable(s) then
+ flush_string;
+
+ ins_list(link(temp_head));
+ restore_cur_string;
+ return;
+ end;
+pdf_file_dump_code:
+ begin
+ save_scanner_status := scanner_status;
+ save_warning_index := warning_index;
+ save_def_ref := def_ref;
+ save_cur_string;
+ {scan offset}
+ cur_val := 0;
+ if (scan_keyword("offset")) then begin
+ scan_int;
+ if (cur_val < 0) then begin
+ print_err("Bad file offset");
+@.Bad file offset@>
+ help2("A file offset must be between 0 and 2^{31}-1,")@/
+ ("I changed this one to zero.");
+ int_error(cur_val);
+ cur_val := 0;
+ end;
+ end;
+ i := cur_val;
+ {scan length}
+ cur_val := 0;
+ if (scan_keyword("length")) then begin
+ scan_int;
+ if (cur_val < 0) then begin
+ print_err("Bad dump length");
+@.Bad dump length@>
+ help2("A dump length must be between 0 and 2^{31}-1,")@/
+ ("I changed this one to zero.");
+ int_error(cur_val);
+ cur_val := 0;
+ end;
+ end;
+ j := cur_val;
+ {scan file name}
+ scan_pdf_ext_toks;
+
+ if selector = new_string then
+ pdf_error("tokens", "tokens_to_string() called while selector = new_string");
+ old_setting:=selector; selector:=new_string;
+ show_token_list(link(def_ref),null,pool_size-pool_ptr);
+ selector:=old_setting;
+ s:=make_string;
+
+ delete_token_ref(def_ref);
+ def_ref := save_def_ref;
+ warning_index := save_warning_index;
+ scanner_status := save_scanner_status;
+ b := pool_ptr;
+ getfiledump(s, i, j);
+ link(garbage) := str_toks(b);
+
+ if flushable(s) then
+ flush_string;
+
+ ins_list(link(temp_head));
+ restore_cur_string;
+ return;
+ end;
+pdf_strcmp_code:
+ begin
+ save_scanner_status:=scanner_status;
+ save_warning_index:=warning_index;
+ save_def_ref:=def_ref;
+ save_cur_string;
+ compare_strings;
+ def_ref:=save_def_ref;
+ warning_index:=save_warning_index;
+ scanner_status:=save_scanner_status;
+ restore_cur_string;
+ end;
XeTeX_Uchar_code: scan_usv_num;
XeTeX_Ucharcat_code:
begin
@@ -10676,7 +11280,7 @@ XeTeX_Ucharcat_code:
if illegal_Ucharcat_catcode(cur_val) then
begin print_err("Invalid code ("); print_int(cur_val);
@.Invalid code@>
- print("), should be in the ranges 1..4, 6..8, 10..12");
+ print("), should be in the ranges 1..4, 6..8, 10..13");
help1("I'm going to use 12 instead of that illegal code value.");@/
error; cat:=12;
end else
@@ -10685,6 +11289,8 @@ XeTeX_Ucharcat_code:
end;
@/@<Cases of `Scan the argument for command |c|'@>@/
job_name_code: if job_name=0 then open_log_file;
+uniform_deviate_code: scan_int;
+normal_deviate_code: do_nothing;
end {there are no other cases}
@ @<Print the result of command |c|@>=
@@ -10710,6 +11316,37 @@ font_name_code: begin
print("pt");
end;
end;
+eTeX_revision_code: print(eTeX_revision);
+left_margin_kern_code: begin
+ p:=list_ptr(p);
+ while (p <> null) and
+ (cp_skipable(p) or
+ ((not is_char_node(p)) and (type(p) = glue_node) and (subtype(p) = left_skip_code + 1)))
+ do
+ p:=link(p);
+ if (p <> null) and (not is_char_node(p)) and (type(p) = margin_kern_node) and (subtype(p) = left_side) then
+ print_scaled(width(p))
+ else
+ print("0");
+ print("pt");
+end;
+right_margin_kern_code: begin
+ q:=list_ptr(p);
+ p:=prev_rightmost(q, null);
+ while (p <> null) and
+ (cp_skipable(p) or
+ ((not is_char_node(p)) and (type(p) = glue_node) and (subtype(p) = right_skip_code + 1)))
+ do
+ p:=prev_rightmost(q, p);
+ if (p <> null) and (not is_char_node(p)) and (type(p) = margin_kern_node) and (subtype(p) = right_side) then
+ print_scaled(width(p))
+ else
+ print("0");
+ print("pt");
+end;
+pdf_strcmp_code: print_int(cur_val);
+uniform_deviate_code: print_int(unif_rand(cur_val));
+normal_deviate_code: print_int(norm_rand);
XeTeX_Uchar_code,
XeTeX_Ucharcat_code: print_char(cur_val);
@/@<Cases of `Print the result of command |c|'@>@/
@@ -14630,6 +15267,12 @@ while font_ptr>font_base do
decr(font_ptr);
end
+@* \[32b] \pdfTeX\ output low-level subroutines (equivalents)
+
+@<Glob...@>=
+@!epochseconds: integer;
+@!microseconds: integer;
+
@* \[33] Packaging.
We're essentially done with the parts of \TeX\ that are concerned with
the input (|get_next|) and the output (|ship_out|). So it's time to
@@ -28667,6 +29310,8 @@ if eTeX_ex then wterm_ln('entering extended mode');
if end_line_char_inactive then decr(limit)
else buffer[limit]:=end_line_char;
fix_date_and_time;@/
+random_seed :=(microseconds*1000)+(epochseconds mod 1000000);@/
+init_randoms(random_seed);@/
@<Compute the magic offset@>;
@<Initialize the print |selector|...@>;
if (loc<limit)and(cat_code(buffer[loc])<>escape) then start_input;
@@ -28831,7 +29476,9 @@ stays the same.
@d set_language_code=5 {command modifier for \.{\\setlanguage}}
@d pdftex_first_extension_code = 6
-@d pdf_save_pos_node == pdftex_first_extension_code + 0
+@d pdf_save_pos_node == pdftex_first_extension_code + 15
+@d reset_timer_code == pdftex_first_extension_code + 25
+@d set_random_seed_code == pdftex_first_extension_code + 27
@d pic_file_code=41 { command modifier for \.{\\XeTeXpicfile}, skipping codes pdfTeX might use }
@d pdf_file_code=42 { command modifier for \.{\\XeTeXpdffile} }
@@ -28854,6 +29501,10 @@ primitive("immediate",extension,immediate_code);@/
@!@:immediate_}{\.{\\immediate} primitive@>
primitive("setlanguage",extension,set_language_code);@/
@!@:set_language_}{\.{\\setlanguage} primitive@>
+primitive("resettimer",extension,reset_timer_code);@/
+@!@:reset_timer_}{\.{\\resettimer} primitive@>
+primitive("setrandomseed",extension,set_random_seed_code);@/
+@!@:set_random_seed_code}{\.{\\setrandomseed} primitive@>
@ The \.{\\XeTeXpicfile} and \.{\\XeTeXpdffile} primitives are only defined in extended mode.
@@ -28886,13 +29537,15 @@ extension: case chr_code of
special_node:print_esc("special");
immediate_code:print_esc("immediate");
set_language_code:print_esc("setlanguage");
+ pdf_save_pos_node: print_esc("pdfsavepos");
+ reset_timer_code: print_esc("resettimer");
+ set_random_seed_code: print_esc("setrandomseed");
pic_file_code:print_esc("XeTeXpicfile");
pdf_file_code:print_esc("XeTeXpdffile");
glyph_code:print_esc("XeTeXglyph");
XeTeX_linebreak_locale_extension_code:print_esc("XeTeXlinebreaklocale");
XeTeX_input_encoding_extension_code:print_esc("XeTeXinputencoding");
XeTeX_default_encoding_extension_code:print_esc("XeTeXdefaultencoding");
- pdf_save_pos_node: print_esc("pdfsavepos");
othercases print("[unknown extension!]")
endcases;
@@ -28908,20 +29561,21 @@ procedure do_extension;
var i,@!j,@!k:integer; {all-purpose integers}
@!p,@!q,@!r:pointer; {all-purpose pointers}
begin case cur_chr of
-open_node:@<Implement \.{\\openout}@>;
-write_node:@<Implement \.{\\write}@>;
-close_node:@<Implement \.{\\closeout}@>;
-special_node:@<Implement \.{\\special}@>;
-immediate_code:@<Implement \.{\\immediate}@>;
-set_language_code:@<Implement \.{\\setlanguage}@>;
-pic_file_code:@<Implement \.{\\XeTeXpicfile}@>;
-pdf_file_code:@<Implement \.{\\XeTeXpdffile}@>;
-glyph_code:@<Implement \.{\\XeTeXglyph}@>;
-XeTeX_input_encoding_extension_code:@<Implement \.{\\XeTeXinputencoding}@>;
-XeTeX_default_encoding_extension_code:@<Implement \.{\\XeTeXdefaultencoding}@>;
-XeTeX_linebreak_locale_extension_code:@<Implement \.{\\XeTeXlinebreaklocale}@>;
-
-pdf_save_pos_node: @<Implement \.{\\pdfsavepos}@>;
+ open_node:@<Implement \.{\\openout}@>;
+ write_node:@<Implement \.{\\write}@>;
+ close_node:@<Implement \.{\\closeout}@>;
+ special_node:@<Implement \.{\\special}@>;
+ immediate_code:@<Implement \.{\\immediate}@>;
+ set_language_code:@<Implement \.{\\setlanguage}@>;
+ pdf_save_pos_node: @<Implement \.{\\pdfsavepos}@>;
+ reset_timer_code: @<Implement \.{\\resettimer}@>;
+ set_random_seed_code: @<Implement \.{\\setrandomseed}@>;
+ pic_file_code:@<Implement \.{\\XeTeXpicfile}@>;
+ pdf_file_code:@<Implement \.{\\XeTeXpdffile}@>;
+ glyph_code:@<Implement \.{\\XeTeXglyph}@>;
+ XeTeX_input_encoding_extension_code:@<Implement \.{\\XeTeXinputencoding}@>;
+ XeTeX_default_encoding_extension_code:@<Implement \.{\\XeTeXdefaultencoding}@>;
+ XeTeX_linebreak_locale_extension_code:@<Implement \.{\\XeTeXlinebreaklocale}@>;
othercases confusion("ext1")
@:this can't happen ext1}{\quad ext1@>
endcases;
@@ -28981,6 +29635,7 @@ end
@ @d call_func(#) == begin if # <> 0 then do_nothing end
@d flushable(#) == (# = str_ptr - 1)
+@d max_integer == @"7FFFFFFF {$2^{31}-1$}
@p procedure flush_str(s: str_number); {flush a string if possible}
begin
@@ -29044,6 +29699,38 @@ done:
cur_val_level:=int_val;
end;
+@ @<Declare procedures that need to be declared forward for \pdfTeX@>=
+function get_microinterval:integer;
+var s,@!m:integer; {seconds and microseconds}
+begin
+ seconds_and_micros(s,m);
+ if (s-epochseconds)>32767 then
+ get_microinterval := max_integer
+ else if (microseconds>m) then
+ get_microinterval := ((s-1-epochseconds)*65536)+ (((m+1000000-microseconds)/100)*65536)/10000
+ else
+ get_microinterval := ((s-epochseconds)*65536) + (((m-microseconds)/100)*65536)/10000;
+end;
+
+@ @<Set initial values of key variables@>=
+ seconds_and_micros(epochseconds,microseconds);
+ init_start_time;
+
+@ Negative random seed values are silently converted to positive ones
+
+@<Implement \.{\\setrandomseed}@>=
+begin
+ scan_int;
+ if cur_val<0 then negate(cur_val);
+ random_seed := cur_val;
+ init_randoms(random_seed);
+end
+
+@ @<Implement \.{\\resettimer}@>=
+begin
+ seconds_and_micros(epochseconds,microseconds);
+end
+
@ Each new type of node that appears in our data structure must be capable
of being displayed, copied, destroyed, and so on. The routines that we
need for write-oriented whatsits are somewhat like those for mark nodes;
@@ -29096,6 +29783,7 @@ language_node:begin print_esc("setlanguage");
print_int(what_lhm(p)); print_char(",");
print_int(what_rhm(p)); print_char(")");
end;
+pdf_save_pos_node: print_esc("pdfsavepos");
native_word_node, native_word_node_AT:begin print_esc(font_id_text(native_font(p)));
print_char(" ");
print_native_word(p);
@@ -29112,7 +29800,6 @@ pic_node,pdf_node: begin
print_visible_char(pic_path_byte(p, i));
print("""");
end;
-pdf_save_pos_node: print_esc("pdfsavepos");
othercases print("whatsit?")
endcases
@@ -29998,12 +30685,6 @@ primitive("XeTeXfonttype", last_item, XeTeX_font_type_code);
primitive("XeTeXfirstfontchar", last_item, XeTeX_first_char_code);
primitive("XeTeXlastfontchar", last_item, XeTeX_last_char_code);
-primitive("pdflastxpos",last_item,pdf_last_x_pos_code);
-primitive("pdflastypos",last_item,pdf_last_y_pos_code);
-primitive("strcmp",convert,pdf_strcmp_code);
-primitive("mdfivesum",convert,pdf_mdfive_sum_code);
-primitive("shellescape",last_item,pdf_shell_escape_code);
-
primitive("XeTeXpdfpagecount",last_item,XeTeX_pdf_page_count_code);
@ @<Cases of |last_item| for |print_cmd_chr|@>=
@@ -30045,9 +30726,6 @@ XeTeX_font_type_code: print_esc("XeTeXfonttype");
XeTeX_first_char_code: print_esc("XeTeXfirstfontchar");
XeTeX_last_char_code: print_esc("XeTeXlastfontchar");
- pdf_last_x_pos_code: print_esc("pdflastxpos");
- pdf_last_y_pos_code: print_esc("pdflastypos");
-
XeTeX_pdf_page_count_code: print_esc("XeTeXpdfpagecount");
@ @<Cases for fetching an integer value@>=
@@ -30313,7 +30991,6 @@ XeTeX_glyph_bounds_code:
end;
@ @<Cases of |convert| for |print_cmd_chr|@>=
-eTeX_revision_code: print_esc("eTeXrevision");
XeTeX_revision_code: print_esc("XeTeXrevision");
XeTeX_variation_name_code: print_esc("XeTeXvariationname");
@@ -30325,52 +31002,6 @@ XeTeX_Uchar_code: print_esc("Uchar");
XeTeX_Ucharcat_code: print_esc("Ucharcat");
@ @<Cases of `Scan the argument for command |c|'@>=
-eTeX_revision_code: do_nothing;
-pdf_strcmp_code:
- begin
- save_scanner_status:=scanner_status;
- save_warning_index:=warning_index;
- save_def_ref:=def_ref;
- save_cur_string;
- compare_strings;
- def_ref:=save_def_ref;
- warning_index:=save_warning_index;
- scanner_status:=save_scanner_status;
- restore_cur_string;
- end;
-
-pdf_mdfive_sum_code:
- begin
- save_scanner_status := scanner_status;
- save_warning_index := warning_index;
- save_def_ref := def_ref;
- save_cur_string;
- boolvar := scan_keyword("file");
- scan_pdf_ext_toks;
-
- if selector = new_string then
- pdf_error("tokens", "tokens_to_string() called while selector = new_string");
- old_setting:=selector; selector:=new_string;
- show_token_list(link(def_ref),null,pool_size-pool_ptr);
- selector:=old_setting;
- s:=make_string;
-
- delete_token_ref(def_ref);
- def_ref := save_def_ref;
- warning_index := save_warning_index;
- scanner_status := save_scanner_status;
- b := pool_ptr;
- getmd5sum(s, boolvar);
- link(garbage) := str_toks(b);
-
- if flushable(s) then
- flush_string;
-
- ins_list(link(temp_head));
- restore_cur_string;
- return;
- end;
-
XeTeX_revision_code: do_nothing;
XeTeX_variation_name_code:
@@ -30409,16 +31040,7 @@ XeTeX_glyph_name_code:
not_native_font_error(convert, c, fnt);
end;
-left_margin_kern_code, right_margin_kern_code: begin
- scan_register_num;
- fetch_box(p);
- if (p = null) or (type(p) <> hlist_node) then
- pdf_error("marginkern", "a non-empty hbox expected")
-end;
-
@ @<Cases of `Print the result of command |c|'@>=
-eTeX_revision_code: print(eTeX_revision);
-pdf_strcmp_code: print_int(cur_val);
XeTeX_revision_code: print(XeTeX_revision);
XeTeX_variation_name_code:
@@ -30435,35 +31057,6 @@ XeTeX_selector_name_code:
XeTeX_glyph_name_code:
if is_native_font(fnt) then print_glyph_name(fnt, arg1);
-left_margin_kern_code: begin
- p:=list_ptr(p);
- while (p <> null) and
- (cp_skipable(p) or
- ((not is_char_node(p)) and (type(p) = glue_node) and (subtype(p) = left_skip_code + 1)))
- do
- p:=link(p);
- if (p <> null) and (not is_char_node(p)) and (type(p) = margin_kern_node) and (subtype(p) = left_side) then
- print_scaled(width(p))
- else
- print("0");
- print("pt");
-end;
-
-right_margin_kern_code: begin
- q:=list_ptr(p);
- p:=prev_rightmost(q, null);
- while (p <> null) and
- (cp_skipable(p) or
- ((not is_char_node(p)) and (type(p) = glue_node) and (subtype(p) = right_skip_code + 1)))
- do
- p:=prev_rightmost(q, p);
- if (p <> null) and (not is_char_node(p)) and (type(p) = margin_kern_node) and (subtype(p) = right_side) then
- print_scaled(width(p))
- else
- print("0");
- print("pt");
-end;
-
@ @d eTeX_ex==(eTeX_mode=1) {is this extended mode?}
@<Glob...@>=