Hi Heiko,
Taco Hoekwater wrote:
Heiko Oberdiek wrote:
Hello,
AFAIK, an expression with \primitive will become expandable
if and only if the primitive is expandable.
(pdfTeX: \pdfprimitive)
I am thinking about this bug.
Please look at the attached patch against pdftex trunk. I have a similar
patch in luatex now, and it works ok for your example file as well as
some other stuff I tried.
The patch makes scan_something_internal (for \number and the other
convert commands) and scan_int (other places where numbers are needed)
skip over the unexpandable version of \primitive so that it looks at
the next token, and if that token is a primitive, it uses this instead.
If the next token is not a primitive at all, then a frozen \relax is
inserted, as that is probably the best thing to do. I have considered
reporting an error, but that is too unpredictable for my taste (and a
"Missing number" error will likely follow anyway).
Please check against any other tests you may have.
Best wishes,
Taco
Index: src/texk/web2c/pdftexdir/pdftex.web
===================================================================
--- src/texk/web2c/pdftexdir/pdftex.web (revision 546)
+++ src/texk/web2c/pdftexdir/pdftex.web (working copy)
@@ -8926,6 +8926,31 @@
end;
end
+@ This block deals with unexpandable \.{\\primitive} appearing at a spot where
+an integer or an internal values should have been found. It fetches the
+next token then resets |cur_cmd|, |cur_cs|, and |cur_tok|, based on the
+primitive value of that token. No expansion takes place, because the
+next token may be all sorts of things. This could trigger further
+expansion creating new errors.
+
+@=
+begin
+get_token;
+cur_cs := prim_lookup(text(cur_cs));
+if cur_cs<>undefined_primitive then begin
+ cur_cmd := prim_eq_type(cur_cs);
+ cur_chr := prim_equiv(cur_cs);
+ cur_tok := (cur_cmd*@'400)+cur_chr;
+ end
+else begin
+ cur_cmd := relax;
+ cur_chr := 0;
+ cur_tok := cs_token_flag+frozen_relax;
+ cur_cs := frozen_relax;
+ end;
+goto restart;
+end
+
@ @=
begin print_err("Undefined control sequence");
@.Undefined control sequence@>
@@ -9571,13 +9596,13 @@
@p procedure scan_something_internal(@!level:small_number;@!negative:boolean);
{fetch an internal parameter}
-label exit;
+label exit, restart;
var m:halfword; {|chr_code| part of the operand token}
n, k: integer; {accumulators}
@!q:halfword; {general purpose index}
@!i:four_quarters; {character info}
@!p:0..nest_size; {index into |nest|}
-begin m:=cur_chr;
+begin restart: m:=cur_chr;
case cur_cmd of
def_code: @;
toks_register,assign_toks,def_family,set_font,def_font,letterspace_font,pdf_copy_font: @;
register: @;
last_item: @;
+ignore_spaces: {trap unexpandable primitives}
+ if cur_chr=1 then @;
othercases @
endcases;@/
while cur_val_level>level do @;
@@ -10082,7 +10109,7 @@
and that the decimal point has been backed up to be scanned again.
@p procedure scan_int; {sets |cur_val| to an integer}
-label done;
+label done, restart;
var negative:boolean; {should the answer be negated?}
@!m:integer; {|@t$2^{31}$@> div radix|, the threshold of danger}
@!d:small_number; {the digit just scanned}
@@ -10090,7 +10117,10 @@
@!OK_so_far:boolean; {has an error message been issued?}
begin radix:=0; OK_so_far:=true;@/
@;
+restart:
if cur_tok=alpha_token then @
+else if cur_tok=cs_token_flag+frozen_primitive then
+ @
else if (cur_cmd>=min_internal)and(cur_cmd<=max_internal) then
scan_something_internal(int_val,false)
else @;