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/>.
23
static const char _svn_version[] =
24
"$Id: scanning.w 3596 2010-04-05 10:12:46Z taco $"
25
"$URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.60.1/source/texk/web2c/luatexdir/tex/scanning.w $";
29
#define prev_depth cur_list.prev_depth_field
30
#define space_factor cur_list.space_factor_field
31
#define par_shape_ptr equiv(par_shape_loc)
32
#define font_id_text(A) cs_text(font_id_base+(A))
34
#define attribute(A) eqtb[attribute_base+(A)].hh.rh
35
#define dimen(A) eqtb[scaled_base+(A)].hh.rh
37
#define skip(A) eqtb[skip_base+(A)].hh.rh
38
#define mu_skip(A) eqtb[mu_skip_base+(A)].hh.rh
39
#define count(A) eqtb[count_base+(A)].hh.rh
40
#define box(A) equiv(box_base+(A))
42
#define text_direction int_par(text_direction_code)
43
#define body_direction int_par(body_direction_code)
46
@ Let's turn now to some procedures that \TeX\ calls upon frequently to digest
47
certain kinds of patterns in the input. Most of these are quite simple;
48
some are quite elaborate. Almost all of the routines call |get_x_token|,
49
which can cause them to be invoked recursively.
51
The |scan_left_brace| routine is called when a left brace is supposed to be
52
the next non-blank token. (The term ``left brace'' means, more precisely,
53
a character whose catcode is |left_brace|.) \TeX\ allows \.{\\relax} to
54
appear before the |left_brace|.
57
void scan_left_brace(void)
58
{ /* reads a mandatory |left_brace| */
59
/* Get the next non-blank non-relax non-call token */
62
} while ((cur_cmd == spacer_cmd) || (cur_cmd == relax_cmd));
64
if (cur_cmd != left_brace_cmd) {
65
print_err("Missing { inserted");
66
help4("A left brace was mandatory here, so I've put one in.",
67
"You might want to delete and/or insert some corrections",
68
"so that I will find a matching right brace soon.",
69
"If you're confused by all this, try typing `I}' now.");
71
cur_tok = left_brace_token + '{';
72
cur_cmd = left_brace_cmd;
79
@ The |scan_optional_equals| routine looks for an optional `\.=' sign preceded
80
by optional spaces; `\.{\\relax}' is not ignored here.
83
void scan_optional_equals(void)
85
/* Get the next non-blank non-call token */
88
} while (cur_cmd == spacer_cmd);
89
if (cur_tok != other_token + '=')
94
@ Here is a procedure that sounds an alarm when mu and non-mu units
98
static void mu_error(void)
100
print_err("Incompatible glue units");
101
help1("I'm going to assume that 1mu=1pt when they're mixed.");
106
@ The next routine `|scan_something_internal|' is used to fetch internal
107
numeric quantities like `\.{\\hsize}', and also to handle the `\.{\\the}'
108
when expanding constructions like `\.{\\the\\toks0}' and
109
`\.{\\the\\baselineskip}'. Soon we will be considering the |scan_int|
110
procedure, which calls |scan_something_internal|; on the other hand,
111
|scan_something_internal| also calls |scan_int|, for constructions like
112
`\.{\\catcode\`\\\$}' or `\.{\\fontdimen} \.3 \.{\\ff}'. So we
113
have to declare |scan_int| as a |forward| procedure. A few other
114
procedures are also declared at this point.
116
\TeX\ doesn't know exactly what to expect when
117
|scan_something_internal| begins. For example, an integer or
118
dimension or glue value could occur immediately after `\.{\\hskip}';
119
and one can even say \.{\\the} with respect to token lists in
120
constructions like `\.{\\xdef\\o\{\\the\\output\}}'. On the other
121
hand, only integers are allowed after a construction like
122
`\.{\\count}'. To handle the various possibilities,
123
|scan_something_internal| has a |level| parameter, which tells the
124
``highest'' kind of quantity that |scan_something_internal| is allowed
125
to produce. Eight levels are distinguished, namely |int_val|,
126
|attr_val|, |dimen_val|, |glue_val|, |mu_val|, |dir_val|, |ident_val|,
129
The output of |scan_something_internal| (and of the other routines
130
|scan_int|, |scan_dimen|, and |scan_glue| below) is put into the global
131
variable |cur_val|, and its level is put into |cur_val_level|. The highest
132
values of |cur_val_level| are special: |mu_val| is used only when
133
|cur_val| points to something in a ``muskip'' register, or to one of the
134
three parameters \.{\\thinmuskip}, \.{\\medmuskip}, \.{\\thickmuskip};
135
|ident_val| is used only when |cur_val| points to a font identifier;
136
|tok_val| is used only when |cur_val| points to |null| or to the reference
137
count of a token list. The last two cases are allowed only when
138
|scan_something_internal| is called with |level=tok_val|.
140
If the output is glue, |cur_val| will point to a glue specification, and
141
the reference count of that glue will have been updated to reflect this
142
reference; if the output is a nonempty token list, |cur_val| will point to
143
its reference count, but in this case the count will not have been updated.
144
Otherwise |cur_val| will contain the integer or scaled value in question.
147
int cur_val; /* value returned by numeric scanners */
148
int cur_val1; /* delcodes are sometimes 51 digits */
149
int cur_val_level; /* the ``level'' of this value */
151
#define scanned_result(A,B) do { \
157
@ When a |glue_val| changes to a |dimen_val|, we use the width component
158
of the glue; there is no need to decrease the reference count, since it
159
has not yet been increased. When a |dimen_val| changes to an |int_val|,
160
we use scaled points so that the value doesn't actually change. And when a
161
|mu_val| changes to a |glue_val|, the value doesn't change either.
164
static void downgrade_cur_val(boolean delete_glue)
167
if (cur_val_level == glue_val_level) {
172
} else if (cur_val_level == mu_val_level) {
178
static void negate_cur_val(boolean delete_glue)
181
if (cur_val_level >= glue_val_level) {
183
cur_val = new_spec(m);
186
/* Negate all three glue components of |cur_val| */
187
negate(width(cur_val));
188
negate(stretch(cur_val));
189
negate(shrink(cur_val));
197
@ Some of the internal items can be fetched both routines,
198
and these have been split off into the next routine, that
199
returns true if the command code was understood
202
static boolean short_scan_something_internal(int cmd, int chr, int level,
205
halfword m; /* |chr_code| part of the operand token */
206
halfword q; /* general purpose index */
207
int p; /* index into |nest| */
209
boolean succeeded = true;
212
case assign_toks_cmd:
213
scanned_result(equiv(m), tok_val_level);
216
scanned_result(eqtb[m].cint, int_val_level);
218
case assign_attr_cmd:
219
scanned_result(eqtb[m].cint, int_val_level);
222
scanned_result(eqtb[m].cint, dir_val_level);
224
case assign_dimen_cmd:
225
scanned_result(eqtb[m].cint, dimen_val_level);
227
case assign_glue_cmd:
228
scanned_result(equiv(m), glue_val_level);
230
case assign_mu_glue_cmd:
231
scanned_result(equiv(m), mu_val_level);
234
scanned_result(m, int_val_level);
237
/* Fetch the |space_factor| or the |prev_depth| */
238
if (abs(cur_list.mode_field) != m) {
239
print_err("Improper ");
240
print_cmd_chr(set_aux_cmd, m);
241
help4("You can refer to \\spacefactor only in horizontal mode;",
242
"you can refer to \\prevdepth only in vertical mode; and",
243
"neither of these is meaningful inside \\write. So",
244
"I'm forgetting what you said and using zero instead.");
246
if (level != tok_val_level)
247
scanned_result(0, dimen_val_level);
249
scanned_result(0, int_val_level);
250
} else if (m == vmode) {
251
scanned_result(prev_depth, dimen_val_level);
253
scanned_result(space_factor, int_val_level);
256
case set_prev_graf_cmd:
257
/* Fetch the |prev_graf| */
258
if (cur_list.mode_field == 0) {
259
scanned_result(0, int_val_level); /* |prev_graf=0| within \.{\\write} */
262
while (abs(nest[p].mode_field) != vmode)
264
scanned_result(nest[p].pg_field, int_val_level);
267
case set_page_int_cmd:
268
/* Fetch the |dead_cycles| or the |insert_penalties| */
270
cur_val = dead_cycles;
272
cur_val = interaction; /* interactionmode */
274
cur_val = insert_penalties;
275
cur_val_level = int_val_level;
277
case set_page_dimen_cmd:
278
/* Fetch something on the |page_so_far| */
279
if ((page_contents == empty) && (!output_active)) {
285
cur_val = page_so_far[m];
287
cur_val_level = dimen_val_level;
289
case set_tex_shape_cmd:
290
/* Fetch the |par_shape| size */
291
if (par_shape_ptr == null)
294
cur_val = vinfo(par_shape_ptr + 1);
295
cur_val_level = int_val_level;
297
case set_etex_shape_cmd:
298
/* Fetch a penalties array element */
300
if ((equiv(m) == null) || (cur_val < 0)) {
303
if (cur_val > penalty(equiv(m)))
304
cur_val = penalty(equiv(m));
305
cur_val = penalty(equiv(m) + cur_val);
307
cur_val_level = int_val_level;
311
case omath_given_cmd:
312
case xmath_given_cmd:
313
scanned_result(cur_chr, int_val_level);
316
/* Because the items in this case directly refer to |cur_chr|,
317
it needs to be saved and restored */
318
save_cur_chr = cur_chr;
320
/* Fetch an item in the current node, if appropriate */
321
/* Here is where \.{\\lastpenalty}, \.{\\lastkern}, and \.{\\lastskip} are
322
implemented. The reference count for \.{\\lastskip} will be updated later.
324
We also handle \.{\\inputlineno} and \.{\\badness} here, because they are
325
legal in similar contexts. */
327
if (m >= input_line_no_code) {
328
if (m >= eTeX_glue) {
329
/* Process an expression and |return| */
332
case mu_to_glue_code:
335
}; /* there are no other cases */
336
cur_val_level = glue_val_level;
337
} else if (m < eTeX_expr) {
339
case glue_to_mu_code:
342
} /* there are no other cases */
343
cur_val_level = mu_val_level;
345
cur_val_level = m - eTeX_expr + int_val_level;
348
/* This code for reducing |cur_val_level| and\slash or negating the
349
result is similar to the one for all the other cases of
350
|scan_something_internal|, with the difference that |scan_expr| has
351
already increased the reference count of a glue specification.
353
while (cur_val_level > level) {
354
downgrade_cur_val(true);
357
negate_cur_val(true);
361
} else if (m >= eTeX_dim) {
363
case font_char_wd_code:
364
case font_char_ht_code:
365
case font_char_dp_code:
366
case font_char_ic_code:
370
if (char_exists(q, cur_val)) {
372
case font_char_wd_code:
373
cur_val = char_width(q, cur_val);
375
case font_char_ht_code:
376
cur_val = char_height(q, cur_val);
378
case font_char_dp_code:
379
cur_val = char_depth(q, cur_val);
381
case font_char_ic_code:
382
cur_val = char_italic(q, cur_val);
384
} /* there are no other cases */
389
case par_shape_length_code:
390
case par_shape_indent_code:
391
case par_shape_dimen_code:
392
q = cur_chr - par_shape_length_code;
394
if ((par_shape_ptr == null) || (cur_val <= 0)) {
399
cur_val = (cur_val + q) / 2;
401
if (cur_val > vinfo(par_shape_ptr + 1))
402
cur_val = vinfo(par_shape_ptr + 1);
404
varmem[par_shape_ptr + 2 * cur_val - q + 1].cint;
406
cur_val_level = dimen_val_level;
408
case glue_stretch_code:
409
case glue_shrink_code:
412
if (m == glue_stretch_code)
413
cur_val = stretch(q);
418
} /* there are no other cases */
419
cur_val_level = dimen_val_level;
422
case input_line_no_code:
426
cur_val = last_badness;
428
case pdftex_version_code:
429
cur_val = pdftex_version;
431
case luatex_version_code:
432
cur_val = get_luatexversion();
434
case pdf_last_obj_code:
435
cur_val = pdf_last_obj;
437
case pdf_last_xform_code:
438
cur_val = pdf_last_xform;
440
case pdf_last_ximage_code:
441
cur_val = pdf_last_ximage;
443
case pdf_last_ximage_pages_code:
444
cur_val = pdf_last_ximage_pages;
446
case pdf_last_annot_code:
447
cur_val = pdf_last_annot;
449
case pdf_last_x_pos_code:
450
cur_val = pdf_last_pos.h;
452
case pdf_last_y_pos_code:
453
cur_val = pdf_last_pos.v;
455
case pdf_retval_code:
456
cur_val = pdf_retval;
458
case pdf_last_ximage_colordepth_code:
459
cur_val = pdf_last_ximage_colordepth;
461
case random_seed_code:
462
cur_val = random_seed;
464
case pdf_last_link_code:
465
cur_val = pdf_last_link;
467
case Aleph_version_code:
468
cur_val = Aleph_version;
470
case Omega_version_code:
471
cur_val = Omega_version;
473
case eTeX_version_code:
474
cur_val = eTeX_version;
476
case Aleph_minor_version_code:
477
cur_val = Aleph_minor_version;
479
case Omega_minor_version_code:
480
cur_val = Omega_minor_version;
482
case eTeX_minor_version_code:
483
cur_val = eTeX_minor_version;
485
case current_group_level_code:
486
cur_val = cur_level - level_one;
488
case current_group_type_code:
491
case current_if_level_code:
499
case current_if_type_code:
500
if (cond_ptr == null)
502
else if (cur_if < unless_code)
503
cur_val = cur_if + 1;
505
cur_val = -(cur_if - unless_code + 1);
507
case current_if_branch_code:
508
if ((if_limit == or_code) || (if_limit == else_code))
510
else if (if_limit == fi_code)
515
case glue_stretch_order_code:
516
case glue_shrink_order_code:
519
if (m == glue_stretch_order_code)
520
cur_val = stretch_order(q);
522
cur_val = shrink_order(q);
526
} /* there are no other cases */
527
cur_val_level = int_val_level;
530
if (cur_chr == glue_val_level)
534
if (cur_chr == last_node_type_code) {
535
cur_val_level = int_val_level;
536
if ((cur_list.tail_field == cur_list.head_field)
537
|| (cur_list.mode_field == 0))
540
cur_val_level = cur_chr; /* assumes identical values */
542
if ((cur_list.tail_field != contrib_head) &&
543
!is_char_node(cur_list.tail_field) &&
544
(cur_list.mode_field != 0)) {
546
case lastpenalty_code:
547
if (type(cur_list.tail_field) == penalty_node)
548
cur_val = penalty(cur_list.tail_field);
551
if (type(cur_list.tail_field) == kern_node)
552
cur_val = width(cur_list.tail_field);
555
if (type(cur_list.tail_field) == glue_node)
556
cur_val = glue_ptr(cur_list.tail_field);
557
if (subtype(cur_list.tail_field) == mu_glue)
558
cur_val_level = mu_val_level;
560
case last_node_type_code:
561
cur_val = visible_last_node_type(cur_list.tail_field);
563
} /* there are no other cases */
564
} else if ((cur_list.mode_field == vmode)
565
&& (cur_list.tail_field == cur_list.head_field)) {
567
case lastpenalty_code:
568
cur_val = last_penalty;
574
if (last_glue != max_halfword)
577
case last_node_type_code:
578
cur_val = last_node_type;
580
} /* there are no other cases */
583
cur_chr = save_cur_chr;
589
while (cur_val_level > level) {
590
/* Convert |cur_val| to a lower level */
591
downgrade_cur_val(false);
593
/* Fix the reference count, if any, and negate |cur_val| if |negative| */
594
/* If |cur_val| points to a glue specification at this point, the reference
595
count for the glue does not yet include the reference by |cur_val|.
596
If |negative| is |true|, |cur_val_level| is known to be |<=mu_val|.
599
negate_cur_val(false);
600
} else if ((cur_val_level >= glue_val_level)
601
&& (cur_val_level <= mu_val_level)) {
602
add_glue_ref(cur_val);
608
@ First, here is a short routine that is called from lua code. All
609
the real work is delegated to |short_scan_something_internal| that
610
is shared between this routine and |scan_something_internal|.
613
void scan_something_simple(halfword cmd, halfword subitem)
615
/* negative is never true */
616
if (!short_scan_something_internal(cmd, subitem, tok_val_level, false)) {
617
/* Complain that |texlib| can not do this; give zero result */
618
print_err("You can't use `");
619
print_cmd_chr((quarterword) cmd, subitem);
620
tprint("' as tex library index");
621
help1("I'm forgetting what you said and using zero instead.");
623
scanned_result(0, int_val_level);
629
@ OK, we're ready for |scan_something_internal| itself. A second parameter,
630
|negative|, is set |true| if the value that is found should be negated.
631
It is assumed that |cur_cmd| and |cur_chr| represent the first token of
632
the internal quantity to be scanned; an error will be signalled if
633
|cur_cmd<min_internal| or |cur_cmd>max_internal|.
636
void scan_something_internal(int level, boolean negative)
638
/* fetch an internal parameter */
639
halfword m; /* |chr_code| part of the operand token */
640
int n, k; /* accumulators */
643
if (!short_scan_something_internal(cur_cmd, cur_chr, level, negative)) {
645
case def_char_code_cmd:
646
/* Fetch a character code from some table */
648
if (m == math_code_base) {
649
cur_val1 = get_math_code_num(cur_val);
650
scanned_result(cur_val1, int_val_level);
651
} else if (m == lc_code_base) {
652
cur_val1 = get_lc_code(cur_val);
653
scanned_result(cur_val1, int_val_level);
654
} else if (m == uc_code_base) {
655
cur_val1 = get_uc_code(cur_val);
656
scanned_result(cur_val1, int_val_level);
657
} else if (m == sf_code_base) {
658
cur_val1 = get_sf_code(cur_val);
659
scanned_result(cur_val1, int_val_level);
660
} else if (m == cat_code_base) {
661
cur_val1 = get_cat_code(int_par(cat_code_table_code), cur_val);
662
scanned_result(cur_val1, int_val_level);
664
confusion("def_char");
667
case def_del_code_cmd:
668
/* Fetch a character code from some table */
670
cur_val1 = get_del_code_num(cur_val);
671
scanned_result(cur_val1, int_val_level);
673
case extdef_math_code_cmd:
674
/* Fetch an extended math code table value */
676
cur_val1 = get_math_code_num(cur_val);
677
scanned_result(cur_val1, int_val_level);
679
case toks_register_cmd:
682
case letterspace_font_cmd:
683
case pdf_copy_font_cmd:
684
/* Fetch a token list or font identifier, provided that |level=tok_val| */
685
if (level != tok_val_level) {
686
print_err("Missing number, treated as zero");
687
help3("A number should have been here; I inserted `0'.",
688
"(If you can't figure out why I needed to see a number,",
689
"look up `weird error' in the index to The TeXbook.)");
691
scanned_result(0, dimen_val_level);
692
} else if (cur_cmd == toks_register_cmd) {
694
m = toks_base + cur_val;
695
scanned_result(equiv(m), tok_val_level);
699
scanned_result(font_id_base + cur_val, ident_val_level);
703
/* Fetch a math font identifier */
705
cur_val1 = fam_fnt(cur_val, m);
706
scanned_result(font_id_base + cur_val1, ident_val_level);
708
case set_math_param_cmd:
709
/* Fetch a math param */
712
if (cur_cmd != math_style_cmd) {
713
print_err("Missing math style, treated as \\displaystyle");
715
("A style should have been here; I inserted `\\displaystyle'.");
716
cur_val = display_style;
721
if (cur_val1 < math_param_first_mu_glue) {
722
if (cur_val1 == math_param_radical_degree_raise) {
723
cur_val1 = get_math_param(cur_val1, cur_chr);
724
scanned_result(cur_val1, int_val_level);
726
cur_val1 = get_math_param(cur_val1, cur_chr);
727
scanned_result(cur_val1, dimen_val_level);
730
cur_val1 = get_math_param(cur_val1, cur_chr);
731
if (cur_val1 == thin_mu_skip_code)
732
cur_val1 = glue_par(thin_mu_skip_code);
733
else if (cur_val1 == med_mu_skip_code)
734
cur_val1 = glue_par(med_mu_skip_code);
735
else if (cur_val1 == thick_mu_skip_code)
736
cur_val1 = glue_par(thick_mu_skip_code);
737
scanned_result(cur_val1, mu_val_level);
740
case assign_box_dir_cmd:
744
cur_val = box_dir(box(m));
747
cur_val_level = dir_val_level;
749
case set_box_dimen_cmd:
750
/* Fetch a box dimension */
752
if (box(cur_val) == null)
755
cur_val = varmem[box(cur_val) + m].cint;
756
cur_val_level = dimen_val_level;
758
case assign_font_dimen_cmd:
759
/* Fetch a font dimension */
762
case assign_font_int_cmd:
763
/* Fetch a font integer */
766
scanned_result(hyphen_char(cur_val), int_val_level);
768
scanned_result(skew_char(cur_val), int_val_level);
769
} else if (m == no_lig_code) {
770
scanned_result(test_no_ligatures(cur_val), int_val_level);
777
scanned_result(get_lp_code(n, k), int_val_level);
780
scanned_result(get_rp_code(n, k), int_val_level);
783
scanned_result(get_ef_code(n, k), int_val_level);
786
scanned_result(get_tag_code(n, k), int_val_level);
792
/* Fetch a register */
796
cur_val = count(cur_val);
799
cur_val = attribute(cur_val);
801
case dimen_val_level:
802
cur_val = dimen(cur_val);
805
cur_val = skip(cur_val);
808
cur_val = mu_skip(cur_val);
810
} /* there are no other cases */
813
case ignore_spaces_cmd: /* trap unexpandable primitives */
815
/* Reset |cur_tok| for unexpandable primitives, goto restart */
816
/* This block deals with unexpandable \.{\\primitive} appearing at a spot where
817
an integer or an internal values should have been found. It fetches the
818
next token then resets |cur_cmd|, |cur_cs|, and |cur_tok|, based on the
819
primitive value of that token. No expansion takes place, because the
820
next token may be all sorts of things. This could trigger further
821
expansion creating new errors.
824
cur_cs = prim_lookup(cs_text(cur_cs));
825
if (cur_cs != undefined_primitive) {
826
cur_cmd = get_prim_eq_type(cur_cs);
827
cur_chr = get_prim_equiv(cur_cs);
828
cur_tok = token_val(cur_cmd, cur_chr);
832
cur_tok = cs_token_flag + frozen_relax;
833
cur_cs = frozen_relax;
839
/* Complain that \.{\\the} can not do this; give zero result */
840
print_err("You can't use `");
841
print_cmd_chr((quarterword) cur_cmd, cur_chr);
842
tprint("' after \\the");
843
help1("I'm forgetting what you said and using zero instead.");
845
if (level != tok_val_level)
846
scanned_result(0, dimen_val_level);
848
scanned_result(0, int_val_level);
851
while (cur_val_level > level) {
852
/* Convert |cur_val| to a lower level */
853
downgrade_cur_val(false);
855
/* Fix the reference count, if any, and negate |cur_val| if |negative| */
856
/* If |cur_val| points to a glue specification at this point, the reference
857
count for the glue does not yet include the reference by |cur_val|.
858
If |negative| is |true|, |cur_val_level| is known to be |<=mu_val|.
861
negate_cur_val(false);
862
} else if ((cur_val_level >= glue_val_level) &&
863
(cur_val_level <= mu_val_level)) {
864
add_glue_ref(cur_val);
870
@ It is nice to have routines that say what they do, so the original
871
|scan_eight_bit_int| is superceded by |scan_register_num| and
872
|scan_mark_num|. It may become split up even further in the future.
874
Many of the |restricted classes| routines are the essentially
875
the same except for the upper limit and the error message, so it makes
876
sense to combine these all into one function.
879
void scan_limited_int(int max, const char *name)
883
if ((cur_val < 0) || (cur_val > max)) {
886
"Since I expected to read a number between 0 and %d,",
888
print_err("Bad number");
891
snprintf(hlp, 80, "A %s must be between 0 and %d.", name, max);
892
snprintf(msg, 80, "Bad %s", name);
895
help2(hlp, "I changed this one to zero.");
902
void scan_fifteen_bit_int(void)
904
scan_real_fifteen_bit_int();
905
cur_val = ((cur_val / 0x1000) * 0x1000000) +
906
(((cur_val % 0x1000) / 0x100) * 0x10000) + (cur_val % 0x100);
910
void scan_fifty_one_bit_int(void)
914
if ((cur_val < 0) || (cur_val > 0777777777)) {
915
print_err("Bad delimiter code");
917
("A numeric delimiter (first part) must be between 0 and 2^{27}-1.",
918
"I changed this one to zero.");
924
if ((cur_val < 0) || (cur_val > 0xFFFFFF)) {
925
print_err("Bad delimiter code");
927
("A numeric delimiter (second part) must be between 0 and 2^{24}-1.",
928
"I changed this one to zero.");
937
@ To be able to determine whether \.{\\write18} is enabled from within
938
\TeX\ we also implement \.{\\eof18}. We sort of cheat by having an
939
additional route |scan_four_bit_int_or_18| which is the same as
940
|scan_four_bit_int| except it also accepts the value 18.
943
void scan_four_bit_int_or_18(void)
946
if ((cur_val < 0) || ((cur_val > 15) && (cur_val != 18))) {
947
print_err("Bad number");
948
help2("Since I expected to read a number between 0 and 15,",
949
"I changed this one to zero.");
957
void scan_string_argument(void)
962
while ((cur_cmd != right_brace_cmd)) {
963
if ((cur_cmd == letter_cmd) || (cur_cmd == other_char_cmd)) {
965
append_char(cur_chr);
966
} else if (cur_cmd == spacer_cmd) {
970
tprint("Bad token appearing in string argument");
975
/* todo: this was just conserving the string pool: */
977
if (str_eq_str("mi",s)) s="mi";
978
if (str_eq_str("mo",s)) s="mo";
979
if (str_eq_str("mn",s)) s="mn";
985
@ An integer number can be preceded by any number of spaces and `\.+' or
986
`\.-' signs. Then comes either a decimal constant (i.e., radix 10), an
987
octal constant (i.e., radix 8, preceded by~'), a hexadecimal constant
988
(radix 16, preceded by~"), an alphabetic constant (preceded by~`), or
989
an internal variable. After scanning is complete,
990
|cur_val| will contain the answer, which must be at most
991
$2^{31}-1=2147483647$ in absolute value. The value of |radix| is set to
992
10, 8, or 16 in the cases of decimal, octal, or hexadecimal constants,
993
otherwise |radix| is set to zero. An optional space follows a constant.
996
int radix; /* |scan_int| sets this to 8, 10, 16, or zero */
999
@ The |scan_int| routine is used also to scan the integer part of a
1000
fraction; for example, the `\.3' in `\.{3.14159}' will be found by
1001
|scan_int|. The |scan_dimen| routine assumes that |cur_tok=point_token|
1002
after the integer part of such a fraction has been scanned by |scan_int|,
1003
and that the decimal point has been backed up to be scanned again.
1007
{ /* sets |cur_val| to an integer */
1008
boolean negative; /* should the answer be negated? */
1009
int m; /* |$2^{31}$ / radix|, the threshold of danger */
1010
int d; /* the digit just scanned */
1011
boolean vacuous; /* have no digits appeared? */
1012
boolean OK_so_far; /* has an error message been issued? */
1015
/* Get the next non-blank non-sign token; set |negative| appropriately */
1018
/* Get the next non-blank non-call token */
1021
} while (cur_cmd == spacer_cmd);
1022
if (cur_tok == other_token + '-') {
1023
negative = !negative;
1024
cur_tok = other_token + '+';
1026
} while (cur_tok == other_token + '+');
1029
if (cur_tok == alpha_token) {
1030
/* Scan an alphabetic character code into |cur_val| */
1031
/* A space is ignored after an alphabetic character constant, so that
1032
such constants behave like numeric ones. */
1033
get_token(); /* suppress macro expansion */
1034
if (cur_tok < cs_token_flag) {
1036
if (cur_cmd <= right_brace_cmd) {
1037
if (cur_cmd == right_brace_cmd)
1042
} else { /* the value of a csname in this context is its name */
1043
str_number txt = cs_text(cur_tok - cs_token_flag);
1044
if (is_active_cs(txt))
1045
cur_val = active_cs_value(txt);
1046
else if (single_letter(txt))
1047
cur_val = pool_to_unichar(str_string(txt));
1049
cur_val = (biggest_char + 1);
1051
if (cur_val > biggest_char) {
1052
print_err("Improper alphabetic constant");
1053
help2("A one-character control sequence belongs after a ` mark.",
1054
"So I'm essentially inserting \\0 here.");
1058
/* Scan an optional space */
1060
if (cur_cmd != spacer_cmd)
1064
} else if (cur_tok == cs_token_flag + frozen_primitive) {
1065
/* Reset |cur_tok| for unexpandable primitives, goto restart */
1066
/* This block deals with unexpandable \.{\\primitive} appearing at a spot where
1067
an integer or an internal values should have been found. It fetches the
1068
next token then resets |cur_cmd|, |cur_cs|, and |cur_tok|, based on the
1069
primitive value of that token. No expansion takes place, because the
1070
next token may be all sorts of things. This could trigger further
1071
expansion creating new errors.
1074
cur_cs = prim_lookup(cs_text(cur_cs));
1075
if (cur_cs != undefined_primitive) {
1076
cur_cmd = get_prim_eq_type(cur_cs);
1077
cur_chr = get_prim_equiv(cur_cs);
1078
cur_tok = token_val(cur_cmd, cur_chr);
1080
cur_cmd = relax_cmd;
1082
cur_tok = cs_token_flag + frozen_relax;
1083
cur_cs = frozen_relax;
1086
} else if (cur_cmd == math_style_cmd) {
1088
} else if ((cur_cmd >= min_internal_cmd) && (cur_cmd <= max_internal_cmd)) {
1089
scan_something_internal(int_val_level, false);
1091
/* Scan a numeric constant */
1094
if (cur_tok == octal_token) {
1098
} else if (cur_tok == hex_token) {
1105
/* Accumulate the constant until |cur_tok| is not a suitable digit */
1107
if ((cur_tok < zero_token + radix) && (cur_tok >= zero_token)
1108
&& (cur_tok <= zero_token + 9)) {
1109
d = cur_tok - zero_token;
1110
} else if (radix == 16) {
1111
if ((cur_tok <= A_token + 5) && (cur_tok >= A_token)) {
1112
d = cur_tok - A_token + 10;
1113
} else if ((cur_tok <= other_A_token + 5)
1114
&& (cur_tok >= other_A_token)) {
1115
d = cur_tok - other_A_token + 10;
1123
if ((cur_val >= m) && ((cur_val > m) || (d > 7) || (radix != 10))) {
1125
print_err("Number too big");
1127
("I can only go up to 2147483647='17777777777=\"7FFFFFFF,",
1128
"so I'm using that number instead of yours.");
1134
cur_val = cur_val * radix + d;
1139
/* Express astonishment that no number was here */
1140
print_err("Missing number, treated as zero");
1141
help3("A number should have been here; I inserted `0'.",
1142
"(If you can't figure out why I needed to see a number,",
1143
"look up `weird error' in the index to The TeXbook.)");
1145
} else if (cur_cmd != spacer_cmd) {
1154
@ The following code is executed when |scan_something_internal| was
1155
called asking for |mu_val|, when we really wanted a ``mudimen'' instead
1159
static void coerce_glue(void)
1162
if (cur_val_level >= glue_val_level) {
1164
delete_glue_ref(cur_val);
1171
@ The |scan_dimen| routine is similar to |scan_int|, but it sets |cur_val| to
1172
a |scaled| value, i.e., an integral number of sp. One of its main tasks
1173
is therefore to interpret the abbreviations for various kinds of units and
1174
to convert measurements to scaled points.
1176
There are three parameters: |mu| is |true| if the finite units must be
1177
`\.{mu}', while |mu| is |false| if `\.{mu}' units are disallowed;
1178
|inf| is |true| if the infinite units `\.{fil}', `\.{fill}', `\.{filll}'
1179
are permitted; and |shortcut| is |true| if |cur_val| already contains
1180
an integer and only the units need to be considered.
1182
The order of infinity that was found in the case of infinite glue is returned
1183
in the global variable |cur_order|.
1186
int cur_order; /* order of infinity found by |scan_dimen| */
1189
@ Constructions like `\.{-\'77 pt}' are legal dimensions, so |scan_dimen|
1190
may begin with |scan_int|. This explains why it is convenient to use
1191
|scan_int| also for the integer part of a decimal fraction.
1193
Several branches of |scan_dimen| work with |cur_val| as an integer and
1194
with an auxiliary fraction |f|, so that the actual quantity of interest is
1195
$|cur_val|+|f|/2^{16}$. At the end of the routine, this ``unpacked''
1196
representation is put into the single word |cur_val|, which suddenly
1197
switches significance from |integer| to |scaled|.
1200
void scan_dimen(boolean mu, boolean inf, boolean shortcut)
1201
/* sets |cur_val| to a dimension */
1203
boolean negative; /* should the answer be negated? */
1204
int f; /* numerator of a fraction whose denominator is $2^{16}$ */
1205
/* Local variables for dimension calculations */
1206
int num, denom; /* conversion ratio for the scanned units */
1207
int k, kk; /* number of digits in a decimal fraction */
1208
halfword p, q; /* top of decimal digit stack */
1209
scaled v; /* an internal dimension */
1210
int save_cur_val; /* temporary storage of |cur_val| */
1213
arith_error = false;
1217
/* Get the next non-blank non-sign... */
1220
/* Get the next non-blank non-call token */
1223
} while (cur_cmd == spacer_cmd);
1224
if (cur_tok == other_token + '-') {
1225
negative = !negative;
1226
cur_tok = other_token + '+';
1228
} while (cur_tok == other_token + '+');
1230
if ((cur_cmd >= min_internal_cmd) && (cur_cmd <= max_internal_cmd)) {
1231
/* Fetch an internal dimension and |goto attach_sign|,
1232
or fetch an internal integer */
1234
scan_something_internal(mu_val_level, false);
1236
if (cur_val_level == mu_val_level)
1238
if (cur_val_level != int_val_level)
1241
scan_something_internal(dimen_val_level, false);
1242
if (cur_val_level == dimen_val_level)
1248
if (cur_tok == continental_point_token) {
1249
cur_tok = point_token;
1251
if (cur_tok != point_token) {
1257
if (cur_tok == continental_point_token)
1258
cur_tok = point_token;
1259
if ((radix == 10) && (cur_tok == point_token)) {
1260
/* Scan decimal fraction */
1261
/* When the following code is executed, we have |cur_tok=point_token|, but this
1262
token has been backed up using |back_input|; we must first discard it.
1264
It turns out that a decimal point all by itself is equivalent to `\.{0.0}'.
1265
Let's hope people don't use that fact. */
1269
get_token(); /* |point_token| is being re-scanned */
1272
if ((cur_tok > zero_token + 9) || (cur_tok < zero_token))
1274
if (k < 17) { /* digits for |k>=17| cannot affect the result */
1276
set_token_link(q, p);
1277
set_token_info(q, cur_tok - zero_token);
1282
for (kk = k; kk >= 1; kk--) {
1283
dig[kk - 1] = token_info(p);
1288
f = round_decimals(k);
1289
if (cur_cmd != spacer_cmd)
1294
if (cur_val < 0) { /* in this case |f=0| */
1295
negative = !negative;
1298
/* Scan units and set |cur_val| to $x\cdot(|cur_val|+f/2^{16})$, where there
1299
are |x| sp per unit; |goto attach_sign| if the units are internal */
1300
/* Now comes the harder part: At this point in the program, |cur_val| is a
1301
nonnegative integer and $f/2^{16}$ is a nonnegative fraction less than 1;
1302
we want to multiply the sum of these two quantities by the appropriate
1303
factor, based on the specified units, in order to produce a |scaled|
1304
result, and we want to do the calculation with fixed point arithmetic that
1309
/* Scan for (f)\.{fil} units; |goto attach_fraction| if found */
1310
/* In traditional TeX, a specification like `\.{filllll}' or `\.{fill L L
1311
L}' will lead to two error messages (one for each additional keyword
1313
Not so for luatex, it just parses the construct in reverse. */
1314
if (scan_keyword("filll")) {
1316
goto ATTACH_FRACTION;
1317
} else if (scan_keyword("fill")) {
1319
goto ATTACH_FRACTION;
1320
} else if (scan_keyword("fil")) {
1322
goto ATTACH_FRACTION;
1323
} else if (scan_keyword("fi")) {
1325
goto ATTACH_FRACTION;
1329
/* Scan for (u)units that are internal dimensions;
1330
|goto attach_sign| with |cur_val| set if found */
1331
save_cur_val = cur_val;
1332
/* Get the next non-blank non-call... */
1335
} while (cur_cmd == spacer_cmd);
1337
if ((cur_cmd < min_internal_cmd) || (cur_cmd > max_internal_cmd)) {
1341
scan_something_internal(mu_val_level, false);
1343
if (cur_val_level != mu_val_level)
1346
scan_something_internal(dimen_val_level, false);
1353
if (scan_keyword("em")) {
1354
v = (quad(get_cur_font()));
1355
} else if (scan_keyword("ex")) {
1356
v = (x_height(get_cur_font()));
1357
} else if (scan_keyword("px")) {
1358
v = dimen_par(pdf_px_dimen_code);
1362
/* Scan an optional space */
1364
if (cur_cmd != spacer_cmd)
1368
cur_val = nx_plus_y(save_cur_val, v, xn_over_d(v, f, 0200000));
1373
/* Scan for (m)\.{mu} units and |goto attach_fraction| */
1374
if (scan_keyword("mu")) {
1375
goto ATTACH_FRACTION;
1377
print_err("Illegal unit of measure (mu inserted)");
1378
help4("The unit of measurement in math glue must be mu.",
1379
"To recover gracefully from this error, it's best to",
1380
"delete the erroneous units; e.g., type `2' to delete",
1381
"two letters. (See Chapter 27 of The TeXbook.)");
1383
goto ATTACH_FRACTION;
1386
if (scan_keyword("true")) {
1387
/* Adjust (f)for the magnification ratio */
1389
if (int_par(mag_code) != 1000) {
1390
cur_val = xn_over_d(cur_val, 1000, int_par(mag_code));
1391
f = (1000 * f + 0200000 * tex_remainder) / int_par(mag_code);
1392
cur_val = cur_val + (f / 0200000);
1396
if (scan_keyword("pt"))
1397
goto ATTACH_FRACTION; /* the easy case */
1398
/* Scan for (a)all other units and adjust |cur_val| and |f| accordingly;
1399
|goto done| in the case of scaled points */
1401
/* The necessary conversion factors can all be specified exactly as
1402
fractions whose numerator and denominator add to 32768 or less.
1403
According to the definitions here, $\rm2660\,dd\approx1000.33297\,mm$;
1404
this agrees well with the value $\rm1000.333\,mm$ cited by Bosshard
1405
\^{Bosshard, Hans Rudolf}
1406
in {\sl Technische Grundlagen zur Satzherstellung\/} (Bern, 1980).
1407
The Didot point has been newly standardized in 1978;
1408
it's now exactly $\rm 1\,nd=0.375\,mm$.
1409
Conversion uses the equation $0.375=21681/20320/72.27\cdot25.4$.
1410
The new Cicero follows the new Didot point; $\rm 1\,nc=12\,nd$.
1411
These would lead to the ratios $21681/20320$ and $65043/5080$,
1413
The closest approximations supported by the algorithm would be
1414
$11183/10481$ and $1370/107$. In order to maintain the
1415
relation $\rm 1\,nc=12\,nd$, we pick the ratio $685/642$ for
1419
#define set_conversion(A,B) do { num=(A); denom=(B); } while(0)
1421
if (scan_keyword("in")) {
1422
set_conversion(7227, 100);
1423
} else if (scan_keyword("pc")) {
1424
set_conversion(12, 1);
1425
} else if (scan_keyword("cm")) {
1426
set_conversion(7227, 254);
1427
} else if (scan_keyword("mm")) {
1428
set_conversion(7227, 2540);
1429
} else if (scan_keyword("bp")) {
1430
set_conversion(7227, 7200);
1431
} else if (scan_keyword("dd")) {
1432
set_conversion(1238, 1157);
1433
} else if (scan_keyword("cc")) {
1434
set_conversion(14856, 1157);
1435
} else if (scan_keyword("nd")) {
1436
set_conversion(685, 642);
1437
} else if (scan_keyword("nc")) {
1438
set_conversion(1370, 107);
1439
} else if (scan_keyword("sp")) {
1442
/* Complain about unknown unit and |goto done2| */
1443
print_err("Illegal unit of measure (pt inserted)");
1444
help6("Dimensions can be in units of em, ex, in, pt, pc,",
1445
"cm, mm, dd, cc, nd, nc, bp, or sp; but yours is a new one!",
1446
"I'll assume that you meant to say pt, for printer's points.",
1447
"To recover gracefully from this error, it's best to",
1448
"delete the erroneous units; e.g., type `2' to delete",
1449
"two letters. (See Chapter 27 of The TeXbook.)");
1453
cur_val = xn_over_d(cur_val, num, denom);
1454
f = (num * f + 0200000 * tex_remainder) / denom;
1455
cur_val = cur_val + (f / 0200000);
1459
if (cur_val >= 040000)
1462
cur_val = cur_val * unity + f;
1464
/* Scan an optional space */
1466
if (cur_cmd != spacer_cmd)
1469
if (arith_error || (abs(cur_val) >= 010000000000)) {
1470
/* Report that this dimension is out of range */
1471
print_err("Dimension too large");
1472
help2("I can't work with sizes bigger than about 19 feet.",
1473
"Continue and I'll use the largest value I can.");
1475
cur_val = max_dimen;
1476
arith_error = false;
1483
@ The final member of \TeX's value-scanning trio is |scan_glue|, which
1484
makes |cur_val| point to a glue specification. The reference count of that
1485
glue spec will take account of the fact that |cur_val| is pointing to~it.
1487
The |level| parameter should be either |glue_val| or |mu_val|.
1489
Since |scan_dimen| was so much more complex than |scan_int|, we might expect
1490
|scan_glue| to be even worse. But fortunately, it is very simple, since
1491
most of the work has already been done.
1494
void scan_glue(int level)
1495
{ /* sets |cur_val| to a glue spec pointer */
1496
boolean negative; /* should the answer be negated? */
1497
halfword q; /* new glue specification */
1498
boolean mu; /* does |level=mu_val|? */
1499
mu = (level == mu_val_level);
1500
/* Get the next non-blank non-sign... */
1503
/* Get the next non-blank non-call token */
1506
} while (cur_cmd == spacer_cmd);
1507
if (cur_tok == other_token + '-') {
1508
negative = !negative;
1509
cur_tok = other_token + '+';
1511
} while (cur_tok == other_token + '+');
1513
if ((cur_cmd >= min_internal_cmd) && (cur_cmd <= max_internal_cmd)) {
1514
scan_something_internal(level, negative);
1515
if (cur_val_level >= glue_val_level) {
1516
if (cur_val_level != level)
1520
if (cur_val_level == int_val_level)
1521
scan_dimen(mu, false, true);
1522
else if (level == mu_val_level)
1526
scan_dimen(mu, false, false);
1530
/* Create a new glue specification whose width is |cur_val|; scan for its
1531
stretch and shrink components */
1532
q = new_spec(zero_glue);
1534
if (scan_keyword("plus")) {
1535
scan_dimen(mu, true, false);
1536
stretch(q) = cur_val;
1537
stretch_order(q) = (quarterword) cur_order;
1539
if (scan_keyword("minus")) {
1540
scan_dimen(mu, true, false);
1541
shrink(q) = cur_val;
1542
shrink_order(q) = (quarterword) cur_order;
1547
@ This is an omega routine
1549
void scan_scaled(void)
1550
{ /* sets |cur_val| to a scaled value */
1551
boolean negative; /* should the answer be negated? */
1552
int f; /* numerator of a fraction whose denominator is $2^{16}$ */
1553
int k, kk; /* number of digits in a decimal fraction */
1554
halfword p, q; /* top of decimal digit stack */
1556
arith_error = false;
1558
/* Get the next non-blank non-sign... */
1561
/* Get the next non-blank non-call token */
1564
} while (cur_cmd == spacer_cmd);
1565
if (cur_tok == other_token + '-') {
1566
negative = !negative;
1567
cur_tok = other_token + '+';
1569
} while (cur_tok == other_token + '+');
1572
if (cur_tok == continental_point_token)
1573
cur_tok = point_token;
1574
if (cur_tok != point_token) {
1580
if (cur_tok == continental_point_token)
1581
cur_tok = point_token;
1582
if ((radix == 10) && (cur_tok == point_token)) {
1583
/* Scan decimal fraction */
1584
/* TODO: merge this with the same block in |scan_dimen| */
1585
/* When the following code is executed, we have |cur_tok=point_token|, but this
1586
token has been backed up using |back_input|; we must first discard it.
1588
It turns out that a decimal point all by itself is equivalent to `\.{0.0}'.
1589
Let's hope people don't use that fact. */
1593
get_token(); /* |point_token| is being re-scanned */
1596
if ((cur_tok > zero_token + 9) || (cur_tok < zero_token))
1598
if (k < 17) { /* digits for |k>=17| cannot affect the result */
1600
set_token_link(q, p);
1601
set_token_info(q, cur_tok - zero_token);
1606
for (kk = k; kk >= 1; kk--) {
1607
dig[kk - 1] = token_info(p);
1612
f = round_decimals(k);
1613
if (cur_cmd != spacer_cmd)
1617
if (cur_val < 0) { /* in this case |f=0| */
1618
negative = !negative;
1621
if (cur_val > 040000)
1624
cur_val = cur_val * unity + f;
1625
if (arith_error || (abs(cur_val) >= 010000000000)) {
1626
print_err("Stack number too large");
1634
@ This procedure is supposed to scan something like `\.{\\skip\\count12}',
1635
i.e., whatever can follow `\.{\\the}', and it constructs a token list
1636
containing something like `\.{-3.0pt minus 0.5fill}'.
1639
halfword the_toks(void)
1641
int old_setting; /* holds |selector| setting */
1642
halfword p, q, r; /* used for copying a token list */
1643
int c; /* value of |cur_chr| */
1646
/* Handle \.{\\unexpanded} or \.{\\detokenize} and |return| */
1649
scan_general_text();
1653
old_setting = selector;
1654
selector = new_string;
1656
set_token_link(p, token_link(temp_token_head));
1659
selector = old_setting;
1661
retval = str_toks(str_lstring(s));
1667
scan_something_internal(tok_val_level, false);
1668
if (cur_val_level >= ident_val_level) {
1669
/* Copy the token list */
1670
p = temp_token_head;
1671
set_token_link(p, null);
1672
if (cur_val_level == ident_val_level) {
1673
store_new_token(cs_token_flag + cur_val);
1674
} else if (cur_val != null) {
1675
r = token_link(cur_val); /* do not copy the reference count */
1677
fast_store_new_token(token_info(r));
1683
old_setting = selector;
1684
selector = new_string;
1685
switch (cur_val_level) {
1689
case attr_val_level:
1695
case dimen_val_level:
1696
print_scaled(cur_val);
1699
case glue_val_level:
1700
print_spec(cur_val, "pt");
1701
delete_glue_ref(cur_val);
1704
print_spec(cur_val, "mu");
1705
delete_glue_ref(cur_val);
1707
} /* there are no other cases */
1708
selector = old_setting;
1710
retval = str_toks(str_lstring(s));
1717
str_number the_scanned_result(void)
1719
int old_setting; /* holds |selector| setting */
1720
str_number r; /* return value * */
1721
old_setting = selector;
1722
selector = new_string;
1723
if (cur_val_level >= ident_val_level) {
1724
if (cur_val != null) {
1725
show_token_list(token_link(cur_val), null, -1);
1731
switch (cur_val_level) {
1735
case attr_val_level:
1741
case dimen_val_level:
1742
print_scaled(cur_val);
1745
case glue_val_level:
1746
print_spec(cur_val, "pt");
1747
delete_glue_ref(cur_val);
1750
print_spec(cur_val, "mu");
1751
delete_glue_ref(cur_val);
1753
} /* there are no other cases */
1756
selector = old_setting;
1762
@ The following routine is used to implement `\.{\\fontdimen} |n| |f|'.
1763
The boolean parameter |writing| is set |true| if the calling program
1764
intends to change the parameter value.
1767
static void font_param_error(int f)
1770
print_esc(font_id_text(f));
1771
tprint(" has only ");
1772
print_int(font_params(f));
1773
tprint(" fontdimen parameters");
1774
help2("To increase the number of font parameters, you must",
1775
"use \\fontdimen immediately after the \\font is loaded.");
1779
void set_font_dimen(void)
1781
internal_font_number f;
1782
int n; /* the parameter number */
1788
font_param_error(f);
1790
if (n > font_params(f)) {
1792
font_param_error(f);
1794
/* Increase the number of parameters in the font */
1796
set_font_param(f, (font_params(f) + 1), 0);
1797
} while (n != font_params(f));
1801
scan_optional_equals();
1802
scan_normal_dimen();
1803
set_font_param(f, n, cur_val);
1806
void get_font_dimen(void)
1808
internal_font_number f;
1809
int n; /* the parameter number */
1814
cur_val = 0; /* initialize return value */
1816
font_param_error(f);
1819
if (n > font_params(f)) {
1821
font_param_error(f);
1824
/* Increase the number of parameters in the font */
1826
set_font_param(f, (font_params(f) + 1), 0);
1827
} while (n != font_params(f));
1832
cur_val = font_param(f, n);
1834
scanned_result(cur_val, dimen_val_level);
1838
@ Here's a similar procedure that returns a pointer to a rule node. This
1839
routine is called just after \TeX\ has seen \.{\\hrule} or \.{\\vrule};
1840
therefore |cur_cmd| will be either |hrule| or |vrule|. The idea is to store
1841
the default rule dimensions in the node, then to override them if
1842
`\.{height}' or `\.{width}' or `\.{depth}' specifications are
1843
found (in any order).
1846
halfword scan_rule_spec(void)
1848
halfword q; /* the rule node being created */
1849
q = new_rule(); /* |width|, |depth|, and |height| all equal |null_flag| now */
1850
if (cur_cmd == vrule_cmd) {
1851
width(q) = default_rule;
1852
rule_dir(q) = body_direction;
1854
height(q) = default_rule;
1856
rule_dir(q) = text_direction;
1859
if (scan_keyword("width")) {
1860
scan_normal_dimen();
1864
if (scan_keyword("height")) {
1865
scan_normal_dimen();
1866
height(q) = cur_val;
1869
if (scan_keyword("depth")) {
1870
scan_normal_dimen();
1878
@ Declare procedures that scan font-related stuff
1881
void scan_font_ident(void)
1883
internal_font_number f;
1885
/* Get the next non-blank non-call... */
1888
} while (cur_cmd == spacer_cmd);
1890
if ((cur_cmd == def_font_cmd) || (cur_cmd == letterspace_font_cmd)
1891
|| (cur_cmd == pdf_copy_font_cmd)) {
1893
} else if (cur_cmd == set_font_cmd) {
1895
set_font_touched(f, 1);
1896
} else if (cur_cmd == def_family_cmd) {
1898
scan_math_family_int();
1899
f = fam_fnt(cur_val, m);
1900
set_font_touched(f, 1);
1902
print_err("Missing font identifier");
1903
help2("I was looking for a control sequence whose",
1904
"current meaning has been defined by \\font.");
1911
@ The |scan_general_text| procedure is much like |scan_toks(false,false)|,
1912
but will be invoked via |expand|, i.e., recursively.
1914
The token list (balanced text) created by |scan_general_text| begins
1915
at |link(temp_token_head)| and ends at |cur_val|. (If |cur_val=temp_token_head|,
1919
void scan_general_text(void)
1921
int s; /* to save |scanner_status| */
1922
halfword w; /* to save |warning_index| */
1923
halfword d; /* to save |def_ref| */
1924
halfword p; /* tail of the token list being built */
1925
halfword q; /* new node being added to the token list via |store_new_token| */
1926
halfword unbalance; /* number of unmatched left braces */
1930
scanner_status = absorbing;
1931
warning_index = cur_cs;
1934
set_token_ref_count(def_ref, 0);
1936
scan_left_brace(); /* remove the compulsory left brace */
1940
if (cur_tok < right_brace_limit) {
1941
if (cur_cmd < right_brace_cmd) {
1949
store_new_token(cur_tok);
1951
q = token_link(def_ref);
1952
free_avail(def_ref); /* discard reference count */
1954
cur_val = temp_token_head;
1957
set_token_link(temp_token_head, q);
1964
@ The |get_x_or_protected| procedure is like |get_x_token| except that
1965
protected macros are not expanded.
1968
void get_x_or_protected(void)
1969
{ /* sets |cur_cmd|, |cur_chr|, |cur_tok|,
1970
and expands non-protected macros */
1973
if (cur_cmd <= max_command_cmd)
1975
if ((cur_cmd >= call_cmd) && (cur_cmd < end_template_cmd)) {
1976
if (token_info(token_link(cur_chr)) == protected_token)
1984
@ |scan_toks|. This function returns a pointer to the tail of a new token
1985
list, and it also makes |def_ref| point to the reference count at the
1988
There are two boolean parameters, |macro_def| and |xpand|. If |macro_def|
1989
is true, the goal is to create the token list for a macro definition;
1990
otherwise the goal is to create the token list for some other \TeX\
1991
primitive: \.{\\mark}, \.{\\output}, \.{\\everypar}, \.{\\lowercase},
1992
\.{\\uppercase}, \.{\\message}, \.{\\errmessage}, \.{\\write}, or
1993
\.{\\special}. In the latter cases a left brace must be scanned next; this
1994
left brace will not be part of the token list, nor will the matching right
1995
brace that comes at the end. If |xpand| is false, the token list will
1996
simply be copied from the input using |get_token|. Otherwise all expandable
1997
tokens will be expanded until unexpandable tokens are left, except that
1998
the results of expanding `\.{\\the}' are not expanded further.
1999
If both |macro_def| and |xpand| are true, the expansion applies
2000
only to the macro body (i.e., to the material following the first
2001
|left_brace| character).
2003
The value of |cur_cs| when |scan_toks| begins should be the |eqtb|
2004
address of the control sequence to display in ``runaway'' error
2008
halfword scan_toks(boolean macro_def, boolean xpand)
2010
halfword t; /* token representing the highest parameter number */
2011
halfword s; /* saved token */
2012
halfword p; /* tail of the token list being built */
2013
halfword q; /* new node being added to the token list via |store_new_token| */
2014
halfword unbalance; /* number of unmatched left braces */
2015
halfword hash_brace; /* possible `\.{\#\{}' token */
2017
scanner_status = defining;
2019
scanner_status = absorbing;
2020
warning_index = cur_cs;
2023
set_token_ref_count(def_ref, 0);
2028
/* Scan and build the parameter part of the macro definition */
2030
get_token(); /* set |cur_cmd|, |cur_chr|, |cur_tok| */
2031
if (cur_tok < right_brace_limit)
2033
if (cur_cmd == mac_param_cmd) {
2034
/* If the next character is a parameter number, make |cur_tok|
2035
a |match| token; but if it is a left brace, store
2036
`|left_brace|, |end_match|', set |hash_brace|, and |goto done|;
2038
s = match_token + cur_chr;
2040
if (cur_cmd == left_brace_cmd) {
2041
hash_brace = cur_tok;
2042
store_new_token(cur_tok);
2043
store_new_token(end_match_token);
2046
if (t == zero_token + 9) {
2047
print_err("You already have nine parameters");
2048
help1("I'm going to ignore the # sign you just used.");
2053
print_err("Parameters must be numbered consecutively");
2055
("I've inserted the digit you should have used after the #.",
2056
"Type `1' to delete what you did use.");
2062
store_new_token(cur_tok);
2064
store_new_token(end_match_token);
2065
if (cur_cmd == right_brace_cmd) {
2066
/* Express shock at the missing left brace; |goto found| */
2067
print_err("Missing { inserted");
2070
("Where was the left brace? You said something like `\\def\\a}',",
2071
"which I'm going to interpret as `\\def\\a{}'.");
2077
scan_left_brace(); /* remove the compulsory left brace */
2080
/* Scan and build the body of the token list; |goto found| when finished */
2084
/* Expand the next part of the input */
2085
/* Here we insert an entire token list created by |the_toks| without
2086
expanding it further. */
2089
if (cur_cmd >= call_cmd) {
2090
if (token_info(token_link(cur_chr)) == protected_token) {
2091
cur_cmd = relax_cmd;
2092
cur_chr = no_expand_flag;
2095
if (cur_cmd <= max_command_cmd)
2097
if (cur_cmd != the_cmd) {
2101
if (token_link(temp_token_head) != null) {
2102
set_token_link(p, token_link(temp_token_head));
2112
if (cur_tok < right_brace_limit) {
2113
if (cur_cmd < right_brace_cmd) {
2120
} else if (cur_cmd == mac_param_cmd) {
2122
/* Look for parameter number or \.{\#\#} */
2128
if (cur_cmd != mac_param_cmd) {
2129
if ((cur_tok <= zero_token) || (cur_tok > t)) {
2130
print_err("Illegal parameter number in definition of ");
2131
sprint_cs(warning_index);
2132
help3("You meant to type ## instead of #, right?",
2133
"Or maybe a } was forgotten somewhere earlier, and things",
2134
"are all screwed up? I''m going to assume that you meant ##.");
2138
cur_tok = out_param_token - '0' + cur_chr;
2143
store_new_token(cur_tok);
2146
scanner_status = normal;
2147
if (hash_brace != 0)
2148
store_new_token(hash_brace);
2153
@ Here we declare two trivial procedures in order to avoid mutually
2154
recursive procedures with parameters.
2157
void scan_normal_glue(void)
2159
scan_glue(glue_val_level);
2162
void scan_mu_glue(void)
2164
scan_glue(mu_val_level);
2167
@ The |scan_expr| procedure scans and evaluates an expression.
2169
@ Evaluating an expression is a recursive process: When the left
2170
parenthesis of a subexpression is scanned we descend to the next level
2171
of recursion; the previous level is resumed with the matching right
2176
expr_none = 0, /* \.( seen, or \.( $\langle\it expr\rangle$ \.) seen */
2177
expr_add = 1, /* \.( $\langle\it expr\rangle$ \.+ seen */
2178
expr_sub = 2, /* \.( $\langle\it expr\rangle$ \.- seen */
2179
expr_mult = 3, /* $\langle\it term\rangle$ \.* seen */
2180
expr_div = 4, /* $\langle\it term\rangle$ \./ seen */
2181
expr_scale = 5, /* $\langle\it term\rangle$ \.* $\langle\it factor\rangle$ \./ seen */
2182
} expression_states;
2185
@ We want to make sure that each term and (intermediate) result is in
2186
the proper range. Integer values must not exceed |infinity|
2187
($2^{31}-1$) in absolute value, dimensions must not exceed |max_dimen|
2188
($2^{30}-1$). We avoid the absolute value of an integer, because this
2189
might fail for the value $-2^{31}$ using 32-bit arithmetic.
2191
@ clear a number or dimension and set |arith_error|
2194
#define num_error(A) do { \
2200
@ clear a glue spec and set |arith_error|
2203
#define glue_error(A) do { \
2205
delete_glue_ref(A); \
2206
A=new_spec(zero_glue); \
2210
#define normalize_glue(A) do { \
2211
if (stretch(A)==0) stretch_order(A)=normal; \
2212
if (shrink(A)==0) shrink_order(A)=normal; \
2216
@ Parenthesized subexpressions can be inside expressions, and this
2217
nesting has a stack. Seven local variables represent the top of the
2218
expression stack: |p| points to pushed-down entries, if any; |l|
2219
specifies the type of expression currently beeing evaluated; |e| is the
2220
expression so far and |r| is the state of its evaluation; |t| is the
2221
term so far and |s| is the state of its evaluation; finally |n| is the
2222
numerator for a combined multiplication and division, if any.
2225
#define expr_type(A) type((A)+1)
2226
#define expr_state(A) subtype((A)+1)
2227
#define expr_e_field(A) vlink((A)+1) /* saved expression so far */
2228
#define expr_t_field(A) vlink((A)+2) /* saved term so far */
2229
#define expr_n_field(A) vinfo((A)+2) /* saved numerator */
2232
#define expr_add_sub(A,B,C) add_or_sub((A),(B),(C),(r==expr_sub))
2233
#define expr_a(A,B) expr_add_sub((A),(B),max_dimen)
2236
The function |add_or_sub(x,y,max_answer,negative)| computes the sum
2237
(for |negative=false|) or difference (for |negative=true|) of |x| and
2238
|y|, provided the absolute value of the result does not exceed
2242
int add_or_sub(int x, int y, int max_answer, boolean negative)
2244
int a; /* the answer */
2248
if (y <= max_answer - x)
2252
} else if (y >= -max_answer - x) {
2261
#define expr_m(A) A = nx_plus_y((A),f,0)
2263
#define expr_d(A) A=quotient((A),f)
2266
@ The function |quotient(n,d)| computes the rounded quotient
2267
$q=\lfloor n/d+{1\over2}\rfloor$, when $n$ and $d$ are positive.
2270
int quotient(int n, int d)
2272
boolean negative; /* should the answer be negated? */
2273
int a; /* the answer */
2285
negative = !negative;
2289
d = n - d; /* avoid certain compiler optimizations! */
2298
#define expr_s(A) A=fract((A),n,f,max_dimen)
2301
@ Finally, the function |fract(x,n,d,max_answer)| computes the integer
2302
$q=\lfloor xn/d+{1\over2}\rfloor$, when $x$, $n$, and $d$ are positive
2303
and the result does not exceed |max_answer|. We can't use floating
2304
point arithmetic since the routine must produce identical results in all
2305
cases; and it would be too dangerous to multiply by~|n| and then divide
2306
by~|d|, in separate operations, since overflow might well occur. Hence
2307
this subroutine simulates double precision arithmetic, somewhat
2308
analogous to Metafont's |make_fraction| and |take_fraction| routines.
2311
int fract(int x, int n, int d, int max_answer)
2313
boolean negative; /* should the answer be negated? */
2314
int a; /* the answer */
2315
int f; /* a proper fraction */
2316
int h; /* smallest integer such that |2*h>=d| */
2317
int r; /* intermediate remainder */
2318
int t; /* temp variable */
2330
negative = !negative;
2331
} else if (x == 0) {
2336
negative = !negative;
2339
if (t > max_answer / x)
2346
if (t > (max_answer - a) / n)
2359
/* now |0<n<=x<d| */
2360
/* Compute $f=\lfloor xn/d+{1\over2}\rfloor$; */
2361
/* The loop here preserves the following invariant relations
2362
between |f|, |x|, |n|, and~|r|:
2363
(i)~$f+\lfloor(xn+(r+d))/d\rfloor=\lfloor x_0n_0/d+{1\over2}\rfloor$;
2364
(ii)~|-d<=r<0<n<=x<d|, where $x_0$, $n_0$ are the original values of~$x$
2366
/* Notice that the computation specifies |(x-d)+x| instead of |(x+x)-d|,
2367
because the latter could overflow. */
2398
if (f > (max_answer - a))
2412
void scan_expr(void)
2413
{ /* scans and evaluates an expression */
2414
boolean a, b; /* saved values of |arith_error| */
2415
int l; /* type of expression */
2416
int r; /* state of expression so far */
2417
int s; /* state of term so far */
2418
int o; /* next operation or type of next factor */
2419
int e; /* expression so far */
2420
int t; /* term so far */
2421
int f; /* current factor */
2422
int n; /* numerator of combined multiplication and division */
2423
halfword p; /* top of expression stack */
2424
halfword q; /* for stack manipulations */
2429
/* Scan and evaluate an expression |e| of type |l| */
2441
/* Scan a factor |f| of type |o| or start a subexpression */
2442
/* Get the next non-blank non-call token */
2445
} while (cur_cmd == spacer_cmd);
2447
if (cur_tok == other_token + '(') {
2448
/* Push the expression stack and |goto restart| */
2449
q = new_node(expr_node, 0);
2451
expr_type(q) = (quarterword) l;
2452
expr_state(q) = (quarterword) (4 * s + r);
2453
expr_e_field(q) = e;
2454
expr_t_field(q) = t;
2455
expr_n_field(q) = n;
2461
if ((o == int_val_level) || (o == attr_val_level))
2463
else if (o == dimen_val_level)
2464
scan_normal_dimen();
2465
else if (o == glue_val_level)
2472
/* Scan the next operator and set |o| */
2473
/* Get the next non-blank non-call token */
2476
} while (cur_cmd == spacer_cmd);
2478
if (cur_tok == other_token + '+') {
2480
} else if (cur_tok == other_token + '-') {
2482
} else if (cur_tok == other_token + '*') {
2484
} else if (cur_tok == other_token + '/') {
2489
if (cur_cmd != relax_cmd)
2491
} else if (cur_tok != other_token + ')') {
2492
print_err("Missing ) inserted for expression");
2493
help1("I was expecting to see `+', `-', `*', `/', or `)'. Didn't.");
2499
/* Make sure that |f| is in the proper range */
2500
if (((l == int_val_level) || (l == attr_val_level)) || (s > expr_sub)) {
2501
if ((f > infinity) || (f < -infinity))
2503
} else if (l == dimen_val_level) {
2504
if (abs(f) > max_dimen)
2507
if ((abs(width(f)) > max_dimen) ||
2508
(abs(stretch(f)) > max_dimen) || (abs(shrink(f)) > max_dimen))
2513
/* Cases for evaluation of the current term */
2516
Applying the factor |f| to the partial term |t| (with the operator
2517
|s|) is delayed until the next operator |o| has been scanned. Here we
2518
handle the first factor of a partial term. A glue spec has to be copied
2519
unless the next operator is a right parenthesis; this allows us later on
2520
to simply modify the glue components.
2522
if ((l >= glue_val_level) && (o != expr_none)) {
2531
/* If a multiplication is followed by a division, the two operations are
2532
combined into a `scaling' operation. Otherwise the term |t| is
2533
multiplied by the factor |f|. */
2534
if (o == expr_div) {
2537
} else if ((l == int_val_level) || (l == attr_val_level)) {
2538
t = mult_integers(t, f);
2539
} else if (l == dimen_val_level) {
2548
/* Here we divide the term |t| by the factor |f| */
2549
if (l < glue_val_level) {
2558
/* Here the term |t| is multiplied by the quotient $n/f$. */
2559
if ((l == int_val_level) || (l == attr_val_level)) {
2560
t = fract(t, n, f, infinity);
2561
} else if (l == dimen_val_level) {
2570
} /* there are no other cases */
2574
/* Evaluate the current expression */
2575
/* When a term |t| has been completed it is copied to, added to, or
2576
subtracted from the expression |e|. */
2578
if (r == expr_none) {
2580
} else if ((l == int_val_level) || (l == attr_val_level)) {
2581
e = expr_add_sub(e, t, infinity);
2582
} else if (l == dimen_val_level) {
2585
/* Compute the sum or difference of two glue specs */
2586
/* We know that |stretch_order(e)>normal| implies |stretch(e)<>0| and
2587
|shrink_order(e)>normal| implies |shrink(e)<>0|. */
2588
width(e) = expr_a(width(e), width(t));
2589
if (stretch_order(e) == stretch_order(t)) {
2590
stretch(e) = expr_a(stretch(e), stretch(t));
2591
} else if ((stretch_order(e) < stretch_order(t))
2592
&& (stretch(t) != 0)) {
2593
stretch(e) = stretch(t);
2594
stretch_order(e) = stretch_order(t);
2596
if (shrink_order(e) == shrink_order(t)) {
2597
shrink(e) = expr_a(shrink(e), shrink(t));
2598
} else if ((shrink_order(e) < shrink_order(t)) && (shrink(t) != 0)) {
2599
shrink(e) = shrink(t);
2600
shrink_order(e) = shrink_order(t);
2611
/* Pop the expression stack and |goto found| */
2614
e = expr_e_field(q);
2615
t = expr_t_field(q);
2616
n = expr_n_field(q);
2617
s = expr_state(q) / 4;
2618
r = expr_state(q) % 4;
2626
print_err("Arithmetic overflow");
2627
help2("I can't evaluate this expression,",
2628
"since the result is out of range.");
2630
if (l >= glue_val_level) {