|
|
This is the official pdfsync page.
This is the patch for embedding pdfsync into pdftex
Index: trunk/source/src/texk/web2c/lib/texmfmp.c
===================================================================
--- trunk/source/src/texk/web2c/lib/texmfmp.c (revision 347)
+++ trunk/source/src/texk/web2c/lib/texmfmp.c (working copy)
@@ -191,6 +191,10 @@
kpse_record_input = recorder_record_input;
kpse_record_output = recorder_record_output;
+#if defined (pdfTeX) || defined(__synchronize___)
+ synchronizeoption = 0;// means no synchronization
+#endif
+
#if defined(pdfTeX)
ptexbanner = BANNER;
#endif
@@ -895,6 +899,9 @@
{ "no-shell-escape", 0, &shellenabledp, -1 },
{ "debug-format", 0, &debugformatfile, 1 },
{ "src-specials", 2, 0, 0 },
+#if defined(pdfTeX) || defined(__synchronize__)
+ { "synchronize", 1, 0, 0 },//Synchronization: just like interaction above
+#endif
#endif /* TeX */
#if defined (TeX) || defined (MF) || defined (MP)
{ "file-line-error-style", 0, &filelineerrorstylep, 1 },
@@ -1073,6 +1080,10 @@
} else if (ARGUMENT_IS ("help")) {
usagehelp (PROGRAM_HELP, BUG_ADDRESS);
+#if defined (pdfTeX) || defined(__synchronize___)
+ } else if (ARGUMENT_IS ("synchronize")) {
+ synchronizeoption = (int) strtoul(optarg, NULL, 0);// Synchronization: catching the command line option as an unsigned long
+ #endif
} else if (ARGUMENT_IS ("version")) {
char *versions;
#if defined (pdfTeX) || defined(XeTeX)
Index: trunk/source/src/texk/web2c/pdftexdir/utils.c
===================================================================
--- trunk/source/src/texk/web2c/pdftexdir/utils.c (revision 347)
+++ trunk/source/src/texk/web2c/pdftexdir/utils.c (working copy)
@@ -441,6 +441,7 @@
sfd_free();
glyph_unicode_free();
zip_free();
+ sync_terminate();
}
/* Converts any string given in in in an allowed PDF string which can be
Index: trunk/source/src/texk/web2c/pdftexdir/Makefile.in
===================================================================
--- trunk/source/src/texk/web2c/pdftexdir/Makefile.in (revision 347)
+++ trunk/source/src/texk/web2c/pdftexdir/Makefile.in (working copy)
@@ -47,7 +47,7 @@
OBJS = epdf.o mapfile.o utils.o vfpacket.o pkin.o \
writefont.o writet1.o writet3.o writezip.o writeenc.o writettf.o \
writejpg.o writejbig2.o writepng.o writeimg.o pdftoepdf.o avl.o \
-avlstuff.o subfont.o tounicode.o pdflib.o
+avlstuff.o subfont.o tounicode.o pdflib.o synchronize.o
all: libpdf.a makecpool
Index: trunk/source/src/texk/web2c/pdftexdir/synchronize.c
===================================================================
--- trunk/source/src/texk/web2c/pdftexdir/synchronize.c (revision 0)
+++ trunk/source/src/texk/web2c/pdftexdir/synchronize.c (revision 0)
@@ -0,0 +1,425 @@
+/*
+Copyright (c) 2008 Jerome.Laurens AT u-bourgogne.fr
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with pdfTeX; if not, write to the Free Software Foundation, Inc., 51
+Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "ptexlib.h"
+
+/* Synchronization is explained in greater details in synchronization.readme/synchronize+Frames.pdf.*/
+
+#if defined(pdfTeX) || defined(__synchronize__)
+
+#define SYNC_DEBUG 0
+
+// Here are all the local variables
+
+static struct
+{
+ FILE *file; // the foo.sync I/O identifier
+ char *name; // the real "foo.sync" name
+ char *root_name; // in general jobname.tex
+ // next concern the last sync record encountered
+ halfword p; // the last synchronized node, must be set before the recorder
+ void (*recorder)(halfword p); // the recorder of the node above
+ integer h, v; // its coordinates
+ integer offset; // the offset of the origin / the topleft of the page in both directions
+} sync_ctxt = {NULL,NULL,NULL,0,NULL,0,0,0};
+
+#define sync_version 1
+
+// the macros defined below do the same job than their almost eponym counterparts of *tex.web,
+// the memory access is sometimes more direct because *tex.web won't share its own constants
+// the main purpose is to maintain very few hook points into *tex.web
+// in order both to ensure portability and not modifying to much the original code.
+// see texmfmem.h and *tex.web for details,
+// the sync_ prefix prevents name conflicts, it is some kind of namespace
+#warning These structures MUST be kept in synchronization with the main program
+// synchronizeoption is a global integer variable defined in *tex.web
+// it is set to 1 by texmfmp.c if the command line has the '-synchronize' option.
+#define sync_options synchronizeoption
+#define sync_disabled_mask 0x80000000
+// if the sync_disabled_mask bit of sync_options is set, the synchronization is definitely disabled
+#define sync_ignore_cli_mask 0x40000000
+// if the sync_ignore_cli_mask bit of sync_options is set, the option given from the command line is ignored
+
+// glue code: really define the main memory
+#define mem zmem
+// glue code: synchronizeoffset is a global integer variable defined in *tex.web
+// it is set to the offset where the primitive \synchronize reads and writes its value.
+#define sync_is_enabled zeqtb[synchronizeoffset].cint
+// if there were a mean to share the value of synchronize_code between pdftex.web and this file, it would be great
+
+// sync_dot_open ensures that the foo.sync file is open.
+// In case of problem, it disables definitely synchronization
+// Now all the synchronization info is in one page.
+// It is possible to split this info into as many different files as sheets plus the 1
+// but the overall benefits are not so clear.
+static FILE * sync_dot_open(void)
+{
+ #if SYNC_DEBUG
+ fprintf(stdout,"\nwarning: Synchronize DEBUG:sync_dot_open\n");
+ fprintf(stdout,"\nwarning: sync_is_enabled=%i\n",sync_is_enabled);
+ fprintf(stdout,"\nwarning: sync_options=%i\n",sync_options);
+ #endif
+ if(sync_options & sync_disabled_mask)
+ return 0;// synchronization is definitely disabled: do nothing
+
+ #if SYNC_DEBUG
+ fprintf(stdout,"\nwarning: Synchronize DEBUG:sync_dot_open 1\n");
+ #endif
+ if (!sync_ctxt.file)
+ {
+ // this is the first time we are asked to open the file
+ // this part of code is executed only once:
+ // either sync_ctxt.file is nonnegative or synchronization is definitely disabled.
+ static char *suffix = ".sync";
+ char *s = makecstring(jobname);
+ char *j = xstrdup(s);
+ check_buf(strlen(s) + strlen(suffix) + 1, MAX_CSTRING_LEN);
+ strcat(s, suffix);
+ sync_ctxt.name = xstrdup(s);
+ sync_ctxt.file = xfopen(sync_ctxt.name, FOPEN_W_MODE);
+ #if SYNC_DEBUG
+ fprintf(stdout,"\nwarning: Synchronize DEBUG:sync_dot_open 2\n");
+ #endif
+ if(sync_ctxt.file)
+ {
+ // print the preamble
+ fprintf(sync_ctxt.file,"synchronize\nversion:1\n",sync_version);
+ if(sync_ctxt.root_name)
+ {
+ fprintf(sync_ctxt.file,"i:1:%s\n",sync_ctxt.root_name);
+ xfree(sync_ctxt.root_name);
+ sync_ctxt.root_name = NULL;
+ }
+ #if SYNC_DEBUG
+ fprintf(stdout,"\nwarning: Synchronize DEBUG:sync_dot_open 3-a\n");
+ #endif
+ }
+ else
+ {
+ sync_options = sync_disabled_mask;
+ // no .sync file available, disable synchronization
+ #if SYNC_DEBUG
+ fprintf(stdout,"\nwarning: Synchronize DEBUG:sync_dot_open 3-b\n");
+ #endif
+ }
+ xfree(j);
+ }
+ return sync_ctxt.file;
+}
+
+// Each time TeX opens a file, it sends syncstartinput.
+// A new synchronization tag is created and stored in the synctag_field of the TeX current input context.
+// each node will record this tag instead of the file name
+// syncstartinput writes the mapping synctag <-> file name to the .sync file
+// a client will read the .sync file and retrieve this mapping
+// it will be able to open the correct file just knowing its tag.
+// If the same file is read more than once, it might be associated to different tags.
+// Viewers should be prepared to handle this situation.
+// No two different files will have the same positive tag.
+// It is not advisable to definitely store the file names here.
+// If the file names ever have to be stored, it should definitely be done at the TeX level
+// such that other components of the program can use it.
+void syncstartinput(void)
+{
+ static unsigned int synctag_counter = 0;
+
+ #if SYNC_DEBUG
+ fprintf(stdout,"\nwarning: Synchronize DEBUG:syncstartinput %i\n",synctag_counter);
+ fprintf(stdout,"\nwarning: sync_is_enabled=%i\n",sync_is_enabled);
+ fprintf(stdout,"\nwarning: sync_options=%i\n",sync_options);
+ fprintf(stdout,"\nwarning: sync_disabled_mask=%i\n",sync_disabled_mask);
+ #endif
+
+ if((sync_options & sync_disabled_mask) != 0)
+ {
+ // this is where we disable synchronization -synchronization=-1
+ return;
+ }
+ // synctag_counter is a counter uniquely identifying the file actually open
+ // each time tex opens a new file, syncstartinput will increment this counter
+ if(~synctag_counter>0)
+ {
+ ++synctag_counter;
+ }
+ else
+ {
+ // we have reached the limit, subsequent files will be softly ignored
+ // this makes a lot of files... even in 32 bits
+ curinput.synctagfield = 0;
+ return;
+ }
+
+ if(0 == (sync_options & sync_ignore_cli_mask))
+ {
+ // the command line options are not ignored
+ sync_is_enabled = MAX(sync_options,sync_is_enabled);
+ sync_options |= sync_ignore_cli_mask;
+ // the command line options will be ignored from now on.
+ // every subsequent call of syncstartinput won't get there
+ // sync_options is now the list of option flags
+ }
+
+ curinput.synctagfield = synctag_counter;// -> *TeX.web
+ if(synctag_counter==1)
+ {
+ // this is the first file TeX opens, in general \jobname.tex
+ // we do not know yet if synchronization will ever be enabled
+ // so we have to store the file name, because we will need it later
+ // This is certainly not necessary dur to \jobname
+ sync_ctxt.root_name = xstrdup(makecstring(curinput.namefield));
+ return;
+ }
+ if(sync_ctxt.file || ((sync_is_enabled && sync_dot_open()) != 0))
+ {
+ fprintf(sync_ctxt.file,"i:%u:%s\n",curinput.synctagfield,makecstring(curinput.namefield));
+ }
+ return;
+}
+
+// All the sync... functions below have the smallest set of parameters.
+// It appears to be either the address of a node, or nothing at all.
+// Using zmem, which is the place where all the nodes are stored, one can retrieve every information about a node.
+// The other information is obtained through global variables.
+//
+
+// Recording the "s:..." line
+void syncsheet(integer pdf_output)
+{
+ #if SYNC_DEBUG
+ fprintf(stdout,"\nSynchronize DEBUG:syncsheet\n");
+ #endif
+ if((sync_options & sync_disabled_mask) != 0)
+ {
+ return;
+ }
+ // update the offsets, depending on the output mode
+ sync_ctxt.offset = pdf_output?0:4736286;
+ if((sync_ctxt.file != 0) || ((sync_is_enabled && sync_dot_open()) != 0)) // tries to open the .sync, useful if synchronization was enabled from the source file and not from the CLI
+ {
+ if((totalpages == 0) && (pdf_output == 0))
+ fprintf(sync_ctxt.file,">:no pdf\n");
+ fprintf(sync_ctxt.file,"s:%u\n",(long int)totalpages+1);
+ }
+}
+
+#define UNIT / 8192
+// UNIT is the scale. TeX coordinates are very accurate and client won't need that in a first step.
+// 1.0 <-> 2^16 = 65536
+// The TeX unit is sp (scaled point) or pt/65536 which means that the scale factor to retrieve a bp unit (a postscript) is
+// 72/72.27/65536 = 1/4096/16.06 = 1/8192/8.03
+// Here we use 1/8192 as scale factor, then we can limit ourselves to integers.
+// IMPORTANT: We can say that the natural unit of .sync files is 8192 sp.
+// To retrieve the proper bp unit, we'll have to divide by 8.03.
+// To reduce rounding errors, we'll certainly have to add 0.5 for non negative integers and ±0.5 for negative integers.
+// This is mainly to gain speed and size
+// maybe a binary file would be more appropriate in that respect,
+// but I guess that some clients like auctex would not like it very much.
+// we cannot use "<<13" instead of "/8192" because the integers are signed and we do not want the sign bit to be propagated.
+// the origin of the coordinates is at the top left point of the page
+// for pdftex, it is straightforward, but for dvi, we'll have to add the 1in offset in both directions.
+
+#warning This should be in sync with the eponym declarations in *tex.web
+#define box_node_size 9
+#define sync_width(NODE) mem[NODE+1].cint
+#define sync_depth(NODE) mem[NODE+2].cint
+#define sync_height(NODE) mem[NODE+3].cint
+#define sync_tag(NODE) mem[NODE+box_node_size-2].cint
+#define sync_line(NODE) mem[NODE+box_node_size-1].cint
+
+// When an hlist ships out, it can contain many different kern nodes with exactly the same sync tag and line.
+// To reduce the size of the .sync file, we only display ker node sync info when either the sync tag or the line changes
+// Also, we try ro reduce the distance between the chosen nodes in order to improve accuracy.
+// It means that we display information for consecutive nodes, as far as possible.
+// See details in the implementation of the functions below.
+
+#define SYNC_IGNORE(NODE) ((sync_options & sync_disabled_mask) != 0) \
+ || (sync_is_enabled == 0) \
+ || (sync_ctxt.file == 0)
+
+// Recording a "h:..." line
+void sync_hlist_recorder(halfword p)
+{
+ fprintf(sync_ctxt.file,"h:%u:%u(%i,%i,%i,%i)%i\n",
+ sync_tag(p), sync_line(p),
+ (curh + sync_ctxt.offset) UNIT, (curv+sync_depth(p) + sync_ctxt.offset) UNIT,
+ sync_width(p) UNIT, (sync_height(p)+sync_depth(p)) UNIT,
+ sync_depth(p) UNIT);
+}
+// This message is sent when an hlist will be shipped out.
+// p is the address of the hlist
+// We assume that p is really an hlist node!
+void synchlist(halfword p)
+{
+ #if SYNC_DEBUG
+ fprintf(stdout,"\nSynchronize DEBUG:synchlist\n");
+ #endif
+ if(SYNC_IGNORE(p))
+ return;
+ sync_ctxt.p = 0;// reset
+ sync_ctxt.recorder = NULL;// reset
+ sync_hlist_recorder(p);
+}
+
+// Recording a "e" line ending an hbox
+// this message is sent whenever an hlist has been shipped out
+// it is used to close the hlist nesting level
+void synctsilh(halfword p)
+{
+ #if SYNC_DEBUG
+ fprintf(stdout,"\nSynchronize DEBUG:synctsilh\n");
+ #endif
+ if(SYNC_IGNORE(p))
+ return;
+ // is there a pending info to be recorded
+ if(sync_ctxt.recorder)
+ {
+ // sync_ctxt node is set and must be recorded as last node
+ (*sync_ctxt.recorder)(sync_ctxt.p);
+ sync_ctxt.p = 0;// force next node to be recorded!
+ sync_ctxt.recorder = NULL;
+ }
+ fputs("e\n", sync_ctxt.file);
+}
+
+#undef SYNC_IGNORE
+#define SYNC_IGNORE(NODE) ((sync_options & sync_disabled_mask) != 0) \
+ || (sync_is_enabled == 0) \
+ || (sync_tag(NODE)<=0) \
+ || (sync_line(NODE)<=0) \
+ || (sync_ctxt.file == 0)
+#undef sync_tag
+#undef sync_line
+// glue code: these only work with nodes of size medium_node_size
+#define medium_node_size 4
+#define sync_tag(NODE) mem[NODE+medium_node_size-2].cint
+#define sync_line(NODE) mem[NODE+medium_node_size-1].cint
+
+#define SYNC_CONTEXT_DID_CHANGE ((sync_ctxt.p == 0)\
+ || (sync_tag(p) != sync_tag(sync_ctxt.p))\
+ || (sync_line(p) != sync_line(sync_ctxt.p)))
+// Recording a "$:..." line
+void sync_math_recorder(halfword p)
+{
+ fprintf(sync_ctxt.file,"$:%u:%u(%i,%i)\n",
+ sync_tag(p), sync_line(p),
+ (sync_ctxt.h + sync_ctxt.offset) UNIT, (sync_ctxt.v + sync_ctxt.offset) UNIT);
+}
+// glue code this message is sent whenever an inline math node will ship out
+void syncmath(halfword p)
+{
+ #if SYNC_DEBUG
+ fprintf(stdout,"\nSynchronize DEBUG:syncmath\n");
+ #endif
+ if(SYNC_IGNORE(p))
+ return;
+ if((sync_ctxt.recorder!=NULL) && SYNC_CONTEXT_DID_CHANGE)// the sync context did change
+ (*sync_ctxt.recorder)(sync_ctxt.p);
+ sync_ctxt.h = curh;
+ sync_ctxt.v = curv;
+ sync_ctxt.p = p;
+ sync_ctxt.recorder = NULL;// no need to record once more
+ sync_math_recorder(p);// always record
+}
+
+// Recording a "g:..." line
+void sync_glue_recorder(halfword p)
+{
+ fprintf(sync_ctxt.file,"g:%u:%u(%i,%i)\n",
+ sync_tag(p), sync_line(p),
+ (sync_ctxt.h + sync_ctxt.offset) UNIT, (sync_ctxt.v + sync_ctxt.offset) UNIT);
+}
+// this message is sent whenever a glue node ships out
+void syncglue(halfword p)
+{
+ #if SYNC_DEBUG
+ fprintf(stdout,"\nSynchronize DEBUG:syncglue\n");
+ #endif
+ if(SYNC_IGNORE(p))
+ return;
+ if(SYNC_CONTEXT_DID_CHANGE)// the sync context has changed
+ {
+ if(sync_ctxt.recorder!=NULL) // was not recorded
+ (*sync_ctxt.recorder)(sync_ctxt.p);
+ sync_ctxt.h = curh;
+ sync_ctxt.v = curv;
+ sync_ctxt.p = p;
+ sync_ctxt.recorder = NULL;
+ sync_glue_recorder(p);// always record
+ }
+ else
+ {
+ // just update the geometry and type (for future improvements)
+ sync_ctxt.h = curh;
+ sync_ctxt.v = curv;
+ sync_ctxt.p = p;
+ sync_ctxt.recorder = &sync_glue_recorder;
+ }
+}
+
+// Recording a "k:..." line
+void sync_kern_recorder(halfword p)
+{
+ fprintf(sync_ctxt.file,"k:%u:%u(%i,%i)\n",
+ sync_tag(p), sync_line(p),
+ (sync_ctxt.h + sync_ctxt.offset) UNIT, (sync_ctxt.v + sync_ctxt.offset) UNIT);
+}
+// this message is sent whenever a kern node or a glue node ships out
+void synckern(halfword p)
+{
+ #if SYNC_DEBUG
+ fprintf(stdout,"\nSynchronize DEBUG:synckern\n");
+ #endif
+ if(SYNC_IGNORE(p))
+ return;
+ if(SYNC_CONTEXT_DID_CHANGE)// the sync context has changed
+ {
+ if(sync_ctxt.recorder!=NULL) // was not recorded
+ (*sync_ctxt.recorder)(sync_ctxt.p);
+ sync_ctxt.h = curh;
+ sync_ctxt.v = curv;
+ sync_ctxt.p = p;
+ sync_ctxt.recorder = NULL;
+ sync_kern_recorder(p);
+ }
+ else
+ {
+ // just update the geometry and type (for future improvements)
+ sync_ctxt.h = curh;
+ sync_ctxt.v = curv;
+ sync_ctxt.p = p;
+ sync_ctxt.recorder = &sync_kern_recorder;
+ }
+}
+
+// Free all memory used and close the file
+// sent by utils.c
+void sync_terminate(void)
+{
+ #if SYNC_DEBUG
+ fprintf(stdout,"\nSynchronize DEBUG:sync_terminate\n");
+ #endif
+ if (sync_ctxt.file != NULL) {
+ xfclose(sync_ctxt.file, sync_ctxt.name);
+ xfree(sync_ctxt.name);
+ }
+ xfree(sync_ctxt.root_name);
+}
+
+#endif
Property changes on: trunk/source/src/texk/web2c/pdftexdir/synchronize.c
___________________________________________________________________
Name: svn:eol-style
+ native
Index: trunk/source/src/texk/web2c/pdftexdir/pdftex.defines
===================================================================
--- trunk/source/src/texk/web2c/pdftexdir/pdftex.defines (revision 347)
+++ trunk/source/src/texk/web2c/pdftexdir/pdftex.defines (working copy)
@@ -151,5 +151,14 @@
{ loadpdftexpool }
@define function loadpoolstrings();
+{ functions from synchronize.c }
+@define procedure syncstartinput;
+@define procedure syncsheet();
+@define procedure synchlist();
+@define procedure synctsilh();
+@define procedure syncmath();
+@define procedure synckern();
+@define procedure syncglue();
+
{ end of pdftex.defines }
{ vim: set syntax=web : }
Index: trunk/source/src/texk/web2c/pdftexdir/pdftex.web
===================================================================
--- trunk/source/src/texk/web2c/pdftexdir/pdftex.web (revision 347)
+++ trunk/source/src/texk/web2c/pdftexdir/pdftex.web (working copy)
@@ -3188,6 +3188,11 @@
found: link(r):=null; {this node is now nonempty}
@!stat var_used:=var_used+s; {maintain usage statistics}
tats@;@/
+if s>3 then {Synchronization: default initialization of the two last words to the current sync info}
+begin
+ mem[r+s-2].int := synctag;
+ mem[r+s-1].int := line;
+end;
get_node:=r;
exit:end;
@@ -3367,7 +3372,7 @@
|fil|, |fill|, or |filll|). The |subtype| field is not used.
@d hlist_node=0 {|type| of hlist nodes}
-@d box_node_size=7 {number of words to allocate for a box node}
+@d box_node_size=7+2 {number of words to allocate for a box node, Synchronization hook: +2 integers for synctag and line}
@d width_offset=1 {position of |width| field in a box node}
@d depth_offset=2 {position of |depth| field in a box node}
@d height_offset=3 {position of |height| field in a box node}
@@ -3453,6 +3458,7 @@
@d mark_node=4 {|type| of a mark node}
@d small_node_size=2 {number of words to allocate for most node types}
+@d medium_node_size=small_node_size+2 {Synchonization: +2 integers for sync info in math_node, kern_node and glue_node}
@d mark_ptr(#)==link(#+1) {head of the token list for a mark}
@d mark_class(#)==info(#+1) {the mark class}
@@ -3585,8 +3591,9 @@
@p function new_math(@!w:scaled;@!s:small_number):pointer;
var p:pointer; {the new node}
-begin p:=get_node(small_node_size); type(p):=math_node;
-subtype(p):=s; width(p):=w; new_math:=p;
+begin p:=get_node(medium_node_size); type(p):=math_node; {Synchronization: proper size}
+subtype(p):=s; width(p):=w;
+new_math:=p;
end;
@ \TeX\ makes use of the fact that |hlist_node|, |vlist_node|,
@@ -3681,7 +3688,7 @@
@p function new_param_glue(@!n:small_number):pointer;
var p:pointer; {the new node}
@!q:pointer; {the glue specification}
-begin p:=get_node(small_node_size); type(p):=glue_node; subtype(p):=n+1;
+begin p:=get_node(medium_node_size); type(p):=glue_node; subtype(p):=n+1; {Synchronization: proper size}
leader_ptr(p):=null;@/
q:=@@t@>;
glue_ptr(p):=q; incr(glue_ref_count(q));
@@ -3693,7 +3700,7 @@
@p function new_glue(@!q:pointer):pointer;
var p:pointer; {the new node}
-begin p:=get_node(small_node_size); type(p):=glue_node; subtype(p):=normal;
+begin p:=get_node(medium_node_size); type(p):=glue_node; subtype(p):=normal; {Synchronization: proper size}
leader_ptr(p):=null; glue_ptr(p):=q; incr(glue_ref_count(q));
new_glue:=p;
end;
@@ -3760,7 +3767,7 @@
@p function new_kern(@!w:scaled):pointer;
var p:pointer; {the new node}
-begin p:=get_node(small_node_size); type(p):=kern_node;
+begin p:=get_node(medium_node_size); type(p):=kern_node; { Synchronization: proper size}
subtype(p):=normal;
width(p):=w;
new_kern:=p;
@@ -4508,9 +4515,15 @@
end;
whatsit_node: @;
glue_node: begin fast_delete_glue_ref(glue_ptr(p));
- if leader_ptr(p)<>null then flush_node_list(leader_ptr(p));
+ if leader_ptr(p)<>null then flush_node_list(leader_ptr(p));
+ free_node(p, medium_node_size); {Synchronization: proper size}
+ goto done;
end;
- kern_node,math_node,penalty_node: do_nothing;
+ kern_node,math_node:begin
+ free_node(p, medium_node_size); {Synchronization: proper size}
+ goto done;
+ end;
+ penalty_node: do_nothing;
margin_kern_node: begin
free_avail(margin_char(p));
free_node(p, margin_kern_node_size);
@@ -4583,6 +4596,7 @@
@ @=
case type(p) of
hlist_node,vlist_node,unset_node: begin r:=get_node(box_node_size);
+ mem[r+7].int:=mem[p+7].int;mem[r+8].int:=mem[p+8].int; {Synchronization: copy the sync words}
mem[r+6]:=mem[p+6]; mem[r+5]:=mem[p+5]; {copy the last two words}
list_ptr(r):=copy_node_list(list_ptr(p)); {this affects |mem[r+5]|}
words:=5;
@@ -4596,10 +4610,16 @@
end;
whatsit_node:@;
-glue_node: begin r:=get_node(small_node_size); add_glue_ref(glue_ptr(p));
+glue_node: begin r:=get_node(medium_node_size); add_glue_ref(glue_ptr(p)); {Synchronization: proper size}
+ mem[r+2].int:=mem[p+2].int;mem[r+3].int:=mem[p+3].int; {Synchronization: copy the sync words}
glue_ptr(r):=glue_ptr(p); leader_ptr(r):=copy_node_list(leader_ptr(p));
end;
-kern_node,math_node,penalty_node: begin r:=get_node(small_node_size);
+kern_node,math_node:
+begin
+ words:=medium_node_size; {Synchronization: 2 integers more}
+ r:=get_node(words);
+end;
+penalty_node: begin r:=get_node(small_node_size);
words:=small_node_size;
end;
margin_kern_node: begin
@@ -5675,7 +5695,10 @@
@d eTeX_state_code=etex_int_base+10 {\eTeX\ state variables}
@d etex_int_pars=eTeX_state_code+eTeX_states {total number of \eTeX's integer parameters}
@#
-@d int_pars=etex_int_pars {total number of integer parameters}
+@d synchronize_code=etex_int_pars {Synchronization: generate extra info for source/output synchronization? the 2 next lines are modified too}
+@d sync_int_pars=synchronize_code+1 {total number of \TeX's integer parameters}
+@#
+@d int_pars=sync_int_pars {total number of integer parameters}
@d count_base=int_base+int_pars {256 user \.{\\count} registers}
@d del_code_base=count_base+256 {256 delimiter code mappings}
@d dimen_base=del_code_base+256 {beginning of region 6}
@@ -5768,6 +5791,8 @@
@d pdf_draftmode == int_par(pdf_draftmode_code)
@d pdf_inclusion_copy_font == int_par(pdf_inclusion_copy_font_code)
@#
+@d synchronize == int_par(synchronize_code) {Synchronization}
+@#
@d tracing_assigns==int_par(tracing_assigns_code)
@d tracing_groups==int_par(tracing_groups_code)
@d tracing_ifs==int_par(tracing_ifs_code)
@@ -5871,6 +5896,7 @@
pdf_gen_tounicode_code: print_esc("pdfgentounicode");
pdf_draftmode_code: print_esc("pdfdraftmode");
pdf_inclusion_copy_font_code: print_esc("pdfinclusioncopyfonts");
+synchronize_code: print_esc("synchronize"); {Synchronization}
@/@@/
othercases print("[unknown integer parameter!]")
endcases;
@@ -6051,6 +6077,14 @@
primitive("pdfinclusioncopyfonts",assign_int,int_base+pdf_inclusion_copy_font_code);@/
@!@:pdf_inclusion_copy_font_}{\.{\\pdfinclusioncopyfonts} primitive@>
+@ @=
+primitive("synchronize",assign_int,int_base+synchronize_code);@/{Synchronization}
+@!@:synchronize_}{\.{\\synchronize} primitive@>
+
+@ @=
+@!synchronizeoption:integer; {Synchronization glue: set from the command line, see below}
+@!synchronizeoffset:integer; {Synchronization glue: holds the true value of synchronize_code}
+
@ @=
assign_int: if chr_code=
@@ -7546,6 +7581,7 @@
@d start==cur_input.start_field {starting position in |buffer|}
@d limit==cur_input.limit_field {end of current line in |buffer|}
@d name==cur_input.name_field {name of the current file}
+@d synctag==cur_input.synctag_field {Synchronization:tag of the current file}
@ Let's look more closely now at the control variables
(|state|,~|index|,~|start|,~|loc|,~|limit|,~|name|),
@@ -8164,6 +8200,7 @@
grp_stack[index]:=cur_boundary; if_stack[index]:=cond_ptr;
line_stack[index]:=line; start:=first; state:=mid_line;
name:=0; {|terminal_input| is now |true|}
+synctag:=0; {Synchronization}
end;
@ Conversely, the variables must be downdated when such a level of input
@@ -12400,6 +12437,8 @@
if name=str_ptr-1 then {we can conserve string pool space now}
begin flush_string; name:=cur_name;
end;
+synchronizeoffset:=int_base+synchronize_code; {Synchronization glue code}
+sync_start_input; {Synchronization hook: Take the appropriate actions before reading a new file}
@;
end;
@@ -14438,8 +14477,10 @@
prev_p:=this_box+list_offset;
@;
left_edge:=cur_h;
+sync_hlist(this_box); {Synchronization hook: write info, descend one level}
while p<>null do @
|