3 % Copyright
2009-2010 Taco Hoekwater
<taco@@luatex.org
>
5 % This file is part of LuaTeX.
7 % LuaTeX is free software
; you can redistribute it and
/or modify it under
8 % the terms of the GNU General Public License as published by the Free
9 % Software Foundation
; either version
2 of the License
, or
(at your
10 % option
) any later version.
12 % LuaTeX is distributed in the hope that it will be useful
, but WITHOUT
13 % ANY WARRANTY
; without even the implied warranty of MERCHANTABILITY or
14 % FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 % License for more details.
17 % You should have received a copy of the GNU General Public License along
18 % with LuaTeX
; if not
, see
<http
://www.gnu.org
/licenses
/>.
27 #define mode cur_list.mode_field
28 #define tail cur_list.tail_field
29 #define head cur_list.head_field
30 #define prev_graf cur_list.pg_field
31 #define dir_save cur_list.dirs_field
33 #define tracing_nesting int_par
(tracing_nesting_code
)
34 #define tracing_online int_par
(tracing_online_code
)
35 #define box
(A
) eqtb
[box_base
+(A
)].hh.rh
36 #define global_defs int_par
(global_defs_code
)
37 #define cat_code_table int_par
(cat_code_table_code
)
38 #define toks
(A
) equiv
(toks_base
+(A
))
40 @ The program above includes a bunch of ``hooks'' that allow further
41 capabilities to be added without upsetting \TeX's basic structure.
42 Most of these hooks are concerned with ``whatsit'' nodes
, which are
43 intended to be used for special purposes
; whenever a new extension to
44 \TeX\ involves a new kind of whatsit node
, a corresponding change needs
45 to be made to the routines below that deal with such nodes
,
46 but it will usually be unnecessary to make many changes to the
47 other parts of this program.
49 In order to demonstrate how extensions can be made
, we shall treat
50 `\.
{\\write
}'
, `\.
{\\openout
}'
, `\.
{\\closeout
}'
, `\.
{\\immediate
}'
,
51 and `\.
{\\special
}' as if they were extensions.
52 These commands are actually primitives of \TeX
, and they should
53 appear in all implementations of the system
; but let's try to imagine
54 that they aren't. Then the program below illustrates how a person
57 Sometimes
, of course
, an extension will require changes to \TeX\ itself
;
58 no system of hooks could be complete enough for all conceivable extensions.
59 The features associated with `\.
{\\write
}' are almost all confined to the
60 following paragraphs
, but there are small parts of the |print_ln| and
61 |print_char| procedures that were introduced specifically to \.
{\\write
}
62 characters. Furthermore one of the token lists recognized by the scanner
63 is a |write_text|
; and there are a few other miscellaneous places where we
64 have already provided for some aspect of \.
{\\write
}. The goal of a \TeX\
65 extender should be to minimize alterations to the standard parts of the
66 program
, and to avoid them completely if possible. He or she should also
67 be quite sure that there's no easy way to accomplish the desired goals
68 with the standard features that \TeX\ already has. ``Think thrice before
69 extending
,'' because that may save a lot of work
, and it will also keep
70 incompatible extensions of \TeX\ from proliferating.
71 @^system dependencies@
>
72 @^extensions to \TeX@
>
74 First let's consider the format of whatsit nodes that are used to represent
75 the data associated with \.
{\\write
} and its relatives. Recall that a whatsit
76 has |type
=whatsit_node|
, and the |subtype| is supposed to distinguish
77 different kinds of whatsits. Each node occupies two or more words
; the
78 exact number is immaterial
, as long as it is readily determined from the
79 |subtype| or other data.
81 We shall introduce five |subtype| values here
, corresponding to the
82 control sequences \.
{\\openout
}, \.
{\\write
}, \.
{\\closeout
}, and \.
{\\special
}.
83 The second word of I
/O whatsits has a |write_stream| field
84 that identifies the write-stream number
(0 to
15, or
16 for out-of-range and
85 positive
, or
17 for out-of-range and negative
).
86 In the case of \.
{\\write
} and \.
{\\special
}, there is also a field that
87 points to the reference count of a token list that should be sent. In the
88 case of \.
{\\openout
}, we need three words and three auxiliary subfields
89 to hold the string numbers for name
, area
, and extension.
91 @ Extensions might introduce new command codes
; but it's best to use
92 |extension| with a modifier
, whenever possible
, so that |main_control|
95 @ The sixteen possible \.
{\\write
} streams are represented by the |write_file|
96 array. The |j|th file is open if and only if |write_open
[j
]=true|. The last
97 two streams are special
; |write_open
[16]| represents a stream number
98 greater than
15, while |write_open
[17]| represents a negative stream number
,
99 and both of these variables are always |false|.
102 alpha_file write_file
[last_file_selector
+1];
103 halfword write_file_mode
[last_file_selector
+1];
104 halfword write_file_translation
[last_file_selector
+1];
105 boolean write_open
[last_file_selector
+1];
111 @ The variable |write_loc| just introduced is used to provide an
112 appropriate error message in case of ``runaway'' write texts.
115 halfword write_loc
; /* |eqtb| address of \.
{\\write
} */
118 hh
: eventually i'll make \pdfextension a lua token parsed function
;
119 a complication is that sometimes token lists are delayed
122 @ When an |extension| command occurs in |main_control|
, in any mode
,
123 the |do_extension| routine is called.
126 int last_saved_image_index
;
127 int last_saved_image_pages
;
128 int last_saved_box_index
;
129 scaledpos last_position
= { 0, 0 };
131 static void do_extension_dvi
(int immediate
)
133 if
(scan_keyword
("literal")) {
134 new_whatsit
(special_node
);
135 write_stream
(tail
) = null
;
136 scan_toks
(false
, true
);
137 write_tokens
(tail
) = def_ref
;
139 tex_error
("unexpected use of \\dviextension",null
);
143 static void do_extension_pdf
(int immediate
)
147 if
(scan_keyword
("literal")) {
148 new_whatsit
(pdf_literal_node
);
149 if
(scan_keyword
("direct"))
150 set_pdf_literal_mode
(tail
, direct_always
);
151 else if
(scan_keyword
("page"))
152 set_pdf_literal_mode
(tail
, direct_page
);
154 set_pdf_literal_mode
(tail
, set_origin
);
155 scan_toks
(false
, true
);
156 set_pdf_literal_type
(tail
, normal
);
157 set_pdf_literal_data
(tail
, def_ref
);
158 } else if
(scan_keyword
("dest")) {
159 scan_pdfdest
(static_pdf
);
160 } else if
(scan_keyword
("annot")) {
161 scan_annot
(static_pdf
);
162 } else if
(scan_keyword
("save")) {
163 new_whatsit
(pdf_save_node
);
164 } else if
(scan_keyword
("restore")) {
165 new_whatsit
(pdf_restore_node
);
166 } else if
(scan_keyword
("setmatrix")) {
167 new_whatsit
(pdf_setmatrix_node
);
168 scan_toks
(false
, true
);
169 set_pdf_setmatrix_data
(tail
, def_ref
);
170 } else if
(scan_keyword
("obj")) {
171 scan_obj
(static_pdf
);
173 if
(obj_data_ptr
(static_pdf
, pdf_last_obj
) == 0) /* this object has not been initialized yet
*/
174 normal_error
("pdf backend","\\pdfextension obj 'reserveobjnum' cannot be used with \\immediate");
175 pdf_write_obj
(static_pdf
, pdf_last_obj
);
177 } else if
(scan_keyword
("refobj")) {
178 scan_refobj
(static_pdf
);
179 } else if
(scan_keyword
("colorstack")) {
181 if
(cur_val
>= colorstackused
()) {
182 print_err
("Unknown color stack number ");
185 ("Allocate and initialize a color stack with \\pdfextension colorstackinit.",
186 "I'll use default color stack 0 here.",
187 "Proceed, with fingers crossed.");
192 print_err
("Invalid negative color stack number");
193 help2
("I'll use default color stack 0 here.",
194 "Proceed, with fingers crossed.");
198 if
(scan_keyword
("set"))
200 else if
(scan_keyword
("push"))
202 else if
(scan_keyword
("pop"))
204 else if
(scan_keyword
("current"))
205 i
= colorstack_current
;
209 new_whatsit
(pdf_colorstack_node
);
210 set_pdf_colorstack_stack
(tail
, cur_val
);
211 set_pdf_colorstack_cmd
(tail
, i
);
212 set_pdf_colorstack_data
(tail
, null
);
213 if
(i
<= colorstack_data
) {
214 scan_toks
(false
, true
);
215 set_pdf_colorstack_data
(tail
, def_ref
);
218 print_err
("Color stack action is missing");
219 help3
("The expected actions for \\pdfextension colorstack:",
220 " set, push, pop, current",
221 "I'll ignore the color stack command.");
224 } else if
(scan_keyword
("startlink")) {
225 scan_startlink
(static_pdf
);
226 } else if
(scan_keyword
("endlink")) {
227 if
(abs
(mode
) == vmode
)
228 normal_error
("pdf backend", "\\pdfextension endlink cannot be used in vertical mode");
229 new_whatsit
(pdf_end_link_node
);
230 } else if
(scan_keyword
("startthread")) {
231 new_annot_whatsit
(pdf_start_thread_node
);
233 } else if
(scan_keyword
("endthread")) {
234 new_whatsit
(pdf_end_thread_node
);
235 } else if
(scan_keyword
("thread")) {
236 new_annot_whatsit
(pdf_thread_node
);
238 } else if
(scan_keyword
("outline")) {
239 scan_pdfoutline
(static_pdf
);
240 } else if
(scan_keyword
("glyphtounicode")) {
242 } else if
(scan_keyword
("catalog")) {
243 scan_pdfcatalog
(static_pdf
);
244 } else if
(scan_keyword
("fontattr")) {
246 The font attributes are simply initialized to zero now
, this is easier to deal with from C than an
247 empty \TeX
{} string
, and surely nobody will want to set font attr to a string containing a single zero
,
248 as that would be nonsensical in the PDF output.
253 normal_error
("pdf backend", "invalid font identifier");
254 scan_toks
(false
, true
);
255 set_pdf_font_attr
(i
, tokens_to_string
(def_ref
));
256 if
(str_length
(pdf_font_attr
(i
)) == 0) {
257 flush_str
((str_ptr
- 1)); /* from |tokens_to_string|
*/
258 set_pdf_font_attr
(i
, 0);
260 } else if
(scan_keyword
("mapfile")) {
261 scan_toks
(false
, true
);
263 delete_token_ref
(def_ref
);
264 } else if
(scan_keyword
("mapline")) {
265 scan_toks
(false
, true
);
267 delete_token_ref
(def_ref
);
268 } else if
(scan_keyword
("includechars")) {
269 pdf_include_chars
(static_pdf
);
270 } else if
(scan_keyword
("info")) {
271 scan_toks
(false
, true
);
272 pdf_info_toks
= concat_tokens
(pdf_info_toks
, def_ref
);
273 } else if
(scan_keyword
("names")) {
274 scan_toks
(false
, true
);
275 pdf_names_toks
= concat_tokens
(pdf_names_toks
, def_ref
);
276 } else if
(scan_keyword
("trailer")) {
277 scan_toks
(false
, true
);
278 pdf_trailer_toks
= concat_tokens
(pdf_trailer_toks
, def_ref
);
280 tex_error
("unexpected use of \\pdfextension",null
);
284 static void do_resource_dvi
(int immediate
, int code
)
288 static void do_resource_pdf
(int immediate
, int code
)
291 case use_box_resource_code
:
292 scan_pdfrefxform
(static_pdf
);
294 case use_image_resource_code
:
295 scan_pdfrefximage
(static_pdf
);
297 case save_box_resource_code
:
298 scan_pdfxform
(static_pdf
);
300 pdf_cur_form
= last_saved_box_index
;
301 ship_out
(static_pdf
, obj_xform_box
(static_pdf
, last_saved_box_index
), SHIPPING_FORM
);
304 case save_image_resource_code
:
305 fix_pdf_minorversion
(static_pdf
);
306 scan_pdfximage
(static_pdf
);
308 pdf_write_image
(static_pdf
, last_saved_image_index
);
318 To write a token list
, we must run it through \TeX's scanner
, expanding
319 macros and \.
{\\the
} and \.
{\\number
}, etc. This might cause runaways
,
320 if a delimited macro parameter isn't matched
, and runaways would be
321 extremely confusing since we are calling on \TeX's scanner in the middle
322 of a \.
{\\shipout
} command. Therefore we will put a dummy control sequence as
323 a ``stopper
,'' right after the token list. This control sequence is
324 artificially defined to be \.
{\\outer
}.
326 The presence of `\.
{\\immediate
}' causes the |do_extension| procedure
327 to descend to one level of recursion. Nothing happens unless \.
{\\immediate
}
328 is followed by `\.
{\\openout
}'
, `\.
{\\write
}'
, or `\.
{\\closeout
}'.
332 /* extensions are backend related
*/
334 @ The next subroutine uses |cur_chr| to decide what sort of whatsit is
335 involved
, and also inserts a |write_stream| number.
338 static void new_write_whatsit
(int w
, int check
)
340 new_whatsit
(cur_chr
);
342 /* so we check with open and close
*/
343 scan_limited_int
(last_file_selector
,NULL);
345 /* but we're tolerant with the rest
*/
349 else if
(cur_val
> last_file_selector
) {
350 cur_val
= term_and_log
;
353 write_stream
(tail
) = cur_val
;
356 void do_extension
(int immediate
)
358 halfword p
; /* all-purpose pointer
*/
359 if
(cur_cmd
== extension_cmd
) {
360 /* these have their own range starting at
0 */
364 new_write_whatsit
(open_node_size
,1);
365 scan_optional_equals
();
367 open_name
(tail
) = cur_name
;
368 open_area
(tail
) = cur_area
;
369 open_ext
(tail
) = cur_ext
;
371 out_what
(static_pdf
, tail
);
372 flush_node_list
(tail
);
379 When `\.
{\\write
12\
{...\
}}' appears
, we scan the token list `\.
{\
{...\
}}'
380 without expanding its macros
; the macros will be expanded later when this
381 token list is rescanned.
384 new_write_whatsit
(write_node_size
,0);
385 cur_cs
= write_stream
(tail
);
386 scan_toks
(false
, false
);
387 write_tokens
(tail
) = def_ref
;
389 out_what
(static_pdf
, tail
);
390 flush_node_list
(tail
);
397 new_write_whatsit
(close_node_size
,1);
398 write_tokens
(tail
) = null
;
400 out_what
(static_pdf
, tail
);
401 flush_node_list
(tail
);
408 When `\.
{\\special\
{...\
}}' appears
, we expand the macros in the token
409 list as in \.
{\\xdef
} and \.
{\\mark
}.
411 new_whatsit
(special_node
);
412 write_stream
(tail
) = null
;
413 p
= scan_toks
(false
, true
);
414 write_tokens
(tail
) = def_ref
;
420 case use_box_resource_code
:
421 case use_image_resource_code
:
422 case save_box_resource_code
:
423 case save_image_resource_code
:
424 switch
(get_o_mode
()) {
426 do_resource_dvi
(immediate
,cur_chr
);
429 do_resource_pdf
(immediate
,cur_chr
);
435 /* backend extensions have their own range starting at
32 */
436 case dvi_extension_code
:
437 if
(get_o_mode
() == OMODE_DVI
)
438 do_extension_dvi
(immediate
);
440 case pdf_extension_code
:
441 if
(get_o_mode
() == OMODE_PDF
)
442 do_extension_pdf
(immediate
);
449 confusion
("invalid extension");
454 /* no extension command
, quite certainly following \immediate
*/
459 @ Here is a subroutine that creates a whatsit node having a given |subtype|
460 and a given number of words. It initializes only the first word of the whatsit
,
461 and appends it to the current list.
464 void new_whatsit
(int s
)
466 halfword p
= new_node
(whatsit_node
, s
);
467 couple_nodes
(tail
, p
);
471 @ The final line of this routine is slightly subtle
; at least
, the author
472 didn't think about it until getting burnt
! There is a used-up token list
473 @^Knuth
, Donald Ervin@
>
474 on the stack
, namely the one that contained |end_write_token|.
(We
475 insert this artificial `\.
{\\endwrite
}' to prevent runaways
, as explained
476 above.
) If it were not removed
, and if there were numerous writes on a
477 single page
, the stack would overflow.
480 #define end_write_token cs_token_flag
+end_write
482 void expand_macros_in_tokenlist
(halfword p
)
485 pointer q
= get_avail
();
486 pointer r
= get_avail
();
487 token_info
(q
) = right_brace_token
+ '
}'
;
489 token_info
(r
) = end_write_token
;
490 begin_token_list
(q
, inserted
);
491 begin_token_list
(write_tokens
(p
), write_text
);
493 token_info
(q
) = left_brace_token
+ '
{'
;
494 begin_token_list
(q
, inserted
);
495 /* now we're ready to scan
496 `\.\
{$\langle\
,$token list$\
,\rangle$\.
{\
} \\endwrite
}'
*/
499 /* disable \.
{\\prevdepth
}, \.
{\\spacefactor
}, \.
{\\lastskip
}, \.
{\\prevgraf
} */
501 q
= scan_toks
(false
, true
); /* expand macros
, etc.
*/
503 if
(cur_tok
!= end_write_token
) {
504 /* Recover from an unbalanced write command
*/
505 const char
*hlp
[] = {
506 "On this page there's a \\write with fewer real {'s than }'s.",
507 "I can't handle that very well; good luck.", NULL
509 tex_error
("Unbalanced write command", hlp
);
512 } while
(cur_tok
!= end_write_token
);
515 end_token_list
(); /* conserve stack space
*/
518 void write_out
(halfword p
)
520 int old_setting
; /* holds print |selector|
*/
521 int j
; /* write stream number
*/
522 char
*s
, *ss
; /* line to be written
, as a C string
*/
525 expand_macros_in_tokenlist
(p
);
526 old_setting
= selector
;
530 } else if
((j
== term_only
) && (selector == term_and_log)) {
531 /* write to the terminal if file isn't open
*/
537 s
= tokenlist_to_cstring
(def_ref
, false
, NULL);
538 if
(selector
< no_print
) {
539 /* selector is a file
*/
540 callback_id
= callback_defined
(process_output_buffer_callback
);
541 if
(callback_id
> 0) {
542 /* fix up the output buffer using callbacks
*/
543 lua_retval
= run_callback
(callback_id
, "S->S", s
, &ss);
544 if
((lua_retval
== true
) && (ss != NULL)) {
554 selector
= old_setting
;
557 void finalize_write_files
(void
) {
559 for
(k
= 0; k
<= last_file_selector
; k
++) {
561 lua_a_close_out
(write_file
[k
]);
566 void initialize_write_files
(void
) {
568 for
(k
= 0; k
<= last_file_selector
; k
++) {
569 write_open
[k
] = false
;
573 void close_write_file
(int id
) {
574 if
(write_open
[id
]) {
575 lua_a_close_out
(write_file
[id
]);
576 write_open
[id
] = false
;
580 boolean open_write_file
(int id
, char
*fn
) {
581 if
(lua_a_open_out
(&(write_file[id]), fn, (id + 1))) {
582 write_open
[id
] = true
;
590 @ To implement primitives as \.
{\\pdfextension info
}, \.
{\\pdfextension catalog
} or
591 \.
{\\pdfextension names
} we need to concatenate tokens lists.
594 halfword concat_tokens
(halfword q
, halfword r
)
595 { /* concat |q| and |r| and returns the result tokens list
*/
600 while
(token_link
(p
) != null
)
602 set_token_link
(p
, token_link
(r
));
607 @ The \eTeX\ features available in extended mode are grouped into two
608 categories
: (1)~Some of them are permanently enabled and have no
609 semantic effect as long as none of the additional primitives are
610 executed.
(2)~The remaining \eTeX\ features are optional and can be
611 individually enabled and disabled. For each optional feature there is
612 an \eTeX\ state variable named \.
{\\...state
}; the feature is enabled
,
613 resp.\ disabled by assigning a positive
, resp.\ non-positive value to
616 @ In order to handle \.
{\\everyeof
} we need an array |eof_seen| of
620 boolean
*eof_seen
; /* has eof been seen?
*/
622 @ The |print_group| procedure prints the current level of grouping and
623 the name corresponding to |cur_group|.
626 void print_group
(boolean e
)
630 tprint
("bottom level");
634 case semi_simple_group
:
635 if
(cur_group
== semi_simple_group
)
640 case adjusted_hbox_group
:
641 if
(cur_group
== adjusted_hbox_group
)
653 if
(cur_group
== no_align_group
)
670 case math_choice_group
:
671 case math_shift_group
:
672 case math_left_group
:
674 if
(cur_group
== math_choice_group
)
676 else if
(cur_group
== math_shift_group
)
678 else if
(cur_group
== math_left_group
)
681 } /* there are no other cases
*/
682 tprint
(" group (level ");
683 print_int
(cur_level
);
685 if
(saved_value
(-1) != 0) { /* |saved_line|
*/
687 tprint
(" entered at line ");
690 print_int
(saved_value
(-1)); /* |saved_line|
*/
694 @ The |group_trace| procedure is called when a new level of grouping
695 begins
(|e
=false|
) or ends
(|e
=true|
) with |saved_value
(-1)| containing the
699 void group_trace
(boolean e
)
709 end_diagnostic
(false
);
712 @ A group entered
(or a conditional started
) in one file may end in a
713 different file. Such slight anomalies
, although perfectly legitimate
,
714 may cause errors that are difficult to locate. In order to be able to
715 give a warning message when such anomalies occur
, \eTeX\ uses the
716 |grp_stack| and |if_stack| arrays to record the initial |cur_boundary|
717 and |cond_ptr| values for each input file.
720 save_pointer
*grp_stack
; /* initial |cur_boundary|
*/
721 halfword
*if_stack
; /* initial |cond_ptr|
*/
723 @ When a group ends that was apparently entered in a different input
724 file
, the |group_warning| procedure is invoked in order to update the
725 |grp_stack|. If moreover \.
{\\tracingnesting
} is positive we want to
726 give a warning message. The situation is
, however
, somewhat complicated
727 by two facts
: (1)~There may be |grp_stack| elements without a
728 corresponding \.
{\\input
} file or \.
{\\scantokens
} pseudo file
(e.g.
,
729 error insertions from the terminal
); and
(2)~the relevant information is
730 recorded in the |name_field| of the |input_stack| only loosely
731 synchronized with the |in_open| variable indexing |grp_stack|.
734 void group_warning
(void
)
736 boolean w
= false
; /* do we need a warning?
*/
737 int i
= in_open
; /* index into |grp_stack|
*/
738 base_ptr
= input_ptr
;
739 input_stack
[base_ptr
] = cur_input
; /* store current state
*/
740 while
((grp_stack
[i
] == cur_boundary
) && (i > 0)) {
741 /* Set variable |w| to indicate if this case should be reported
*/
742 /* This code scans the input stack in order to determine the type of the
743 current input file.
*/
744 if
(tracing_nesting
> 0) {
745 while
((input_stack
[base_ptr
].state_field
== token_list
) ||
746 (input_stack
[base_ptr
].index_field
> i
))
748 if
(input_stack
[base_ptr
].name_field
> 17)
752 grp_stack
[i
] = save_value
(save_ptr
);
756 tprint_nl
("Warning: end of ");
758 tprint
(" of a different file");
760 if
(tracing_nesting
> 1)
762 if
(history
== spotless
)
763 history
= warning_issued
;
767 @ When a conditional ends that was apparently started in a different
768 input file
, the |if_warning| procedure is invoked in order to update the
769 |if_stack|. If moreover \.
{\\tracingnesting
} is positive we want to
770 give a warning message
(with the same complications as above
).
773 void if_warning
(void
)
775 boolean w
= false
; /* do we need a warning?
*/
777 base_ptr
= input_ptr
;
778 input_stack
[base_ptr
] = cur_input
; /* store current state
*/
779 while
(if_stack
[i
] == cond_ptr
) {
780 /* Set variable |w| to...
*/
781 if
(tracing_nesting
> 0) {
782 while
((input_stack
[base_ptr
].state_field
== token_list
) ||
783 (input_stack
[base_ptr
].index_field
> i
))
785 if
(input_stack
[base_ptr
].name_field
> 17)
789 if_stack
[i
] = vlink
(cond_ptr
);
793 tprint_nl
("Warning: end of ");
794 print_cmd_chr
(if_test_cmd
, cur_if
);
795 print_if_line
(if_line
);
796 tprint
(" of a different file");
798 if
(tracing_nesting
> 1)
800 if
(history
== spotless
)
801 history
= warning_issued
;
806 @ Conversely
, the |file_warning| procedure is invoked when a file ends
807 and some groups entered or conditionals started while reading from that
808 file are still incomplete.
811 void file_warning
(void
)
813 halfword p
= save_ptr
; /* saved value of |save_ptr| or |cond_ptr|
*/
814 int l
= cur_level
; /* saved value of |cur_level| or |if_limit|
*/
815 int c
= cur_group
; /* saved value of |cur_group| or |cur_if|
*/
816 int i
; /* saved value of |if_line|
*/
817 save_ptr
= cur_boundary
;
818 while
(grp_stack
[in_open
] != save_ptr
) {
820 tprint_nl
("Warning: end of file when ");
822 tprint
(" is incomplete");
823 cur_group
= save_level
(save_ptr
);
824 save_ptr
= save_value
(save_ptr
);
827 cur_level
= (quarterword
) l
;
828 cur_group
= (group_code
) c
; /* restore old values
*/
833 while
(if_stack
[in_open
] != cond_ptr
) {
834 tprint_nl
("Warning: end of file when ");
835 print_cmd_chr
(if_test_cmd
, cur_if
);
836 if
(if_limit
== fi_code
)
838 print_if_line
(if_line
);
839 tprint
(" is incomplete");
840 if_line
= if_line_field
(cond_ptr
);
841 cur_if
= if_limit_subtype
(cond_ptr
);
842 if_limit
= if_limit_type
(cond_ptr
);
843 cond_ptr
= vlink
(cond_ptr
);
848 if_line
= i
; /* restore old values
*/
850 if
(tracing_nesting
> 1)
852 if
(history
== spotless
)
853 history
= warning_issued
;
857 halfword last_line_fill
; /* the |par_fill_skip| glue node of the new paragraph
*/
859 @ The lua interface needs some extra functions. The functions
860 themselves are quite boring
, but they are handy because otherwise this
861 internal stuff has to be accessed from C directly
, where lots of the
862 defines are not available.
865 #define dimen
(A
) eqtb
[scaled_base
+(A
)].hh.rh
866 #define count
(A
) eqtb
[count_base
+(A
)].hh.rh
868 #define get_tex_dimen_register
(j
) dimen
(j
)
869 #define get_tex_skip_register
(j
) skip
(j
)
870 #define get_tex_mu_skip_register
(j
) mu_skip
(j
)
871 #define get_tex_count_register
(j
) count
(j
)
872 #define get_tex_attribute_register
(j
) attribute
(j
)
873 #define get_tex_box_register
(j
) box
(j
)
875 /* these can now be macros
(todo
) */
877 int get_tex_extension_count_register
(int i
)
879 return
(int
) int_par
(backend_int_base-int_base
+i
);
882 void set_tex_extension_count_register
(int i
, int d
)
884 int_par
(backend_int_base-int_base
+i
) = d
;
887 int get_tex_extension_dimen_register
(int i
)
889 return
(int
) dimen_par
(backend_dimen_base-dimen_base
+i
);
892 void set_tex_extension_dimen_register
(int i
, int d
)
894 dimen_par
(backend_dimen_base-dimen_base
+i
) = d
;
897 int get_tex_extension_toks_register
(int i
)
899 return equiv
(backend_toks_base
+i
);
902 int set_tex_dimen_register
(int j
, scaled v
)
904 int a
; /* return non-nil for error
*/
909 word_define
(j
+ scaled_base
, v
);
913 int set_tex_skip_register
(int j
, halfword v
)
915 int a
; /* return non-nil for error
*/
920 if
(type
(v
) != glue_spec_node
)
922 word_define
(j
+ skip_base
, v
);
926 int set_tex_mu_skip_register
(int j
, halfword v
)
928 int a
; /* return non-nil for error
*/
933 if
(type
(v
) != glue_spec_node
)
935 word_define
(j
+ mu_skip_base
, v
);
939 int set_tex_count_register
(int j
, scaled v
)
941 int a
; /* return non-nil for error
*/
946 word_define
(j
+ count_base
, v
);
950 int set_tex_box_register
(int j
, scaled v
)
952 int a
; /* return non-nil for error
*/
957 define
(j
+ box_base
, box_ref_cmd
, v
);
961 int set_tex_attribute_register
(int j
, scaled v
)
963 int a
; /* return non-nil for error
*/
968 if
(j
> max_used_attr
)
970 attr_list_cache
= cache_disabled
;
971 word_define
(j
+ attribute_base
, v
);
975 int get_tex_toks_register
(int j
)
977 str_number s
= get_nullstr
();
978 if
(toks
(j
) != null
) {
979 s
= tokens_to_string
(toks
(j
));
984 int set_tex_toks_register
(int j
, lstring s
)
987 halfword ref
= get_avail
();
989 set_token_ref_count
(ref
, 0);
990 set_token_link
(ref
, token_link
(temp_token_head
));
995 define
(j
+ toks_base
, call_cmd
, ref
);
999 int scan_tex_toks_register
(int j
, int c
, lstring s
)
1002 halfword ref
= get_avail
();
1003 (void
) str_scan_toks
(c
,s
);
1004 set_token_ref_count
(ref
, 0);
1005 set_token_link
(ref
, token_link
(temp_token_head
));
1006 if
(global_defs
> 0)
1010 define
(j
+ toks_base
, call_cmd
, ref
);
1014 scaled get_tex_box_width
(int j
)
1016 halfword q
= box
(j
);
1022 int set_tex_box_width
(int j
, scaled v
)
1024 halfword q
= box
(j
);
1031 scaled get_tex_box_height
(int j
)
1033 halfword q
= box
(j
);
1039 int set_tex_box_height
(int j
, scaled v
)
1041 halfword q
= box
(j
);
1048 scaled get_tex_box_depth
(int j
)
1050 halfword q
= box
(j
);
1056 int set_tex_box_depth
(int j
, scaled v
)
1058 halfword q
= box
(j
);
1065 @ This section is devoted to the
{\sl Synchronize \TeX nology
}
1066 - or simply
{\sl Sync\TeX
} - used to synchronize between input and output.
1067 This section explains how synchronization basics are implemented.
1068 Before we enter into more technical details
,
1069 let us recall in a few words what is synchronization.
1071 \TeX\ typesetting system clearly separates the input and the output material
,
1072 and synchronization will provide a new link between both that can help
1073 text editors and viewers to work together.
1074 More precisely
, forwards synchronization is the ability
,
1075 given a location in the input source file
,
1076 to find what is the corresponding place in the output.
1077 Backwards synchronization just performs the opposite
:
1078 given a location in the output
,
1079 retrieve the corresponding material in the input source file.
1081 For better code management and maintainance
, we adopt a naming convention.
1082 Throughout this program
, code related to the
{\sl Synchronize \TeX nology
} is tagged
1083 with the ``
{\sl synctex
}'' key word. Any code extract where
{\sl Sync\TeX
} plays
1084 its part
, either explicitly or implicitly
, (should
) contain the string ``
{\sl synctex
}''.
1085 This naming convention also holds for external files.
1086 Moreover
, all the code related to
{\sl Sync\TeX
} is gathered in this section
,
1087 except the definitions.
1089 Enabling synchronization should be performed from the command line
,
1090 |synctexoption| is used for that purpose.
1091 This global integer variable is declared here but it is not used here.
1092 This is just a placeholder where the command line controller will put
1093 the
{\sl Sync\TeX
} related options
, and the
{\sl Sync\TeX
} controller will read them.
1098 @ A convenient primitive is provided
:
1099 \.
{\\synctex
=1} in the input source file enables synchronization whereas
1100 \.
{\\synctex
=0} disables it.
1101 Its memory address is |synctex_code|.
1102 It is initialized by the
{\sl Sync\TeX
} controller to the command-line option if given.
1103 The controller may filter some reserved bits.
1105 In order to give the
{\sl Sync\TeX
} controller read and write access to
1106 the contents of the \.
{\\synctex
} primitive
, we declare |synctexoffset|
,
1107 such that |mem
[synctexoffset
]| and \.
{\\synctex
} correspond to
1108 the same memory storage. |synctexoffset| is initialized to
1109 the correct value when quite everything is initialized.
1112 int synctexoffset
; /* holds the true value of |synctex_code|
*/
1114 @ Synchronization is achieved with the help of an auxiliary file named
1115 `\.
{{\sl jobname
}.synctex
}'
({\sl jobname
} is the contents of the
1116 \.
{\\jobname
} macro
), where a
{\sl Sync\TeX
} controller implemented
1117 in the external |synctex.c| file will store geometrical information.
1118 This
{\sl Sync\TeX
} controller will take care of every technical details
1119 concerning the
{\sl Sync\TeX
} file
, we will only focus on the messages
1120 the controller will receive from the \TeX\ program.
1122 The most accurate synchronization information should allow to map
1123 any character of the input source file to the corresponding location
1124 in the output
, if relevant.
1125 Ideally
, the synchronization information of the input material consists of
1126 the file name
, the line and column numbers of every character.
1127 The synchronization information in the output is simply the page number and
1128 either point coordinates
, or box dimensions and position.
1129 The problem is that the mapping between these informations is only known at
1130 ship out time
, which means that we must keep track of the input
1131 synchronization information until the pages ship out.
1133 As \TeX\ only knows about file names and line numbers
,
1134 but forgets the column numbers
, we only consider a
1135 restricted input synchronization information called
{\sl Sync\TeX\ information
}.
1136 It consists of a unique file name identifier
, the
{\sl Sync\TeX\ file tag
},
1137 and the line number.
1139 Keeping track of such information
,
1140 should be different whether characters or nodes are involved.
1141 Actually
, only certain nodes are involved in
{\sl Sync\TeX
},
1142 we call them
{\sl synchronized nodes
}.
1143 Synchronized nodes store the
{\sl Sync\TeX
} information in their last two words
:
1144 the first one contains a
{\sl Sync\TeX\ file tag
} uniquely identifying
1145 the input file
, and the second one contains the current line number
,
1146 as returned by the \.
{\\inputlineno
} primitive.
1147 The |synctex_field_size| macro contains the necessary size to store
1148 the
{\sl Sync\TeX
} information in a node.
1150 When declaring the size of a new node
, it is recommanded to use the following
1151 convention
: if the node is synchronized
, use a definition similar to
1152 |my_synchronized_node_size|
={\sl xxx
}+|synctex_field_size|.
1153 Moreover
, one should expect that the
{\sl Sync\TeX
} information is always stored
1154 in the last two words of a synchronized node.
1156 By default
, every node with a sufficiently big size is initialized
1157 at creation time in the |get_node| routine with the current
1158 {\sl Sync\TeX
} information
, whether or not the node is synchronized.
1159 One purpose is to set this information very early in order to minimize code
1160 dependencies
, including forthcoming extensions.
1161 Another purpose is to avoid the assumption that every node type has a dedicated getter
,
1162 where initialization should take place. Actually
, it appears that some nodes are created
1163 using directly the |get_node| routine and not the dedicated constructor.
1164 And finally
, initializing the node at only one place is less error prone.
1166 Instead of storing the input file name
, it is better to store just an identifier.
1167 Each time \TeX\ opens a new file
, it notifies the
{\sl Sync\TeX
} controller with
1168 a |synctex_start_input| message.
1169 This controller will create a new
{\sl Sync\TeX
} file tag and
1170 will update the current input state record accordingly.
1171 If the input comes from the terminal or a pseudo file
, the |synctex_tag| is set to
0.
1172 It results in automatically disabling synchronization for material
1173 input from the terminal or pseudo files.
1175 Synchronized nodes are boxes
, math
, kern and glue nodes.
1176 Other nodes should be synchronized too
, in particular math noads.
1177 \TeX\ assumes that math
, kern and glue nodes have the same size
,
1178 this is why both are synchronized.
1179 {\sl In fine
}, only horizontal lists are really used in
{\sl Sync\TeX
},
1180 but all box nodes are considered the same with respect to synchronization
,
1181 because a box node type is allowed to change at execution time.
1184 The
{\sl Sync\TeX
} code is very close to the memory model.
1185 It is not connected to any other part of the code
,
1186 except for memory management. It is possible to neutralize the
{\sl Sync\TeX
} code
1187 rather simply. The first step is to define a null |synctex_field_size|.
1188 The second step is to comment out the code in ``Initialize bigger nodes...'' and every
1189 ``Copy ...
{\sl Sync\TeX
} information''.
1190 The last step will be to comment out the |synctex_tag_field| related code in the
1191 definition of |synctex_tag| and the various ``Prepare ...
{\sl Sync\TeX
} information''.
1192 Then all the remaining code should be just harmless.
1193 The resulting program would behave exactly the same as if absolutely no
{\sl Sync\TeX
}
1194 related code was there
, including memory management.
1195 Of course
, all this assumes that
{\sl Sync\TeX
} is turned off from the command line.
1199 @ Here are extra variables for Web2c.
(This numbering of the
1200 system-dependent section allows easy integration of Web2c and e-\TeX
, etc.
)
1201 @^
<system dependencies@
>
1204 pool_pointer edit_name_start
; /* where the filename to switch to starts
*/
1205 int edit_name_length
, edit_line
; /* what line to start editing at
*/
1206 int ipcon
; /* level of IPC action
, 0 for none
[default
] */
1207 boolean stop_at_space
; /* whether |more_name| returns false for space
*/
1209 @ The |edit_name_start| will be set to point into |str_pool| somewhere after
1210 its beginning if \TeX\ is supposed to switch to an editor on exit.
1214 int restrictedshell
;
1215 char
*output_comment
;
1217 @ Are we printing extra info as we read the format file?
1220 boolean debug_format_file
;