3 % Copyright
2009-2012 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
/>.
26 #define prev_depth cur_list.prev_depth_field
27 #define space_factor cur_list.space_factor_field
28 #define par_shape_ptr equiv
(par_shape_loc
)
29 #define font_id_text
(A
) cs_text
(font_id_base
+(A
))
31 #define attribute
(A
) eqtb
[attribute_base
+(A
)].hh.rh
32 #define dimen
(A
) eqtb
[scaled_base
+(A
)].hh.rh
34 #define skip
(A
) eqtb
[skip_base
+(A
)].hh.rh
35 #define mu_skip
(A
) eqtb
[mu_skip_base
+(A
)].hh.rh
36 #define count
(A
) eqtb
[count_base
+(A
)].hh.rh
37 #define box
(A
) equiv
(box_base
+(A
))
39 #define text_direction int_par
(text_direction_code
)
40 #define body_direction int_par
(body_direction_code
)
43 @ Let's turn now to some procedures that \TeX\ calls upon frequently to digest
44 certain kinds of patterns in the input. Most of these are quite simple
;
45 some are quite elaborate. Almost all of the routines call |get_x_token|
,
46 which can cause them to be invoked recursively.
48 The |scan_left_brace| routine is called when a left brace is supposed to be
49 the next non-blank token.
(The term ``left brace'' means
, more precisely
,
50 a character whose catcode is |left_brace|.
) \TeX\ allows \.
{\\relax
} to
51 appear before the |left_brace|.
54 void scan_left_brace
(void
)
55 { /* reads a mandatory |left_brace|
*/
56 /* Get the next non-blank non-relax non-call token
*/
59 } while
((cur_cmd
== spacer_cmd
) ||
(cur_cmd
== relax_cmd
));
61 if
(cur_cmd
!= left_brace_cmd
) {
62 print_err
("Missing { inserted");
63 help4
("A left brace was mandatory here, so I've put one in.",
64 "You might want to delete and/or insert some corrections",
65 "so that I will find a matching right brace soon.",
66 "If you're confused by all this, try typing `I}' now.");
68 cur_tok
= left_brace_token
+ '
{'
;
69 cur_cmd
= left_brace_cmd
;
76 @ The |scan_optional_equals| routine looks for an optional `\.
=' sign preceded
77 by optional spaces
; `\.
{\\relax
}' is not ignored here.
80 void scan_optional_equals
(void
)
82 /* Get the next non-blank non-call token
*/
85 } while
(cur_cmd
== spacer_cmd
);
86 if
(cur_tok
!= other_token
+ '
='
)
91 @ Here is a procedure that sounds an alarm when mu and non-mu units
95 static void mu_error
(void
)
97 print_err
("Incompatible glue units");
98 help1
("I'm going to assume that 1mu=1pt when they're mixed.");
103 @ The next routine `|scan_something_internal|' is used to fetch internal
104 numeric quantities like `\.
{\\hsize
}'
, and also to handle the `\.
{\\the
}'
105 when expanding constructions like `\.
{\\the\\toks0
}' and
106 `\.
{\\the\\baselineskip
}'. Soon we will be considering the |scan_int|
107 procedure
, which calls |scan_something_internal|
; on the other hand
,
108 |scan_something_internal| also calls |scan_int|
, for constructions like
109 `\.
{\\catcode\`\\\$
}' or `\.
{\\fontdimen
} \
.3 \.
{\\ff
}'. So we
110 have to declare |scan_int| as a |forward| procedure. A few other
111 procedures are also declared at this point.
113 \TeX\ doesn't know exactly what to expect when
114 |scan_something_internal| begins. For example
, an integer or
115 dimension or glue value could occur immediately after `\.
{\\hskip
}'
;
116 and one can even say \.
{\\the
} with respect to token lists in
117 constructions like `\.
{\\xdef\\o\
{\\the\\output\
}}'. On the other
118 hand
, only integers are allowed after a construction like
119 `\.
{\\count
}'. To handle the various possibilities
,
120 |scan_something_internal| has a |level| parameter
, which tells the
121 ``highest'' kind of quantity that |scan_something_internal| is allowed
122 to produce. Eight levels are distinguished
, namely |int_val|
,
123 |attr_val|
, |dimen_val|
, |glue_val|
, |mu_val|
, |dir_val|
, |ident_val|
,
126 The output of |scan_something_internal|
(and of the other routines
127 |scan_int|
, |scan_dimen|
, and |scan_glue| below
) is put into the global
128 variable |cur_val|
, and its level is put into |cur_val_level|. The highest
129 values of |cur_val_level| are special
: |mu_val| is used only when
130 |cur_val| points to something in a ``muskip'' register
, or to one of the
131 three parameters \.
{\\thinmuskip
}, \.
{\\medmuskip
}, \.
{\\thickmuskip
};
132 |ident_val| is used only when |cur_val| points to a font identifier
;
133 |tok_val| is used only when |cur_val| points to |null| or to the reference
134 count of a token list. The last two cases are allowed only when
135 |scan_something_internal| is called with |level
=tok_val|.
137 If the output is glue
, |cur_val| will point to a glue specification
, and
138 the reference count of that glue will have been updated to reflect this
139 reference
; if the output is a nonempty token list
, |cur_val| will point to
140 its reference count
, but in this case the count will not have been updated.
141 Otherwise |cur_val| will contain the integer or scaled value in question.
144 int cur_val
; /* value returned by numeric scanners
*/
145 int cur_val1
; /* delcodes are sometimes
51 digits
*/
146 int cur_val_level
; /* the ``level'' of this value
*/
148 #define scanned_result
(A
,B
) do
{ \
154 @ When a |glue_val| changes to a |dimen_val|
, we use the width component
155 of the glue
; there is no need to decrease the reference count
, since it
156 has not yet been increased. When a |dimen_val| changes to an |int_val|
,
157 we use scaled points so that the value doesn't actually change. And when a
158 |mu_val| changes to a |glue_val|
, the value doesn't change either.
161 static void downgrade_cur_val
(boolean delete_glue
)
164 if
(cur_val_level
== glue_val_level
) {
169 } else if
(cur_val_level
== mu_val_level
) {
175 static void negate_cur_val
(boolean delete_glue
)
178 if
(cur_val_level
>= glue_val_level
) {
180 cur_val
= new_spec
(m
);
183 /* Negate all three glue components of |cur_val|
*/
184 negate
(width
(cur_val
));
185 negate
(stretch
(cur_val
));
186 negate
(shrink
(cur_val
));
194 @ Some of the internal items can be fetched both routines
,
195 and these have been split off into the next routine
, that
196 returns true if the command code was understood
199 static boolean short_scan_something_internal
(int cmd
, int chr
, int level
,
202 halfword m
; /* |chr_code| part of the operand token
*/
203 halfword q
; /* general purpose index
*/
204 int p
; /* index into |nest|
*/
206 boolean succeeded
= true
;
209 case assign_toks_cmd
:
210 scanned_result
(equiv
(m
), tok_val_level
);
213 scanned_result
(eqtb
[m
].cint
, int_val_level
);
215 case assign_attr_cmd
:
216 scanned_result
(eqtb
[m
].cint
, int_val_level
);
219 scanned_result
(eqtb
[m
].cint
, dir_val_level
);
221 case assign_dimen_cmd
:
222 scanned_result
(eqtb
[m
].cint
, dimen_val_level
);
224 case assign_glue_cmd
:
225 scanned_result
(equiv
(m
), glue_val_level
);
227 case assign_mu_glue_cmd
:
228 scanned_result
(equiv
(m
), mu_val_level
);
231 scanned_result
(m
, int_val_level
);
234 /* Fetch the |space_factor| or the |prev_depth|
*/
235 if
(abs
(cur_list.mode_field
) != m
) {
236 print_err
("Improper ");
237 print_cmd_chr
(set_aux_cmd
, m
);
238 help4
("You can refer to \\spacefactor only in horizontal mode;",
239 "you can refer to \\prevdepth only in vertical mode; and",
240 "neither of these is meaningful inside \\write. So",
241 "I'm forgetting what you said and using zero instead.");
243 if
(level
!= tok_val_level
)
244 scanned_result
(0, dimen_val_level
);
246 scanned_result
(0, int_val_level
);
247 } else if
(m
== vmode
) {
248 scanned_result
(prev_depth
, dimen_val_level
);
250 scanned_result
(space_factor
, int_val_level
);
253 case set_prev_graf_cmd
:
254 /* Fetch the |prev_graf|
*/
255 if
(cur_list.mode_field
== 0) {
256 scanned_result
(0, int_val_level
); /* |prev_graf
=0| within \.
{\\write
} */
259 while
(abs
(nest
[p
].mode_field
) != vmode
)
261 scanned_result
(nest
[p
].pg_field
, int_val_level
);
264 case set_page_int_cmd
:
265 /* Fetch the |dead_cycles| or the |insert_penalties|
*/
267 cur_val
= dead_cycles
;
269 cur_val
= interaction
; /* interactionmode
*/
271 cur_val
= insert_penalties
;
272 cur_val_level
= int_val_level
;
274 case set_page_dimen_cmd
:
275 /* Fetch something on the |page_so_far|
*/
276 if
((page_contents
== empty
) && (!output_active)) {
282 cur_val
= page_so_far
[m
];
284 cur_val_level
= dimen_val_level
;
286 case set_tex_shape_cmd
:
287 /* Fetch the |par_shape| size
*/
288 if
(par_shape_ptr
== null
)
291 cur_val
= vinfo
(par_shape_ptr
+ 1);
292 cur_val_level
= int_val_level
;
294 case set_etex_shape_cmd
:
295 /* Fetch a penalties array element
*/
297 if
((equiv
(m
) == null
) ||
(cur_val
< 0)) {
300 if
(cur_val
> penalty
(equiv
(m
)))
301 cur_val
= penalty
(equiv
(m
));
302 cur_val
= penalty
(equiv
(m
) + cur_val
);
304 cur_val_level
= int_val_level
;
308 case xmath_given_cmd
:
309 scanned_result
(cur_chr
, int_val_level
);
312 /* Because the items in this case directly refer to |cur_chr|
,
313 it needs to be saved and restored
*/
314 save_cur_chr
= cur_chr
;
316 /* Fetch an item in the current node
, if appropriate
*/
317 /* Here is where \.
{\\lastpenalty
}, \.
{\\lastkern
}, and \.
{\\lastskip
} are
318 implemented. The reference count for \.
{\\lastskip
} will be updated later.
320 We also handle \.
{\\inputlineno
} and \.
{\\badness
} here
, because they are
321 legal in similar contexts.
*/
323 if
(m
>= input_line_no_code
) {
324 if
(m
>= eTeX_glue
) {
325 /* Process an expression and |return|
*/
328 case mu_to_glue_code
:
331 }; /* there are no other cases
*/
332 cur_val_level
= glue_val_level
;
333 } else if
(m
< eTeX_expr
) {
335 case glue_to_mu_code
:
338 } /* there are no other cases
*/
339 cur_val_level
= mu_val_level
;
341 cur_val_level
= m
- eTeX_expr
+ int_val_level
;
344 /* This code for reducing |cur_val_level| and\slash or negating the
345 result is similar to the one for all the other cases of
346 |scan_something_internal|
, with the difference that |scan_expr| has
347 already increased the reference count of a glue specification.
349 while
(cur_val_level
> level
) {
350 downgrade_cur_val
(true
);
353 negate_cur_val
(true
);
357 } else if
(m
>= eTeX_dim
) {
359 case font_char_wd_code
:
360 case font_char_ht_code
:
361 case font_char_dp_code
:
362 case font_char_ic_code
:
366 if
(char_exists
(q
, cur_val
)) {
368 case font_char_wd_code
:
369 cur_val
= char_width
(q
, cur_val
);
371 case font_char_ht_code
:
372 cur_val
= char_height
(q
, cur_val
);
374 case font_char_dp_code
:
375 cur_val
= char_depth
(q
, cur_val
);
377 case font_char_ic_code
:
378 cur_val
= char_italic
(q
, cur_val
);
380 } /* there are no other cases
*/
385 case par_shape_length_code
:
386 case par_shape_indent_code
:
387 case par_shape_dimen_code
:
388 q
= cur_chr
- par_shape_length_code
;
390 if
((par_shape_ptr
== null
) ||
(cur_val
<= 0)) {
395 cur_val
= (cur_val
+ q
) / 2;
397 if
(cur_val
> vinfo
(par_shape_ptr
+ 1))
398 cur_val
= vinfo
(par_shape_ptr
+ 1);
400 varmem
[par_shape_ptr
+ 2 * cur_val
- q
+ 1].cint
;
402 cur_val_level
= dimen_val_level
;
404 case glue_stretch_code
:
405 case glue_shrink_code
:
408 if
(m
== glue_stretch_code
)
409 cur_val
= stretch
(q
);
414 } /* there are no other cases
*/
415 cur_val_level
= dimen_val_level
;
418 case input_line_no_code
:
422 cur_val
= last_badness
;
424 case luatex_version_code
:
425 cur_val
= get_luatexversion
();
427 case pdf_last_obj_code
:
428 cur_val
= pdf_last_obj
;
430 case pdf_last_xform_code
:
431 cur_val
= pdf_last_xform
;
433 case pdf_last_ximage_code
:
434 cur_val
= pdf_last_ximage
;
436 case pdf_last_ximage_pages_code
:
437 cur_val
= pdf_last_ximage_pages
;
439 case pdf_last_annot_code
:
440 cur_val
= pdf_last_annot
;
442 case last_x_pos_code
:
443 cur_val
= pdf_last_pos.h
;
445 case last_y_pos_code
:
446 cur_val
= pdf_last_pos.v
;
448 case pdf_retval_code
:
449 cur_val
= pdf_retval
;
451 case pdf_last_ximage_colordepth_code
:
452 cur_val
= pdf_last_ximage_colordepth
;
454 case random_seed_code
:
455 cur_val
= random_seed
;
457 case pdf_last_link_code
:
458 cur_val
= pdf_last_link
;
460 case eTeX_version_code
:
461 cur_val
= eTeX_version
;
463 case eTeX_minor_version_code
:
464 cur_val
= eTeX_minor_version
;
466 case current_group_level_code
:
467 cur_val
= cur_level
- level_one
;
469 case current_group_type_code
:
472 case current_if_level_code
:
480 case current_if_type_code
:
481 if
(cond_ptr
== null
)
483 else if
(cur_if
< unless_code
)
484 cur_val
= cur_if
+ 1;
486 cur_val
= -(cur_if
- unless_code
+ 1);
488 case current_if_branch_code
:
489 if
((if_limit
== or_code
) ||
(if_limit
== else_code
))
491 else if
(if_limit
== fi_code
)
496 case glue_stretch_order_code
:
497 case glue_shrink_order_code
:
500 if
(m
== glue_stretch_order_code
)
501 cur_val
= stretch_order
(q
);
503 cur_val
= shrink_order
(q
);
507 } /* there are no other cases
*/
508 cur_val_level
= int_val_level
;
511 if
(cur_chr
== glue_val_level
)
515 if
(cur_chr
== last_node_type_code
) {
516 cur_val_level
= int_val_level
;
517 if
((cur_list.tail_field
== cur_list.head_field
)
518 ||
(cur_list.mode_field
== 0))
521 cur_val_level
= cur_chr
; /* assumes identical values
*/
523 if
((cur_list.tail_field
!= contrib_head
) &&
524 !is_char_node
(cur_list.tail_field
) &&
525 (cur_list.mode_field
!= 0)) {
527 case lastpenalty_code
:
528 if
(type
(cur_list.tail_field
) == penalty_node
)
529 cur_val
= penalty
(cur_list.tail_field
);
532 if
(type
(cur_list.tail_field
) == kern_node
)
533 cur_val
= width
(cur_list.tail_field
);
536 if
(type
(cur_list.tail_field
) == glue_node
)
537 cur_val
= glue_ptr
(cur_list.tail_field
);
538 if
(subtype
(cur_list.tail_field
) == mu_glue
)
539 cur_val_level
= mu_val_level
;
541 case last_node_type_code
:
542 cur_val
= visible_last_node_type
(cur_list.tail_field
);
544 } /* there are no other cases
*/
545 } else if
((cur_list.mode_field
== vmode
)
546 && (cur_list.tail_field == cur_list.head_field)) {
548 case lastpenalty_code
:
549 cur_val
= last_penalty
;
555 if
(last_glue
!= max_halfword
)
558 case last_node_type_code
:
559 cur_val
= last_node_type
;
561 } /* there are no other cases
*/
564 cur_chr
= save_cur_chr
;
570 while
(cur_val_level
> level
) {
571 /* Convert |cur_val| to a lower level
*/
572 downgrade_cur_val
(false
);
574 /* Fix the reference count
, if any
, and negate |cur_val| if |negative|
*/
575 /* If |cur_val| points to a glue specification at this point
, the reference
576 count for the glue does not yet include the reference by |cur_val|.
577 If |negative| is |true|
, |cur_val_level| is known to be |
<=mu_val|.
580 negate_cur_val
(false
);
581 } else if
((cur_val_level
>= glue_val_level
)
582 && (cur_val_level <= mu_val_level)) {
583 add_glue_ref
(cur_val
);
589 @ First
, here is a short routine that is called from lua code. All
590 the real work is delegated to |short_scan_something_internal| that
591 is shared between this routine and |scan_something_internal|.
594 void scan_something_simple
(halfword cmd
, halfword subitem
)
596 /* negative is never true
*/
597 if
(!short_scan_something_internal
(cmd
, subitem
, tok_val_level
, false
)) {
598 /* Complain that |texlib| can not do this
; give zero result
*/
599 print_err
("You can't use `");
600 print_cmd_chr
((quarterword
) cmd
, subitem
);
601 tprint
("' as tex library index");
602 help1
("I'm forgetting what you said and using zero instead.");
604 scanned_result
(0, int_val_level
);
610 @
OK, we're ready for |scan_something_internal| itself. A second parameter
,
611 |negative|
, is set |true| if the value that is found should be negated.
612 It is assumed that |cur_cmd| and |cur_chr| represent the first token of
613 the internal quantity to be scanned
; an error will be signalled if
614 |cur_cmd
<min_internal| or |cur_cmd
>max_internal|.
617 void scan_something_internal
(int level
, boolean negative
)
619 /* fetch an internal parameter
*/
620 halfword m
; /* |chr_code| part of the operand token
*/
621 int n
, k
; /* accumulators
*/
624 if
(!short_scan_something_internal
(cur_cmd
, cur_chr
, level
, negative
)) {
626 case def_char_code_cmd
:
627 /* Fetch a character code from some table
*/
629 if
(m
== math_code_base
) {
630 cur_val1
= get_math_code_num
(cur_val
, true
);
631 scanned_result
(cur_val1
, int_val_level
);
632 } else if
(m
== lc_code_base
) {
633 cur_val1
= get_lc_code
(cur_val
);
634 scanned_result
(cur_val1
, int_val_level
);
635 } else if
(m
== uc_code_base
) {
636 cur_val1
= get_uc_code
(cur_val
);
637 scanned_result
(cur_val1
, int_val_level
);
638 } else if
(m
== sf_code_base
) {
639 cur_val1
= get_sf_code
(cur_val
);
640 scanned_result
(cur_val1
, int_val_level
);
641 } else if
(m
== cat_code_base
) {
642 cur_val1
= get_cat_code
(int_par
(cat_code_table_code
), cur_val
);
643 scanned_result
(cur_val1
, int_val_level
);
645 confusion
("def_char");
648 case def_del_code_cmd
:
649 /* Fetch a character code from some table
*/
651 cur_val1
= get_del_code_num
(cur_val
);
652 scanned_result
(cur_val1
, int_val_level
);
654 case extdef_math_code_cmd
:
655 /* Fetch an extended math code table value
*/
657 cur_val1
= get_math_code_num
(cur_val
, false
);
658 scanned_result
(cur_val1
, int_val_level
);
660 case toks_register_cmd
:
663 case letterspace_font_cmd
:
664 case pdf_copy_font_cmd
:
665 /* Fetch a token list or font identifier
, provided that |level
=tok_val|
*/
666 if
(level
!= tok_val_level
) {
667 print_err
("Missing number, treated as zero");
668 help3
("A number should have been here; I inserted `0'.",
669 "(If you can't figure out why I needed to see a number,",
670 "look up `weird error' in the index to The TeXbook.)");
672 scanned_result
(0, dimen_val_level
);
673 } else if
(cur_cmd
== toks_register_cmd
) {
675 m
= toks_base
+ cur_val
;
676 scanned_result
(equiv
(m
), tok_val_level
);
680 scanned_result
(font_id_base
+ cur_val
, ident_val_level
);
684 /* Fetch a math font identifier
*/
686 cur_val1
= fam_fnt
(cur_val
, m
);
687 scanned_result
(font_id_base
+ cur_val1
, ident_val_level
);
689 case set_math_param_cmd
:
690 /* Fetch a math param
*/
693 if
(cur_cmd
!= math_style_cmd
) {
694 print_err
("Missing math style, treated as \\displaystyle");
696 ("A style should have been here; I inserted `\\displaystyle'.");
697 cur_val
= display_style
;
702 if
(cur_val1
< math_param_first_mu_glue
) {
703 if
(cur_val1
== math_param_radical_degree_raise
) {
704 cur_val1
= get_math_param
(cur_val1
, cur_chr
);
705 scanned_result
(cur_val1
, int_val_level
);
707 cur_val1
= get_math_param
(cur_val1
, cur_chr
);
708 scanned_result
(cur_val1
, dimen_val_level
);
711 cur_val1
= get_math_param
(cur_val1
, cur_chr
);
712 if
(cur_val1
== thin_mu_skip_code
)
713 cur_val1
= glue_par
(thin_mu_skip_code
);
714 else if
(cur_val1
== med_mu_skip_code
)
715 cur_val1
= glue_par
(med_mu_skip_code
);
716 else if
(cur_val1
== thick_mu_skip_code
)
717 cur_val1
= glue_par
(thick_mu_skip_code
);
718 scanned_result
(cur_val1
, mu_val_level
);
721 case assign_box_dir_cmd
:
725 cur_val
= box_dir
(box
(m
));
728 cur_val_level
= dir_val_level
;
730 case set_box_dimen_cmd
:
731 /* Fetch a box dimension
*/
733 if
(box
(cur_val
) == null
)
736 cur_val
= varmem
[box
(cur_val
) + m
].cint
;
737 cur_val_level
= dimen_val_level
;
739 case assign_font_dimen_cmd
:
740 /* Fetch a font dimension
*/
743 case assign_font_int_cmd
:
744 /* Fetch a font integer
*/
747 scanned_result
(hyphen_char
(cur_val
), int_val_level
);
749 scanned_result
(skew_char
(cur_val
), int_val_level
);
750 } else if
(m
== no_lig_code
) {
751 scanned_result
(test_no_ligatures
(cur_val
), int_val_level
);
758 scanned_result
(get_lp_code
(n
, k
), int_val_level
);
761 scanned_result
(get_rp_code
(n
, k
), int_val_level
);
764 scanned_result
(get_ef_code
(n
, k
), int_val_level
);
767 scanned_result
(get_tag_code
(n
, k
), int_val_level
);
773 /* Fetch a register
*/
777 cur_val
= count
(cur_val
);
780 cur_val
= attribute
(cur_val
);
782 case dimen_val_level
:
783 cur_val
= dimen
(cur_val
);
786 cur_val
= skip
(cur_val
);
789 cur_val
= mu_skip
(cur_val
);
791 } /* there are no other cases
*/
794 case ignore_spaces_cmd
: /* trap unexpandable primitives
*/
796 /* Reset |cur_tok| for unexpandable primitives
, goto restart
*/
797 /* This block deals with unexpandable \.
{\\primitive
} appearing at a spot where
798 an integer or an internal values should have been found. It fetches the
799 next token then resets |cur_cmd|
, |cur_cs|
, and |cur_tok|
, based on the
800 primitive value of that token. No expansion takes place
, because the
801 next token may be all sorts of things. This could trigger further
802 expansion creating new errors.
805 cur_cs
= prim_lookup
(cs_text
(cur_cs
));
806 if
(cur_cs
!= undefined_primitive
) {
807 cur_cmd
= get_prim_eq_type
(cur_cs
);
808 cur_chr
= get_prim_equiv
(cur_cs
);
809 cur_tok
= token_val
(cur_cmd
, cur_chr
);
813 cur_tok
= cs_token_flag
+ frozen_relax
;
814 cur_cs
= frozen_relax
;
820 /* Complain that \.
{\\the
} can not do this
; give zero result
*/
821 print_err
("You can't use `");
822 print_cmd_chr
((quarterword
) cur_cmd
, cur_chr
);
823 tprint
("' after \\the");
824 help1
("I'm forgetting what you said and using zero instead.");
826 if
(level
!= tok_val_level
)
827 scanned_result
(0, dimen_val_level
);
829 scanned_result
(0, int_val_level
);
832 while
(cur_val_level
> level
) {
833 /* Convert |cur_val| to a lower level
*/
834 downgrade_cur_val
(false
);
836 /* Fix the reference count
, if any
, and negate |cur_val| if |negative|
*/
837 /* If |cur_val| points to a glue specification at this point
, the reference
838 count for the glue does not yet include the reference by |cur_val|.
839 If |negative| is |true|
, |cur_val_level| is known to be |
<=mu_val|.
842 negate_cur_val
(false
);
843 } else if
((cur_val_level
>= glue_val_level
) &&
844 (cur_val_level
<= mu_val_level
)) {
845 add_glue_ref
(cur_val
);
851 @ It is nice to have routines that say what they do
, so the original
852 |scan_eight_bit_int| is superceded by |scan_register_num| and
853 |scan_mark_num|. It may become split up even further in the future.
855 Many of the |restricted classes| routines are the essentially
856 the same except for the upper limit and the error message
, so it makes
857 sense to combine these all into one function.
860 void scan_limited_int
(int max
, const char
*name
)
864 if
((cur_val
< 0) ||
(cur_val
> max
)) {
867 "Since I expected to read a number between 0 and %d,",
869 print_err
("Bad number");
872 snprintf
(hlp
, 80, "A %s must be between 0 and %d.", name
, max
);
873 snprintf
(msg
, 80, "Bad %s", name
);
876 help2
(hlp
, "I changed this one to zero.");
883 void scan_fifteen_bit_int
(void
)
885 scan_real_fifteen_bit_int
();
886 cur_val
= ((cur_val
/ 0x1000) * 0x1000000) +
887 (((cur_val
% 0x1000) / 0x100) * 0x10000) + (cur_val
% 0x100);
891 void scan_fifty_one_bit_int
(void
)
895 if
((cur_val
< 0) ||
(cur_val
> 0777777777)) {
896 print_err
("Bad delimiter code");
898 ("A numeric delimiter (first part) must be between 0 and 2^{27}-1.",
899 "I changed this one to zero.");
905 if
((cur_val
< 0) ||
(cur_val
> 0xFFFFFF)) {
906 print_err
("Bad delimiter code");
908 ("A numeric delimiter (second part) must be between 0 and 2^{24}-1.",
909 "I changed this one to zero.");
918 @ To be able to determine whether \.
{\\write18
} is enabled from within
919 \TeX\ we also implement \.
{\\eof18
}. We sort of cheat by having an
920 additional route |scan_four_bit_int_or_18| which is the same as
921 |scan_four_bit_int| except it also accepts the value
18.
924 void scan_four_bit_int_or_18
(void
)
927 if
((cur_val
< 0) ||
((cur_val
> 15) && (cur_val != 18))) {
928 print_err
("Bad number");
929 help2
("Since I expected to read a number between 0 and 15,",
930 "I changed this one to zero.");
939 @ An integer number can be preceded by any number of spaces and `\.
+' or
940 `\.
-' signs. Then comes either a decimal constant
(i.e.
, radix
10), an
941 octal constant
(i.e.
, radix
8, preceded by~'
), a hexadecimal constant
942 (radix
16, preceded by~
"), an alphabetic constant (preceded by~`), or
943 an internal variable. After scanning is complete,
944 |cur_val| will contain the answer, which must be at most
945 $2^{31}-1=2147483647$ in absolute value. The value of |radix| is set to
946 10, 8, or 16 in the cases of decimal, octal, or hexadecimal constants,
947 otherwise |radix| is set to zero. An optional space follows a constant.
950 int radix; /* |scan_int| sets this to 8, 10, 16, or zero */
953 @ The |scan_int| routine is used also to scan the integer part of a
954 fraction; for example, the `\.3' in `\.{3.14159}' will be found by
955 |scan_int|. The |scan_dimen| routine assumes that |cur_tok=point_token|
956 after the integer part of such a fraction has been scanned by |scan_int|,
957 and that the decimal point has been backed up to be scanned again.
961 { /* sets |cur_val| to an integer */
962 boolean negative; /* should the answer be negated? */
963 int m; /* |$2^{31}$ / radix|, the threshold of danger */
964 int d; /* the digit just scanned */
965 boolean vacuous; /* have no digits appeared? */
966 boolean OK_so_far; /* has an error message been issued? */
969 /* Get the next non-blank non-sign token; set |negative| appropriately */
972 /* Get the next non-blank non-call token */
975 } while (cur_cmd == spacer_cmd);
976 if (cur_tok == other_token + '-') {
977 negative = !negative;
978 cur_tok = other_token + '+';
980 } while (cur_tok == other_token + '+');
983 if (cur_tok == alpha_token) {
984 /* Scan an alphabetic character code into |cur_val| */
985 /* A space is ignored after an alphabetic character constant, so that
986 such constants behave like numeric ones. */
987 get_token(); /* suppress macro expansion */
988 if (cur_tok < cs_token_flag) {
990 if (cur_cmd <= right_brace_cmd) {
991 if (cur_cmd == right_brace_cmd)
996 } else { /* the value of a csname in this context is its name */
997 str_number txt = cs_text(cur_tok - cs_token_flag);
998 if (is_active_cs(txt))
999 cur_val = active_cs_value(txt);
1000 else if (single_letter(txt))
1001 cur_val = pool_to_unichar(str_string(txt));
1003 cur_val = (biggest_char + 1);
1005 if (cur_val > biggest_char) {
1006 print_err("Improper alphabetic constant
");
1007 help2("A one-character control sequence belongs after a ` mark.
",
1008 "So I'm essentially inserting \\
0 here.
");
1012 /* Scan an optional space */
1014 if (cur_cmd != spacer_cmd)
1018 } else if (cur_tok == cs_token_flag + frozen_primitive) {
1019 /* Reset |cur_tok| for unexpandable primitives, goto restart */
1020 /* This block deals with unexpandable \.{\\primitive} appearing at a spot where
1021 an integer or an internal values should have been found. It fetches the
1022 next token then resets |cur_cmd|, |cur_cs|, and |cur_tok|, based on the
1023 primitive value of that token. No expansion takes place, because the
1024 next token may be all sorts of things. This could trigger further
1025 expansion creating new errors.
1028 cur_cs = prim_lookup(cs_text(cur_cs));
1029 if (cur_cs != undefined_primitive) {
1030 cur_cmd = get_prim_eq_type(cur_cs);
1031 cur_chr = get_prim_equiv(cur_cs);
1032 cur_tok = token_val(cur_cmd, cur_chr);
1034 cur_cmd = relax_cmd;
1036 cur_tok = cs_token_flag + frozen_relax;
1037 cur_cs = frozen_relax;
1040 } else if (cur_cmd == math_style_cmd) {
1042 } else if ((cur_cmd >= min_internal_cmd) && (cur_cmd <= max_internal_cmd)) {
1043 scan_something_internal(int_val_level, false);
1045 /* Scan a numeric constant */
1048 if (cur_tok == octal_token) {
1052 } else if (cur_tok == hex_token) {
1059 /* Accumulate the constant until |cur_tok| is not a suitable digit */
1061 if ((cur_tok < zero_token + radix) && (cur_tok >= zero_token)
1062 && (cur_tok <= zero_token + 9)) {
1063 d = cur_tok - zero_token;
1064 } else if (radix == 16) {
1065 if ((cur_tok <= A_token + 5) && (cur_tok >= A_token)) {
1066 d = cur_tok - A_token + 10;
1067 } else if ((cur_tok <= other_A_token + 5)
1068 && (cur_tok >= other_A_token)) {
1069 d = cur_tok - other_A_token + 10;
1077 if ((cur_val >= m) && ((cur_val > m) || (d > 7) || (radix != 10))) {
1079 print_err("Number too big
");
1081 ("I can only go up to
2147483647='
17777777777=\
"7FFFFFFF,",
1082 "so I'm using that number instead of yours.");
1088 cur_val
= cur_val
* radix
+ d
;
1093 /* Express astonishment that no number was here
*/
1094 print_err
("Missing number, treated as zero");
1095 help3
("A number should have been here; I inserted `0'.",
1096 "(If you can't figure out why I needed to see a number,",
1097 "look up `weird error' in the index to The TeXbook.)");
1099 } else if
(cur_cmd
!= spacer_cmd
) {
1108 @ The following code is executed when |scan_something_internal| was
1109 called asking for |mu_val|
, when we really wanted a ``mudimen'' instead
1113 static void coerce_glue
(void
)
1116 if
(cur_val_level
>= glue_val_level
) {
1118 delete_glue_ref
(cur_val
);
1125 @ The |scan_dimen| routine is similar to |scan_int|
, but it sets |cur_val| to
1126 a |scaled| value
, i.e.
, an integral number of sp. One of its main tasks
1127 is therefore to interpret the abbreviations for various kinds of units and
1128 to convert measurements to scaled points.
1130 There are three parameters
: |mu| is |true| if the finite units must be
1131 `\.
{mu
}'
, while |mu| is |false| if `\.
{mu
}' units are disallowed
;
1132 |inf| is |true| if the infinite units `\.
{fil
}'
, `\.
{fill
}'
, `\.
{filll
}'
1133 are permitted
; and |shortcut| is |true| if |cur_val| already contains
1134 an integer and only the units need to be considered.
1136 The order of infinity that was found in the case of infinite glue is returned
1137 in the global variable |cur_order|.
1140 int cur_order
; /* order of infinity found by |scan_dimen|
*/
1143 @ Constructions like `\.
{-\'
77 pt
}' are legal dimensions
, so |scan_dimen|
1144 may begin with |scan_int|. This explains why it is convenient to use
1145 |scan_int| also for the integer part of a decimal fraction.
1147 Several branches of |scan_dimen| work with |cur_val| as an integer and
1148 with an auxiliary fraction |f|
, so that the actual quantity of interest is
1149 $|cur_val|
+|f|
/2^
{16}$. At the end of the routine
, this ``unpacked''
1150 representation is put into the single word |cur_val|
, which suddenly
1151 switches significance from |integer| to |scaled|.
1154 void scan_dimen
(boolean mu
, boolean inf
, boolean shortcut
)
1155 /* sets |cur_val| to a dimension
*/
1157 boolean negative
; /* should the answer be negated?
*/
1158 int f
; /* numerator of a fraction whose denominator is $
2^
{16}$
*/
1159 /* Local variables for dimension calculations
*/
1160 int num
, denom
; /* conversion ratio for the scanned units
*/
1161 int k
, kk
; /* number of digits in a decimal fraction
*/
1162 halfword p
, q
; /* top of decimal digit stack
*/
1163 scaled v
; /* an internal dimension
*/
1164 int save_cur_val
; /* temporary storage of |cur_val|
*/
1167 arith_error
= false
;
1171 /* Get the next non-blank non-sign...
*/
1174 /* Get the next non-blank non-call token
*/
1177 } while
(cur_cmd
== spacer_cmd
);
1178 if
(cur_tok
== other_token
+ '
-'
) {
1179 negative
= !negative
;
1180 cur_tok
= other_token
+ '
+'
;
1182 } while
(cur_tok
== other_token
+ '
+'
);
1184 if
((cur_cmd
>= min_internal_cmd
) && (cur_cmd <= max_internal_cmd)) {
1185 /* Fetch an internal dimension and |goto attach_sign|
,
1186 or fetch an internal integer
*/
1188 scan_something_internal
(mu_val_level
, false
);
1190 if
(cur_val_level
== mu_val_level
)
1192 if
(cur_val_level
!= int_val_level
)
1195 scan_something_internal
(dimen_val_level
, false
);
1196 if
(cur_val_level
== dimen_val_level
)
1202 if
(cur_tok
== continental_point_token
) {
1203 cur_tok
= point_token
;
1205 if
(cur_tok
!= point_token
) {
1211 if
(cur_tok
== continental_point_token
)
1212 cur_tok
= point_token
;
1213 if
((radix
== 10) && (cur_tok == point_token)) {
1214 /* Scan decimal fraction
*/
1215 /* When the following code is executed
, we have |cur_tok
=point_token|
, but this
1216 token has been backed up using |back_input|
; we must first discard it.
1218 It turns out that a decimal point all by itself is equivalent to `\.
{0.0}'.
1219 Let's hope people don't use that fact.
*/
1223 get_token
(); /* |point_token| is being re-scanned
*/
1226 if
((cur_tok
> zero_token
+ 9) ||
(cur_tok
< zero_token
))
1228 if
(k
< 17) { /* digits for |k
>=17| cannot affect the result
*/
1230 set_token_link
(q
, p
);
1231 set_token_info
(q
, cur_tok
- zero_token
);
1236 for
(kk
= k
; kk
>= 1; kk--
) {
1237 dig
[kk
- 1] = token_info
(p
);
1242 f
= round_decimals
(k
);
1243 if
(cur_cmd
!= spacer_cmd
)
1248 if
(cur_val
< 0) { /* in this case |f
=0|
*/
1249 negative
= !negative
;
1252 /* Scan units and set |cur_val| to $x\cdot
(|cur_val|
+f
/2^
{16})$
, where there
1253 are |x| sp per unit
; |goto attach_sign| if the units are internal
*/
1254 /* Now comes the harder part
: At this point in the program
, |cur_val| is a
1255 nonnegative integer and $f
/2^
{16}$ is a nonnegative fraction less than
1;
1256 we want to multiply the sum of these two quantities by the appropriate
1257 factor
, based on the specified units
, in order to produce a |scaled|
1258 result
, and we want to do the calculation with fixed point arithmetic that
1263 /* Scan for
(f
)\.
{fil
} units
; |goto attach_fraction| if found
*/
1264 /* In traditional TeX
, a specification like `\.
{filllll
}' or `\.
{fill L L
1265 L
}' will lead to two error messages
(one for each additional keyword
1267 Not so for luatex
, it just parses the construct in reverse.
*/
1268 if
(scan_keyword
("filll")) {
1270 goto ATTACH_FRACTION
;
1271 } else if
(scan_keyword
("fill")) {
1273 goto ATTACH_FRACTION
;
1274 } else if
(scan_keyword
("fil")) {
1276 goto ATTACH_FRACTION
;
1277 } else if
(scan_keyword
("fi")) {
1279 goto ATTACH_FRACTION
;
1283 /* Scan for
(u
)units that are internal dimensions
;
1284 |goto attach_sign| with |cur_val| set if found
*/
1285 save_cur_val
= cur_val
;
1286 /* Get the next non-blank non-call...
*/
1289 } while
(cur_cmd
== spacer_cmd
);
1291 if
((cur_cmd
< min_internal_cmd
) ||
(cur_cmd
> max_internal_cmd
)) {
1295 scan_something_internal
(mu_val_level
, false
);
1297 if
(cur_val_level
!= mu_val_level
)
1300 scan_something_internal
(dimen_val_level
, false
);
1307 if
(scan_keyword
("em")) {
1308 v
= (quad
(get_cur_font
()));
1309 } else if
(scan_keyword
("ex")) {
1310 v
= (x_height
(get_cur_font
()));
1311 } else if
(scan_keyword
("px")) {
1312 v
= dimen_par
(pdf_px_dimen_code
);
1316 /* Scan an optional space
*/
1318 if
(cur_cmd
!= spacer_cmd
)
1322 cur_val
= nx_plus_y
(save_cur_val
, v
, xn_over_d
(v
, f
, 0200000));
1327 /* Scan for
(m
)\.
{mu
} units and |goto attach_fraction|
*/
1328 if
(scan_keyword
("mu")) {
1329 goto ATTACH_FRACTION
;
1331 print_err
("Illegal unit of measure (mu inserted)");
1332 help4
("The unit of measurement in math glue must be mu.",
1333 "To recover gracefully from this error, it's best to",
1334 "delete the erroneous units; e.g., type `2' to delete",
1335 "two letters. (See Chapter 27 of The TeXbook.)");
1337 goto ATTACH_FRACTION
;
1340 if
(scan_keyword
("true")) {
1341 /* Adjust
(f
)for the magnification ratio
*/
1343 if
(int_par
(mag_code
) != 1000) {
1344 cur_val
= xn_over_d
(cur_val
, 1000, int_par
(mag_code
));
1345 f
= (1000 * f
+ 0200000 * tex_remainder
) / int_par
(mag_code
);
1346 cur_val
= cur_val
+ (f
/ 0200000);
1350 if
(scan_keyword
("pt"))
1351 goto ATTACH_FRACTION
; /* the easy case
*/
1352 /* Scan for
(a
)all other units and adjust |cur_val| and |f| accordingly
;
1353 |goto done| in the case of scaled points
*/
1355 /* The necessary conversion factors can all be specified exactly as
1356 fractions whose numerator and denominator add to
32768 or less.
1357 According to the definitions here
, $\rm2660\
,dd\approx1000.33297\
,mm$
;
1358 this agrees well with the value $\rm1000.333\
,mm$ cited by Bosshard
1359 \^
{Bosshard
, Hans Rudolf
}
1360 in
{\sl Technische Grundlagen zur Satzherstellung\
/} (Bern
, 1980).
1361 The Didot point has been newly standardized in
1978;
1362 it's now exactly $\rm
1\
,nd
=0.375\
,mm$.
1363 Conversion uses the equation $
0.375=21681/20320/72.27\cdot25.4$.
1364 The new Cicero follows the new Didot point
; $\rm
1\
,nc
=12\
,nd$.
1365 These would lead to the ratios $
21681/20320$ and $
65043/5080$
,
1367 The closest approximations supported by the algorithm would be
1368 $
11183/10481$ and $
1370/107$. In order to maintain the
1369 relation $\rm
1\
,nc
=12\
,nd$
, we pick the ratio $
685/642$ for
1373 #define set_conversion
(A
,B
) do
{ num
=(A
); denom
=(B
); } while
(0)
1375 if
(scan_keyword
("in")) {
1376 set_conversion
(7227, 100);
1377 } else if
(scan_keyword
("pc")) {
1378 set_conversion
(12, 1);
1379 } else if
(scan_keyword
("cm")) {
1380 set_conversion
(7227, 254);
1381 } else if
(scan_keyword
("mm")) {
1382 set_conversion
(7227, 2540);
1383 } else if
(scan_keyword
("bp")) {
1384 set_conversion
(7227, 7200);
1385 } else if
(scan_keyword
("dd")) {
1386 set_conversion
(1238, 1157);
1387 } else if
(scan_keyword
("cc")) {
1388 set_conversion
(14856, 1157);
1389 } else if
(scan_keyword
("nd")) {
1390 set_conversion
(685, 642);
1391 } else if
(scan_keyword
("nc")) {
1392 set_conversion
(1370, 107);
1393 } else if
(scan_keyword
("sp")) {
1396 /* Complain about unknown unit and |goto done2|
*/
1397 print_err
("Illegal unit of measure (pt inserted)");
1398 help6
("Dimensions can be in units of em, ex, in, pt, pc,",
1399 "cm, mm, dd, cc, nd, nc, bp, or sp; but yours is a new one!",
1400 "I'll assume that you meant to say pt, for printer's points.",
1401 "To recover gracefully from this error, it's best to",
1402 "delete the erroneous units; e.g., type `2' to delete",
1403 "two letters. (See Chapter 27 of The TeXbook.)");
1407 cur_val
= xn_over_d
(cur_val
, num
, denom
);
1408 f
= (num
* f
+ 0200000 * tex_remainder
) / denom
;
1409 cur_val
= cur_val
+ (f
/ 0200000);
1413 if
(cur_val
>= 040000)
1416 cur_val
= cur_val
* unity
+ f
;
1418 /* Scan an optional space
*/
1420 if
(cur_cmd
!= spacer_cmd
)
1423 if
(arith_error ||
(abs
(cur_val
) >= 010000000000)) {
1424 /* Report that this dimension is out of range
*/
1425 print_err
("Dimension too large");
1426 help2
("I can't work with sizes bigger than about 19 feet.",
1427 "Continue and I'll use the largest value I can.");
1429 cur_val
= max_dimen
;
1430 arith_error
= false
;
1437 @ The final member of \TeX's value-scanning trio is |scan_glue|
, which
1438 makes |cur_val| point to a glue specification. The reference count of that
1439 glue spec will take account of the fact that |cur_val| is pointing to~it.
1441 The |level| parameter should be either |glue_val| or |mu_val|.
1443 Since |scan_dimen| was so much more complex than |scan_int|
, we might expect
1444 |scan_glue| to be even worse. But fortunately
, it is very simple
, since
1445 most of the work has already been done.
1448 void scan_glue
(int level
)
1449 { /* sets |cur_val| to a glue spec pointer
*/
1450 boolean negative
; /* should the answer be negated?
*/
1451 halfword q
; /* new glue specification
*/
1452 boolean mu
; /* does |level
=mu_val|?
*/
1453 mu
= (level
== mu_val_level
);
1454 /* Get the next non-blank non-sign...
*/
1457 /* Get the next non-blank non-call token
*/
1460 } while
(cur_cmd
== spacer_cmd
);
1461 if
(cur_tok
== other_token
+ '
-'
) {
1462 negative
= !negative
;
1463 cur_tok
= other_token
+ '
+'
;
1465 } while
(cur_tok
== other_token
+ '
+'
);
1467 if
((cur_cmd
>= min_internal_cmd
) && (cur_cmd <= max_internal_cmd)) {
1468 scan_something_internal
(level
, negative
);
1469 if
(cur_val_level
>= glue_val_level
) {
1470 if
(cur_val_level
!= level
)
1474 if
(cur_val_level
== int_val_level
)
1475 scan_dimen
(mu
, false
, true
);
1476 else if
(level
== mu_val_level
)
1480 scan_dimen
(mu
, false
, false
);
1484 /* Create a new glue specification whose width is |cur_val|
; scan for its
1485 stretch and shrink components
*/
1486 q
= new_spec
(zero_glue
);
1488 if
(scan_keyword
("plus")) {
1489 scan_dimen
(mu
, true
, false
);
1490 stretch
(q
) = cur_val
;
1491 stretch_order
(q
) = (quarterword
) cur_order
;
1493 if
(scan_keyword
("minus")) {
1494 scan_dimen
(mu
, true
, false
);
1495 shrink
(q
) = cur_val
;
1496 shrink_order
(q
) = (quarterword
) cur_order
;
1501 @ This is an omega routine
1503 void scan_scaled
(void
)
1504 { /* sets |cur_val| to a scaled value
*/
1505 boolean negative
; /* should the answer be negated?
*/
1506 int f
; /* numerator of a fraction whose denominator is $
2^
{16}$
*/
1507 int k
, kk
; /* number of digits in a decimal fraction
*/
1508 halfword p
, q
; /* top of decimal digit stack
*/
1510 arith_error
= false
;
1512 /* Get the next non-blank non-sign...
*/
1514 /* Get the next non-blank non-call token
*/
1517 } while
(cur_cmd
== spacer_cmd
);
1518 if
(cur_tok
== other_token
+ '
-'
) {
1519 negative
= !negative
;
1520 cur_tok
= other_token
+ '
+'
;
1522 } while
(cur_tok
== other_token
+ '
+'
);
1525 if
(cur_tok
== continental_point_token
)
1526 cur_tok
= point_token
;
1527 if
(cur_tok
!= point_token
) {
1533 if
(cur_tok
== continental_point_token
)
1534 cur_tok
= point_token
;
1535 if
((radix
== 10) && (cur_tok == point_token)) {
1536 /* Scan decimal fraction
*/
1537 /* TODO
: merge this with the same block in |scan_dimen|
*/
1538 /* When the following code is executed
, we have |cur_tok
=point_token|
, but this
1539 token has been backed up using |back_input|
; we must first discard it.
1541 It turns out that a decimal point all by itself is equivalent to `\.
{0.0}'.
1542 Let's hope people don't use that fact.
*/
1546 get_token
(); /* |point_token| is being re-scanned
*/
1549 if
((cur_tok
> zero_token
+ 9) ||
(cur_tok
< zero_token
))
1551 if
(k
< 17) { /* digits for |k
>=17| cannot affect the result
*/
1553 set_token_link
(q
, p
);
1554 set_token_info
(q
, cur_tok
- zero_token
);
1559 for
(kk
= k
; kk
>= 1; kk--
) {
1560 dig
[kk
- 1] = token_info
(p
);
1565 f
= round_decimals
(k
);
1566 if
(cur_cmd
!= spacer_cmd
)
1570 if
(cur_val
< 0) { /* in this case |f
=0|
*/
1571 negative
= !negative
;
1574 if
(cur_val
> 040000)
1577 cur_val
= cur_val
* unity
+ f
;
1578 if
(arith_error ||
(abs
(cur_val
) >= 010000000000)) {
1579 print_err
("Stack number too large");
1587 @ This procedure is supposed to scan something like `\.
{\\skip\\count12
}'
,
1588 i.e.
, whatever can follow `\.
{\\the
}'
, and it constructs a token list
1589 containing something like `\.
{-3.0pt minus
0.5fill
}'.
1592 halfword the_toks
(void
)
1594 int old_setting
; /* holds |selector| setting
*/
1595 halfword p
, q
, r
; /* used for copying a token list
*/
1596 int c
; /* value of |cur_chr|
*/
1599 /* Handle \.
{\\unexpanded
} or \.
{\\detokenize
} and |return|
*/
1602 scan_general_text
();
1606 old_setting
= selector
;
1607 selector
= new_string
;
1609 set_token_link
(p
, token_link
(temp_token_head
));
1612 selector
= old_setting
;
1614 retval
= str_toks
(str_lstring
(s
));
1620 scan_something_internal
(tok_val_level
, false
);
1621 if
(cur_val_level
>= ident_val_level
) {
1622 /* Copy the token list
*/
1623 p
= temp_token_head
;
1624 set_token_link
(p
, null
);
1625 if
(cur_val_level
== ident_val_level
) {
1626 store_new_token
(cs_token_flag
+ cur_val
);
1627 } else if
(cur_val
!= null
) {
1628 r
= token_link
(cur_val
); /* do not copy the reference count
*/
1630 fast_store_new_token
(token_info
(r
));
1636 old_setting
= selector
;
1637 selector
= new_string
;
1638 switch
(cur_val_level
) {
1642 case attr_val_level
:
1648 case dimen_val_level
:
1649 print_scaled
(cur_val
);
1652 case glue_val_level
:
1653 print_spec
(cur_val
, "pt");
1654 delete_glue_ref
(cur_val
);
1657 print_spec
(cur_val
, "mu");
1658 delete_glue_ref
(cur_val
);
1660 } /* there are no other cases
*/
1661 selector
= old_setting
;
1663 retval
= str_toks
(str_lstring
(s
));
1670 str_number the_scanned_result
(void
)
1672 int old_setting
; /* holds |selector| setting
*/
1673 str_number r
; /* return value
* */
1674 old_setting
= selector
;
1675 selector
= new_string
;
1676 if
(cur_val_level
>= ident_val_level
) {
1677 if
(cur_val
!= null
) {
1678 show_token_list
(token_link
(cur_val
), null
, -1);
1684 switch
(cur_val_level
) {
1688 case attr_val_level
:
1694 case dimen_val_level
:
1695 print_scaled
(cur_val
);
1698 case glue_val_level
:
1699 print_spec
(cur_val
, "pt");
1700 delete_glue_ref
(cur_val
);
1703 print_spec
(cur_val
, "mu");
1704 delete_glue_ref
(cur_val
);
1706 } /* there are no other cases
*/
1709 selector
= old_setting
;
1715 @ The following routine is used to implement `\.
{\\fontdimen
} |n| |f|'.
1716 The boolean parameter |writing| is set |true| if the calling program
1717 intends to change the parameter value.
1720 static void font_param_error
(int f
)
1723 print_esc
(font_id_text
(f
));
1724 tprint
(" has only ");
1725 print_int
(font_params
(f
));
1726 tprint
(" fontdimen parameters");
1727 help2
("To increase the number of font parameters, you must",
1728 "use \\fontdimen immediately after the \\font is loaded.");
1732 void set_font_dimen
(void
)
1734 internal_font_number f
;
1735 int n
; /* the parameter number
*/
1741 font_param_error
(f
);
1743 if
(n
> font_params
(f
)) {
1745 font_param_error
(f
);
1747 /* Increase the number of parameters in the font
*/
1749 set_font_param
(f
, (font_params
(f
) + 1), 0);
1750 } while
(n
!= font_params
(f
));
1754 scan_optional_equals
();
1755 scan_normal_dimen
();
1756 set_font_param
(f
, n
, cur_val
);
1759 void get_font_dimen
(void
)
1761 internal_font_number f
;
1762 int n
; /* the parameter number
*/
1767 cur_val
= 0; /* initialize return value
*/
1769 font_param_error
(f
);
1772 if
(n
> font_params
(f
)) {
1774 font_param_error
(f
);
1777 /* Increase the number of parameters in the font
*/
1779 set_font_param
(f
, (font_params
(f
) + 1), 0);
1780 } while
(n
!= font_params
(f
));
1785 cur_val
= font_param
(f
, n
);
1787 scanned_result
(cur_val
, dimen_val_level
);
1791 @ Here's a similar procedure that returns a pointer to a rule node. This
1792 routine is called just after \TeX\ has seen \.
{\\hrule
} or \.
{\\vrule
};
1793 therefore |cur_cmd| will be either |hrule| or |vrule|. The idea is to store
1794 the default rule dimensions in the node
, then to override them if
1795 `\.
{height
}' or `\.
{width
}' or `\.
{depth
}' specifications are
1796 found
(in any order
).
1799 halfword scan_rule_spec
(void
)
1801 halfword q
; /* the rule node being created
*/
1802 q
= new_rule
(); /* |width|
, |depth|
, and |height| all equal |null_flag| now
*/
1803 if
(cur_cmd
== vrule_cmd
) {
1804 width
(q
) = default_rule
;
1805 rule_dir
(q
) = body_direction
;
1807 height
(q
) = default_rule
;
1809 rule_dir
(q
) = text_direction
;
1812 if
(scan_keyword
("width")) {
1813 scan_normal_dimen
();
1817 if
(scan_keyword
("height")) {
1818 scan_normal_dimen
();
1819 height
(q
) = cur_val
;
1822 if
(scan_keyword
("depth")) {
1823 scan_normal_dimen
();
1831 @ Declare procedures that scan font-related stuff
1834 void scan_font_ident
(void
)
1836 internal_font_number f
;
1838 /* Get the next non-blank non-call...
*/
1841 } while
(cur_cmd
== spacer_cmd
);
1843 if
((cur_cmd
== def_font_cmd
) ||
(cur_cmd
== letterspace_font_cmd
)
1844 ||
(cur_cmd
== pdf_copy_font_cmd
)) {
1846 } else if
(cur_cmd
== set_font_cmd
) {
1848 set_font_touched
(f
, 1);
1849 } else if
(cur_cmd
== def_family_cmd
) {
1851 scan_math_family_int
();
1852 f
= fam_fnt
(cur_val
, m
);
1853 set_font_touched
(f
, 1);
1855 print_err
("Missing font identifier");
1856 help2
("I was looking for a control sequence whose",
1857 "current meaning has been defined by \\font.");
1864 @ The |scan_general_text| procedure is much like |scan_toks
(false
,false
)|
,
1865 but will be invoked via |expand|
, i.e.
, recursively.
1867 The token list
(balanced text
) created by |scan_general_text| begins
1868 at |link
(temp_token_head
)| and ends at |cur_val|.
(If |cur_val
=temp_token_head|
,
1872 void scan_general_text
(void
)
1874 int s
; /* to save |scanner_status|
*/
1875 halfword w
; /* to save |warning_index|
*/
1876 halfword d
; /* to save |def_ref|
*/
1877 halfword p
; /* tail of the token list being built
*/
1878 halfword q
; /* new node being added to the token list via |store_new_token|
*/
1879 halfword unbalance
; /* number of unmatched left braces
*/
1883 scanner_status
= absorbing
;
1884 warning_index
= cur_cs
;
1887 set_token_ref_count
(def_ref
, 0);
1889 scan_left_brace
(); /* remove the compulsory left brace
*/
1893 if
(cur_tok
< right_brace_limit
) {
1894 if
(cur_cmd
< right_brace_cmd
) {
1902 store_new_token
(cur_tok
);
1904 q
= token_link
(def_ref
);
1905 free_avail
(def_ref
); /* discard reference count
*/
1907 cur_val
= temp_token_head
;
1910 set_token_link
(temp_token_head
, q
);
1917 @ The |get_x_or_protected| procedure is like |get_x_token| except that
1918 protected macros are not expanded.
1921 void get_x_or_protected
(void
)
1922 { /* sets |cur_cmd|
, |cur_chr|
, |cur_tok|
,
1923 and expands non-protected macros
*/
1926 if
(cur_cmd
<= max_command_cmd
)
1928 if
((cur_cmd
>= call_cmd
) && (cur_cmd < end_template_cmd)) {
1929 if
(token_info
(token_link
(cur_chr
)) == protected_token
)
1937 @ |scan_toks|. This function returns a pointer to the tail of a new token
1938 list
, and it also makes |def_ref| point to the reference count at the
1941 There are two boolean parameters
, |macro_def| and |xpand|. If |macro_def|
1942 is true
, the goal is to create the token list for a macro definition
;
1943 otherwise the goal is to create the token list for some other \TeX\
1944 primitive
: \.
{\\mark
}, \.
{\\output
}, \.
{\\everypar
}, \.
{\\lowercase
},
1945 \.
{\\uppercase
}, \.
{\\message
}, \.
{\\errmessage
}, \.
{\\write
}, or
1946 \.
{\\special
}. In the latter cases a left brace must be scanned next
; this
1947 left brace will not be part of the token list
, nor will the matching right
1948 brace that comes at the end. If |xpand| is false
, the token list will
1949 simply be copied from the input using |get_token|. Otherwise all expandable
1950 tokens will be expanded until unexpandable tokens are left
, except that
1951 the results of expanding `\.
{\\the
}' are not expanded further.
1952 If both |macro_def| and |xpand| are true
, the expansion applies
1953 only to the macro body
(i.e.
, to the material following the first
1954 |left_brace| character
).
1956 The value of |cur_cs| when |scan_toks| begins should be the |eqtb|
1957 address of the control sequence to display in ``runaway'' error
1961 halfword scan_toks
(boolean macro_def
, boolean xpand
)
1963 halfword t
; /* token representing the highest parameter number
*/
1964 halfword s
; /* saved token
*/
1965 halfword p
; /* tail of the token list being built
*/
1966 halfword q
; /* new node being added to the token list via |store_new_token|
*/
1967 halfword unbalance
; /* number of unmatched left braces
*/
1968 halfword hash_brace
; /* possible `\.
{\#\
{}' token
*/
1970 scanner_status
= defining
;
1972 scanner_status
= absorbing
;
1973 warning_index
= cur_cs
;
1976 set_token_ref_count
(def_ref
, 0);
1981 /* Scan and build the parameter part of the macro definition
*/
1983 get_token
(); /* set |cur_cmd|
, |cur_chr|
, |cur_tok|
*/
1984 if
(cur_tok
< right_brace_limit
)
1986 if
(cur_cmd
== mac_param_cmd
) {
1987 /* If the next character is a parameter number
, make |cur_tok|
1988 a |match| token
; but if it is a left brace
, store
1989 `|left_brace|
, |end_match|'
, set |hash_brace|
, and |goto done|
;
1991 s
= match_token
+ cur_chr
;
1993 if
(cur_cmd
== left_brace_cmd
) {
1994 hash_brace
= cur_tok
;
1995 store_new_token
(cur_tok
);
1996 store_new_token
(end_match_token
);
1999 if
(t
== zero_token
+ 9) {
2000 print_err
("You already have nine parameters");
2001 help1
("I'm going to ignore the # sign you just used.");
2006 print_err
("Parameters must be numbered consecutively");
2008 ("I've inserted the digit you should have used after the #.",
2009 "Type `1' to delete what you did use.");
2015 store_new_token
(cur_tok
);
2017 store_new_token
(end_match_token
);
2018 if
(cur_cmd
== right_brace_cmd
) {
2019 /* Express shock at the missing left brace
; |goto found|
*/
2020 print_err
("Missing { inserted");
2023 ("Where was the left brace? You said something like `\\def\\a}',",
2024 "which I'm going to interpret as `\\def\\a{}'.");
2030 scan_left_brace
(); /* remove the compulsory left brace
*/
2033 /* Scan and build the body of the token list
; |goto found| when finished
*/
2037 /* Expand the next part of the input
*/
2038 /* Here we insert an entire token list created by |the_toks| without
2039 expanding it further.
*/
2042 if
(cur_cmd
>= call_cmd
) {
2043 if
(token_info
(token_link
(cur_chr
)) == protected_token
) {
2044 cur_cmd
= relax_cmd
;
2045 cur_chr
= no_expand_flag
;
2048 if
(cur_cmd
<= max_command_cmd
)
2050 if
(cur_cmd
!= the_cmd
) {
2054 if
(token_link
(temp_token_head
) != null
) {
2055 set_token_link
(p
, token_link
(temp_token_head
));
2065 if
(cur_tok
< right_brace_limit
) {
2066 if
(cur_cmd
< right_brace_cmd
) {
2073 } else if
(cur_cmd
== mac_param_cmd
) {
2075 /* Look for parameter number or \.
{\#\#
} */
2081 if
(cur_cmd
!= mac_param_cmd
) {
2082 if
((cur_tok
<= zero_token
) ||
(cur_tok
> t
)) {
2083 print_err
("Illegal parameter number in definition of ");
2084 sprint_cs
(warning_index
);
2085 help3
("You meant to type ## instead of #, right?",
2086 "Or maybe a } was forgotten somewhere earlier, and things",
2087 "are all screwed up? I'm going to assume that you meant ##.");
2091 cur_tok
= out_param_token
- '
0'
+ cur_chr
;
2096 store_new_token
(cur_tok
);
2099 scanner_status
= normal
;
2100 if
(hash_brace
!= 0)
2101 store_new_token
(hash_brace
);
2106 @ Here we declare two trivial procedures in order to avoid mutually
2107 recursive procedures with parameters.
2110 void scan_normal_glue
(void
)
2112 scan_glue
(glue_val_level
);
2115 void scan_mu_glue
(void
)
2117 scan_glue
(mu_val_level
);
2120 @ The |scan_expr| procedure scans and evaluates an expression.
2122 @ Evaluating an expression is a recursive process
: When the left
2123 parenthesis of a subexpression is scanned we descend to the next level
2124 of recursion
; the previous level is resumed with the matching right
2129 expr_none
= 0, /* \.
( seen
, or \.
( $\langle\it expr\rangle$ \.
) seen
*/
2130 expr_add
= 1, /* \.
( $\langle\it expr\rangle$ \.
+ seen
*/
2131 expr_sub
= 2, /* \.
( $\langle\it expr\rangle$ \.
- seen
*/
2132 expr_mult
= 3, /* $\langle\it term\rangle$ \.
* seen
*/
2133 expr_div
= 4, /* $\langle\it term\rangle$ \.
/ seen
*/
2134 expr_scale
= 5, /* $\langle\it term\rangle$ \.
* $\langle\it factor\rangle$ \.
/ seen
*/
2135 } expression_states
;
2138 @ We want to make sure that each term and
(intermediate
) result is in
2139 the proper range. Integer values must not exceed |infinity|
2140 ($
2^
{31}-1$
) in absolute value
, dimensions must not exceed |max_dimen|
2141 ($
2^
{30}-1$
). We avoid the absolute value of an integer
, because this
2142 might fail for the value $
-2^
{31}$ using
32-bit arithmetic.
2144 @ clear a number or dimension and set |arith_error|
2147 #define num_error
(A
) do
{ \
2153 @ clear a glue spec and set |arith_error|
2156 #define glue_error
(A
) do
{ \
2158 delete_glue_ref
(A
); \
2159 A
=new_spec
(zero_glue
); \
2163 #define normalize_glue
(A
) do
{ \
2164 if
(stretch
(A
)==0) stretch_order
(A
)=normal
; \
2165 if
(shrink
(A
)==0) shrink_order
(A
)=normal
; \
2169 @ Parenthesized subexpressions can be inside expressions
, and this
2170 nesting has a stack. Seven local variables represent the top of the
2171 expression stack
: |p| points to pushed-down entries
, if any
; |l|
2172 specifies the type of expression currently beeing evaluated
; |e| is the
2173 expression so far and |r| is the state of its evaluation
; |t| is the
2174 term so far and |s| is the state of its evaluation
; finally |n| is the
2175 numerator for a combined multiplication and division
, if any.
2178 #define expr_type
(A
) type
((A
)+1)
2179 #define expr_state
(A
) subtype
((A
)+1)
2180 #define expr_e_field
(A
) vlink
((A
)+1) /* saved expression so far
*/
2181 #define expr_t_field
(A
) vlink
((A
)+2) /* saved term so far
*/
2182 #define expr_n_field
(A
) vinfo
((A
)+2) /* saved numerator
*/
2185 #define expr_add_sub
(A
,B
,C
) add_or_sub
((A
),(B
),(C
),(r
==expr_sub
))
2186 #define expr_a
(A
,B
) expr_add_sub
((A
),(B
),max_dimen
)
2189 The function |add_or_sub
(x
,y
,max_answer
,negative
)| computes the sum
2190 (for |negative
=false|
) or difference
(for |negative
=true|
) of |x| and
2191 |y|
, provided the absolute value of the result does not exceed
2195 int add_or_sub
(int x
, int y
, int max_answer
, boolean negative
)
2197 int a
; /* the answer
*/
2201 if
(y
<= max_answer
- x
)
2205 } else if
(y
>= -max_answer
- x
) {
2214 #define expr_m
(A
) A
= nx_plus_y
((A
),f
,0)
2216 #define expr_d
(A
) A
=quotient
((A
),f
)
2219 @ The function |quotient
(n
,d
)| computes the rounded quotient
2220 $q
=\lfloor n
/d
+{1\over2
}\rfloor$
, when $n$ and $d$ are positive.
2223 int quotient
(int n
, int d
)
2225 boolean negative
; /* should the answer be negated?
*/
2226 int a
; /* the answer
*/
2238 negative
= !negative
;
2242 d
= n
- d
; /* avoid certain compiler optimizations
! */
2251 #define expr_s
(A
) A
=fract
((A
),n
,f
,max_dimen
)
2254 @ Finally
, the function |fract
(x
,n
,d
,max_answer
)| computes the integer
2255 $q
=\lfloor xn
/d
+{1\over2
}\rfloor$
, when $x$
, $n$
, and $d$ are positive
2256 and the result does not exceed |max_answer|. We can't use floating
2257 point arithmetic since the routine must produce identical results in all
2258 cases
; and it would be too dangerous to multiply by~|n| and then divide
2259 by~|d|
, in separate operations
, since overflow might well occur. Hence
2260 this subroutine simulates double precision arithmetic
, somewhat
2261 analogous to Metafont's |make_fraction| and |take_fraction| routines.
2264 int fract
(int x
, int n
, int d
, int max_answer
)
2266 boolean negative
; /* should the answer be negated?
*/
2267 int a
; /* the answer
*/
2268 int f
; /* a proper fraction
*/
2269 int h
; /* smallest integer such that |
2*h
>=d|
*/
2270 int r
; /* intermediate remainder
*/
2271 int t
; /* temp variable
*/
2283 negative
= !negative
;
2284 } else if
(x
== 0) {
2289 negative
= !negative
;
2292 if
(t
> max_answer
/ x
)
2299 if
(t
> (max_answer
- a
) / n
)
2312 /* now |
0<n
<=x
<d|
*/
2313 /* Compute $f
=\lfloor xn
/d
+{1\over2
}\rfloor$
; */
2314 /* The loop here preserves the following invariant relations
2315 between |f|
, |x|
, |n|
, and~|r|
:
2316 (i
)~$f
+\lfloor
(xn
+(r
+d
))/d\rfloor
=\lfloor x_0n_0
/d
+{1\over2
}\rfloor$
;
2317 (ii
)~|
-d
<=r
<0<n
<=x
<d|
, where $x_0$
, $n_0$ are the original values of~$x$
2319 /* Notice that the computation specifies |
(x-d
)+x| instead of |
(x
+x
)-d|
,
2320 because the latter could overflow.
*/
2351 if
(f
> (max_answer
- a
))
2365 void scan_expr
(void
)
2366 { /* scans and evaluates an expression
*/
2367 boolean a
, b
; /* saved values of |arith_error|
*/
2368 int l
; /* type of expression
*/
2369 int r
; /* state of expression so far
*/
2370 int s
; /* state of term so far
*/
2371 int o
; /* next operation or type of next factor
*/
2372 int e
; /* expression so far
*/
2373 int t
; /* term so far
*/
2374 int f
; /* current factor
*/
2375 int n
; /* numerator of combined multiplication and division
*/
2376 halfword p
; /* top of expression stack
*/
2377 halfword q
; /* for stack manipulations
*/
2382 /* Scan and evaluate an expression |e| of type |l|
*/
2394 /* Scan a factor |f| of type |o| or start a subexpression
*/
2395 /* Get the next non-blank non-call token
*/
2398 } while
(cur_cmd
== spacer_cmd
);
2400 if
(cur_tok
== other_token
+ '
('
) {
2401 /* Push the expression stack and |goto restart|
*/
2402 q
= new_node
(expr_node
, 0);
2404 expr_type
(q
) = (quarterword
) l
;
2405 expr_state
(q
) = (quarterword
) (4 * s
+ r
);
2406 expr_e_field
(q
) = e
;
2407 expr_t_field
(q
) = t
;
2408 expr_n_field
(q
) = n
;
2414 if
((o
== int_val_level
) ||
(o
== attr_val_level
))
2416 else if
(o
== dimen_val_level
)
2417 scan_normal_dimen
();
2418 else if
(o
== glue_val_level
)
2425 /* Scan the next operator and set |o|
*/
2426 /* Get the next non-blank non-call token
*/
2429 } while
(cur_cmd
== spacer_cmd
);
2431 if
(cur_tok
== other_token
+ '
+'
) {
2433 } else if
(cur_tok
== other_token
+ '
-'
) {
2435 } else if
(cur_tok
== other_token
+ '
*'
) {
2437 } else if
(cur_tok
== other_token
+ '
/'
) {
2442 if
(cur_cmd
!= relax_cmd
)
2444 } else if
(cur_tok
!= other_token
+ '
)'
) {
2445 print_err
("Missing ) inserted for expression");
2446 help1
("I was expecting to see `+', `-', `*', `/', or `)'. Didn't.");
2452 /* Make sure that |f| is in the proper range
*/
2453 if
(((l
== int_val_level
) ||
(l
== attr_val_level
)) ||
(s
> expr_sub
)) {
2454 if
((f
> infinity
) ||
(f
< -infinity
))
2456 } else if
(l
== dimen_val_level
) {
2457 if
(abs
(f
) > max_dimen
)
2460 if
((abs
(width
(f
)) > max_dimen
) ||
2461 (abs
(stretch
(f
)) > max_dimen
) ||
(abs
(shrink
(f
)) > max_dimen
))
2466 /* Cases for evaluation of the current term
*/
2469 Applying the factor |f| to the partial term |t|
(with the operator
2470 |s|
) is delayed until the next operator |o| has been scanned. Here we
2471 handle the first factor of a partial term. A glue spec has to be copied
2472 unless the next operator is a right parenthesis
; this allows us later on
2473 to simply modify the glue components.
2475 if
((l
>= glue_val_level
) && (o != expr_none)) {
2484 /* If a multiplication is followed by a division
, the two operations are
2485 combined into a `scaling' operation. Otherwise the term |t| is
2486 multiplied by the factor |f|.
*/
2487 if
(o
== expr_div
) {
2490 } else if
((l
== int_val_level
) ||
(l
== attr_val_level
)) {
2491 t
= mult_integers
(t
, f
);
2492 } else if
(l
== dimen_val_level
) {
2501 /* Here we divide the term |t| by the factor |f|
*/
2502 if
(l
< glue_val_level
) {
2511 /* Here the term |t| is multiplied by the quotient $n
/f$.
*/
2512 if
((l
== int_val_level
) ||
(l
== attr_val_level
)) {
2513 t
= fract
(t
, n
, f
, infinity
);
2514 } else if
(l
== dimen_val_level
) {
2523 } /* there are no other cases
*/
2527 /* Evaluate the current expression
*/
2528 /* When a term |t| has been completed it is copied to
, added to
, or
2529 subtracted from the expression |e|.
*/
2531 if
(r
== expr_none
) {
2533 } else if
((l
== int_val_level
) ||
(l
== attr_val_level
)) {
2534 e
= expr_add_sub
(e
, t
, infinity
);
2535 } else if
(l
== dimen_val_level
) {
2538 /* Compute the sum or difference of two glue specs
*/
2539 /* We know that |stretch_order
(e
)>normal| implies |stretch
(e
)<>0| and
2540 |shrink_order
(e
)>normal| implies |shrink
(e
)<>0|.
*/
2541 width
(e
) = expr_a
(width
(e
), width
(t
));
2542 if
(stretch_order
(e
) == stretch_order
(t
)) {
2543 stretch
(e
) = expr_a
(stretch
(e
), stretch
(t
));
2544 } else if
((stretch_order
(e
) < stretch_order
(t
))
2545 && (stretch(t) != 0)) {
2546 stretch
(e
) = stretch
(t
);
2547 stretch_order
(e
) = stretch_order
(t
);
2549 if
(shrink_order
(e
) == shrink_order
(t
)) {
2550 shrink
(e
) = expr_a
(shrink
(e
), shrink
(t
));
2551 } else if
((shrink_order
(e
) < shrink_order
(t
)) && (shrink(t) != 0)) {
2552 shrink
(e
) = shrink
(t
);
2553 shrink_order
(e
) = shrink_order
(t
);
2564 /* Pop the expression stack and |goto found|
*/
2567 e
= expr_e_field
(q
);
2568 t
= expr_t_field
(q
);
2569 n
= expr_n_field
(q
);
2570 s
= expr_state
(q
) / 4;
2571 r
= expr_state
(q
) % 4;
2579 print_err
("Arithmetic overflow");
2580 help2
("I can't evaluate this expression,",
2581 "since the result is out of range.");
2583 if
(l
>= glue_val_level
) {