1
4
5# include "luametatex.h"
6
7print_state_info lmt_print_state = {
8 .logfile = NULL,
9 .loggable_info = NULL,
10 .selector = 0,
11 .tally = 0,
12 .terminal_offset = 0,
13 .logfile_offset = 0,
14 .new_string_line = 0,
15 .trick_buffer = { 0 },
16 .trick_count = 0,
17 .first_count = 0,
18 .saved_selector = 0,
19 .font_in_short_display = 0,
20 .saved_logfile = NULL,
21 .saved_logfile_offset = 0,
22};
23
24
42
43
104
105void tex_print_ln(void)
106{
107 switch (lmt_print_state.selector) {
108 case no_print_selector_code:
109 break;
110 case terminal_selector_code:
111 fputc('\n', stdout);
112 lmt_print_state.terminal_offset = 0;
113 break;
114 case logfile_selector_code:
115 fputc('\n', lmt_print_state.logfile);
116 lmt_print_state.logfile_offset = 0;
117 break;
118 case terminal_and_logfile_selector_code:
119 fputc('\n', stdout);
120 fputc('\n', lmt_print_state.logfile);
121 lmt_print_state.terminal_offset = 0;
122 lmt_print_state.logfile_offset = 0;
123 break;
124 case pseudo_selector_code:
125 break;
126 case new_string_selector_code:
127 if (lmt_print_state.new_string_line > 0) {
128 tex_print_char(lmt_print_state.new_string_line);
129 }
130 break;
131 case luabuffer_selector_code:
132 lmt_newline_to_buffer();
133 break;
134 default:
135 break;
136 }
137
138}
139
140
141
152
153void tex_print_char(int s)
154{
155 if (s < 0 || s > 255) {
156 tex_formatted_warning("print", "weird character %i", s);
157 } else {
158 switch (lmt_print_state.selector) {
159 case no_print_selector_code:
160 break;
161 case terminal_selector_code:
162 if (s == new_line_char_par) {
163 fputc('\n', stdout);
164 lmt_print_state.terminal_offset = 0;
165 } else {
166 fputc(s, stdout);
167 ++lmt_print_state.terminal_offset;
168 }
169 break;
170 case logfile_selector_code:
171 if (s == new_line_char_par) {
172 fputc('\n', lmt_print_state.logfile);
173 lmt_print_state.logfile_offset = 0;
174 } else {
175 fputc(s, lmt_print_state.logfile);
176 ++lmt_print_state.logfile_offset;
177 }
178 break;
179 case terminal_and_logfile_selector_code:
180 if (s == new_line_char_par) {
181 fputc('\n', stdout);
182 fputc('\n', lmt_print_state.logfile);
183 lmt_print_state.terminal_offset = 0;
184 lmt_print_state.logfile_offset = 0;
185 } else {
186 fputc(s, stdout);
187 fputc(s, lmt_print_state.logfile);
188 ++lmt_print_state.terminal_offset;
189 ++lmt_print_state.logfile_offset;
190 }
191 break;
192 case pseudo_selector_code:
193 if (lmt_print_state.tally < lmt_print_state.trick_count) {
194 lmt_print_state.trick_buffer[lmt_print_state.tally % lmt_error_state.line_limits.size] = (unsigned char) s;
195 }
196 ++lmt_print_state.tally;
197 break;
198 case new_string_selector_code:
199 tex_append_char((unsigned char) s);
200 break;
201 case luabuffer_selector_code:
202 lmt_char_to_buffer((char) s);
203 break;
204 default:
205 break;
206 }
207 }
208}
209
210
225
226
227
228static void tex_aux_uprint(int s)
229{
230
231
238 if (s == new_line_char_par && lmt_print_state.selector < pseudo_selector_code) {
239 tex_print_ln();
240 } else if (s <= 0x7F) {
241 tex_print_char(s);
242 } else if (s <= 0x7FF) {
243 tex_print_char(0xC0 + (s / 0x40));
244 tex_print_char(0x80 + (s % 0x40));
245 } else if (s <= 0xFFFF) {
246 tex_print_char(0xE0 + (s / 0x1000));
247 tex_print_char(0x80 + ((s % 0x1000) / 0x40));
248 tex_print_char(0x80 + ((s % 0x1000) % 0x40));
249 } else {
250 tex_print_char(0xF0 + (s / 0x40000));
251 tex_print_char(0x80 + ((s % 0x40000) / 0x1000));
252 tex_print_char(0x80 + (((s % 0x40000) % 0x1000) / 0x40));
253 tex_print_char(0x80 + (((s % 0x40000) % 0x1000) % 0x40));
254 }
255}
256
257void tex_print_tex_str(int s)
258{
259 if (s >= lmt_string_pool_state.string_pool_data.ptr) {
260 tex_normal_warning("print", "bad string pointer");
261 } else if (s < cs_offset_value) {
262 if (s < 0) {
263 tex_normal_warning("print", "bad string offset");
264 } else {
265 tex_aux_uprint(s);
266 }
267 } else if (lmt_print_state.selector == new_string_selector_code) {
268 tex_append_string(str_string(s), (unsigned) str_length(s));
269 } else {
270 unsigned char *j = str_string(s);
271 for (unsigned i = 0; i < str_length(s); i++) {
272 tex_print_char(j[i]);
273 }
274 }
275}
276
277
283
284void tex_print_nlp(void)
285{
286 if (lmt_print_state.new_string_line > 0) {
287 tex_print_char(lmt_print_state.new_string_line);
288 } else {
289 switch (lmt_print_state.selector) {
290 case terminal_selector_code:
291 if (lmt_print_state.terminal_offset > 0) {
292 fputc('\n', stdout);
293 lmt_print_state.terminal_offset = 0;
294 }
295 break;
296 case logfile_selector_code:
297 if (lmt_print_state.logfile_offset > 0) {
298 fputc('\n', lmt_print_state.logfile);
299 lmt_print_state.logfile_offset = 0;
300 }
301 break;
302 case terminal_and_logfile_selector_code:
303 if (lmt_print_state.terminal_offset > 0) {
304 fputc('\n', stdout);
305 lmt_print_state.terminal_offset = 0;
306 }
307 if (lmt_print_state.logfile_offset > 0) {
308 fputc('\n', lmt_print_state.logfile);
309 lmt_print_state.logfile_offset = 0;
310 }
311 break;
312 case luabuffer_selector_code:
313 lmt_newline_to_buffer();
314 break;
315 }
316 }
317}
318
319
325
326void tex_print_str(const char *s)
327{
328 int logfile = 0;
329 int terminal = 0;
330 switch (lmt_print_state.selector) {
331 case no_print_selector_code:
332 return;
333 case terminal_selector_code:
334 terminal = 1;
335 break;
336 case logfile_selector_code:
337 logfile = 1;
338 break;
339 case terminal_and_logfile_selector_code:
340 logfile = 1;
341 terminal = 1;
342 break;
343 case pseudo_selector_code:
344 while ((*s) && (lmt_print_state.tally < lmt_print_state.trick_count)) {
345 lmt_print_state.trick_buffer[lmt_print_state.tally % lmt_error_state.line_limits.size] = (unsigned char) *s++;
346 lmt_print_state.tally++;
347 }
348 return;
349 case new_string_selector_code:
350 tex_append_string((const unsigned char *) s, (unsigned) strlen(s));
351 return;
352 case luabuffer_selector_code:
353 lmt_string_to_buffer(s);
354 return;
355 default:
356 return;
357 }
358 if (terminal || logfile) {
359 int len = (int) strlen(s);
360 if (logfile && ! lmt_fileio_state.log_opened) {
361 logfile = 0;
362 }
363 if (len > 0) {
364 int newline = s[len-1] == '\n';
365 if (logfile) {
366 fputs(s, lmt_print_state.logfile);
367
368 if (newline) {
369 lmt_print_state.logfile_offset = 0;
370 } else {
371 lmt_print_state.logfile_offset += len;
372 }
373 }
374 if (terminal) {
375 fputs(s, stdout);
376
377 if (newline) {
378 lmt_print_state.terminal_offset = 0;
379 } else {
380 lmt_print_state.terminal_offset += len;
381 }
382 }
383 }
384 }
385}
386
387
397
398void tex_print_banner(void)
399{
400 fprintf(
401 stdout,
402 "%s %s\n",
403 lmt_engine_state.luatex_banner,
404 lmt_engine_state.dump_name
405 );
406}
407
408void tex_print_log_banner(void)
409{
410 fprintf(
411 lmt_print_state.logfile,
412 "engine: %s, format id: %s, time stamp: %d-%d-%d %d:%d, startup file: %s, job name: %s",
413 lmt_engine_state.luatex_banner,
414 lmt_engine_state.dump_name,
415 year_par, month_par > 12 ? 0 : month_par, day_par, time_par / 60, time_par % 60,
416 lmt_engine_state.startup_filename ? lmt_engine_state.startup_filename : "-",
417 lmt_engine_state.startup_jobname ? lmt_engine_state.startup_jobname : "-"
418 );
419}
420
421void tex_print_version_banner(void)
422{
423 fputs(lmt_engine_state.luatex_banner, stdout);
424}
425
426
432
433void tex_print_tex_str_esc(strnumber s)
434{
435
436 int c = escape_char_par;
437 if (c >= 0) {
438 tex_print_tex_str(c);
439 }
440 if (s) {
441 tex_print_tex_str(s);
442 }
443}
444
445
446
447void tex_print_str_esc(const char *s)
448{
449
450 int c = escape_char_par;
451 if (c >= 0) {
452 tex_print_tex_str(c);
453 }
454 if (s) {
455 tex_print_str(s);
456 }
457}
458
459
467
468void tex_print_int(int n)
469{
470
471 if (n < 0) {
472 tex_print_char('-');
473 n = -n;
474 }
475 if (n >= 0 && n <= 9) {
476 tex_print_char('0' + n);
477 } else if (n >= 0 && n <= 99) {
478 tex_print_char('0' + n/10);
479 tex_print_char('0' + n%10);
480 } else {
481 int k = 0;
482 unsigned char digits[24];
483
484
485
486
487 do {
488 digits[k] = '0' + (unsigned char) (n % 10);
489 n = n / 10;
490 ++k;
491 } while (n != 0);
492 while (k-- > 0) {
493 tex_print_char(digits[k]);
494 }
495 }
496}
497
498
513
514void tex_print_dimension(scaled s, int unit)
515{
516 if (s == 0) {
517 tex_print_str("0.0");
518 } else {
519
520 scaled delta = 10;
521 char buffer[20] = { 0 } ;
522 int i = 0;
523 if (s < 0) {
524
525 tex_print_char('-');
526 s = -s;
527 }
528
529 tex_print_int(s / unity);
530 buffer[i++] = '.';
531 s = 10 * (s % unity) + 5;
532 do {
533 if (delta > unity) {
534
535 s = s + 0x8000 - 50000;
536 }
537 buffer[i++] = (unsigned char) ('0' + (s / unity));
538 s = 10 * (s % unity);
539 delta *= 10;
540 } while (s > delta);
541
542 tex_print_str(buffer);
543 }
544 if (unit != no_unit) {
545 tex_print_unit(unit);
546 }
547}
548
549void tex_print_sparse_dimension(scaled s, int unit)
550{
551 if (s == 0) {
552 tex_print_char('0');
553 } else if (s == unity) {
554 tex_print_char('1');
555 } else {
556
557 scaled delta = 10;
558 char buffer[20];
559 int i = 0;
560 if (s < 0) {
561
562 tex_print_char('-');
563
564 s = -s;
565 }
566
567 tex_print_int(s / unity);
568 s = 10 * (s % unity) + 5;
569 do {
570 if (delta > unity) {
571
572 s = s + 0100000 - 50000;
573 }
574 buffer[i++] = (unsigned char) ('0' + (s / unity));
575 s = 10 * (s % unity);
576 delta *= 10;
577 } while (s > delta);
578 if (i == 1 && buffer[i-1] == '0') {
579
580 } else {
581 buffer[i++] = '\0';
582 tex_print_char('.');
583 tex_print_str(buffer);
584 }
585 }
586 if (unit != no_unit) {
587 tex_print_unit(unit);
588 }
589}
590
591
594
595void tex_print_posit(halfword s)
596{
597 char b[32];
598 sprintf(b, "%.20g", tex_posit_to_double(s));
599 tex_print_str(b);
600}
601
602
608
609void tex_print_hex(long long sn)
610{
611 if (sn == 0) {
612 tex_print_char('0');
613 } else {
614 unsigned long long n = 0;
615 int k = 0;
616 unsigned char digits[24];
617 if (sn < 0) {
618 tex_print_char('-');
619 n = (unsigned long long) -sn;
620 } else {
621 n = (unsigned long long) sn;
622 }
623 do {
624 unsigned char d = (unsigned char) (n % 16);
625 if (d < 10) {
626 digits[k] = '0' + d;
627 } else {
628 digits[k] = 'A' - 10 + d;
629 }
630 n = n / 16;
631 ++k;
632 } while (n != 0);
633 while (k-- > 0) {
634 tex_print_char(digits[k]);
635 }
636 }
637}
638
639void tex_print_qhex(long long n)
640{
641 tex_print_char('"');
642 tex_print_hex(n);
643}
644
645void tex_print_uhex(long long n)
646{
647 tex_print_str("U+");
648
649 if (n < 16) {
650 tex_print_char('0');
651 }
652 if (n < 256) {
653 tex_print_char('0');
654 }
655 if (n < 4096) {
656 tex_print_char('0');
657 }
658 tex_print_hex(n);
659}
660
661static void tex_print_xhex(long long n)
662{
663 tex_print_char('"');
664
665 if (n < 0xF) {
666 tex_print_char('0');
667 }
668 if (n < 0xFF) {
669 tex_print_char('0');
670 }
671 if (n < 0xFFF) {
672 tex_print_char('0');
673 }
674 if (n < 0xFFFF) {
675 tex_print_char('0');
676 }
677 if (n < 0xFFFFF) {
678 tex_print_char('0');
679 }
680 if (n < 0xFFFFFF) {
681 tex_print_char('0');
682 }
683 if (n < 0xFFFFFFF) {
684 tex_print_char('0');
685 }
686 tex_print_hex(n);
687}
688
689
696
697void tex_print_roman_int(int n)
698{
699 char mystery[] = "m2d5c2l5x2v5i";
700 char *j = (char *) mystery;
701 int v = 1000;
702 while (1) {
703 while (n >= v) {
704 tex_print_char(*j);
705 n = n - v;
706 }
707 if (n <= 0) {
708
709 return;
710 } else {
711 char *k = j + 2;
712 int u = v / (*(k - 1) - '0');
713 if (*(k - 1) == '2') {
714 k = k + 2;
715 u = u / (*(k - 1) - '0');
716 }
717 if (n + u >= v) {
718 tex_print_char(*k);
719 n = n + u;
720 } else {
721 j = j + 2;
722 v = v / (*(j - 1) - '0');
723 }
724 }
725 }
726}
727
728
734
735void tex_print_current_string(void)
736{
737 for (int j = 0; j < lmt_string_pool_state.string_temp_top; j++) {
738 tex_print_char(lmt_string_pool_state.string_temp[j++]);
739 }
740}
741
742
751
752void tex_print_cs_checked(halfword p)
753{
754 switch (tex_cs_state(p)) {
755 case cs_no_error:
756 {
757 strnumber t = cs_text(p);
758 if (t < 0 || t >= lmt_string_pool_state.string_pool_data.ptr) {
759 tex_print_str(error_string_nonexistent(13));
760 } else if (tex_is_active_cs(t)) {
761 tex_print_tex_str(active_cs_value(t));
762 } else {
763 tex_print_tex_str_esc(t);
764 if (! tex_single_letter(t) || (tex_get_cat_code(cat_code_table_par, aux_str2uni(str_string(t))) == letter_cmd)) {
765 tex_print_char(' ');
766 }
767 }
768 }
769 break;
770 case cs_null_error:
771 tex_print_str_esc("csname");
772 tex_print_str_esc("endcsname");
773 tex_print_char(' ');
774 break;
775 case cs_below_base_error:
776 tex_print_str(error_string_impossible(11));
777 break;
778 case cs_undefined_error:
779 tex_print_str_esc("undefined");
780 tex_print_char(' ');
781 break;
782 case cs_out_of_range_error:
783 tex_print_str(error_string_impossible(12));
784 break;
785 }
786}
787
788
794
795void tex_print_cs(halfword p)
796{
797 if (p == null_cs) {
798 tex_print_str_esc("csname");
799 tex_print_str_esc("endcsname");
800 } else {
801 strnumber t = cs_text(p);
802 if (tex_is_active_cs(t)) {
803 tex_print_tex_str(active_cs_value(t));
804 } else {
805 tex_print_tex_str_esc(t);
806 }
807 }
808}
809
810void tex_print_cs_name(halfword p)
811{
812 if (p != null_cs) {
813 strnumber t = cs_text(p);
814 if (tex_is_active_cs(t)) {
815 tex_print_tex_str(active_cs_value(t));
816 } else {
817 tex_print_tex_str(t);
818 }
819 }
820}
821
822
828
829void tex_print_glue(scaled d, int order, int unit)
830{
831 tex_print_dimension(d, no_unit);
832 if ((order < normal_glue_order) || (order > filll_glue_order)) {
833
834 tex_print_str("foul");
835 } else if (order > normal_glue_order) {
836 tex_print_str("fi");
837 while (order > fi_glue_order) {
838 tex_print_char('l');
839 --order;
840 }
841 } else {
842 tex_print_unit(unit);
843 }
844}
845
846
847
848void tex_print_unit(int unit)
849{
850 if (unit != no_unit) {
851 tex_print_str(unit == pt_unit ? "pt" : "mu");
852 }
853}
854
855void tex_print_spec(int p, int unit)
856{
857 if (p < 0) {
858 tex_print_char('*');
859 } else if (p == 0) {
860 tex_print_dimension(0, unit);
861 } else {
862 tex_print_dimension(glue_amount(p), unit);
863 if (glue_stretch(p)) {
864 tex_print_str(" plus ");
865 tex_print_glue(glue_stretch(p), glue_stretch_order(p), unit);
866 }
867 if (glue_shrink(p)) {
868 tex_print_str(" minus ");
869 tex_print_glue(glue_shrink(p), glue_shrink_order(p), unit);
870 }
871 }
872}
873
874void tex_print_fontspec(int p)
875{
876 tex_print_int(font_spec_identifier(p));
877 if (font_spec_scale(p) != unused_scale_value) {
878 tex_print_str(" scale ");
879 tex_print_int(font_spec_scale(p));
880 }
881 if (font_spec_x_scale(p) != unused_scale_value) {
882 tex_print_str(" xscale ");
883 tex_print_int(font_spec_x_scale(p));
884 }
885 if (font_spec_y_scale(p) != unused_scale_value) {
886 tex_print_str(" yscale ");
887 tex_print_int(font_spec_y_scale(p));
888 }
889 if (font_spec_slant(p)) {
890 tex_print_str(" slant ");
891 tex_print_int(font_spec_slant(p));
892 }
893 if (font_spec_weight(p)) {
894 tex_print_str(" weight ");
895 tex_print_int(font_spec_weight(p));
896 }
897}
898
899
900
901void tex_print_mathspec(int p)
902{
903 if (p) {
904 mathcodeval m = tex_get_math_spec(p);
905 tex_show_mathcode_value(m, node_subtype(p));
906 } else {
907 tex_print_str("[invalid mathspec]");
908 }
909}
910
911
946
947void tex_print_char_identifier(halfword c)
948{
949 if (c <= 0x10FFFF) {
950 char b[10];
951 if ( (c >= 0x00E000 && c <= 0x00F8FF) || (c >= 0x0F0000 && c <= 0x0FFFFF) ||
952 (c >= 0x100000 && c <= 0x10FFFF) || (c >= 0x00D800 && c <= 0x00DFFF) ) {
953 sprintf(b, "0x%06X", c);
954 tex_print_str(b);
955 } else {
956 sprintf(b, "U+%06X", c);
957 tex_print_str(b);
958 tex_print_char(' ');
959 tex_print_tex_str(c);
960 }
961 }
962}
963
964void tex_print_font_identifier(halfword f)
965{
966
967 if (f < 0) {
968 f = cur_font_par;
969 }
970 if (tex_is_valid_font(f)) {
971 tex_print_format("<%i: %s @ %p>", f, font_name(f), font_size(f));
972 } else {
973 tex_print_str("<*>");
974 }
975}
976
977void tex_print_font_specifier(halfword e)
978{
979 if (e && tex_is_valid_font(font_spec_identifier(e))) {
980 tex_print_format("<%i: %i %i %i %i %i>", font_spec_identifier(e), font_spec_scale(e), font_spec_x_scale(e), font_spec_y_scale(e), font_spec_slant(e), font_spec_weight(e));
981 } else {
982 tex_print_str("<*>");
983 }
984}
985
986void tex_print_font(halfword f)
987{
988 if (f < 0) {
989 f = cur_font_par;
990 }
991 if (! f) {
992 tex_print_str("nullfont");
993 } else if (tex_is_valid_font(f)) {
994 tex_print_str(font_name(f));
995
996
1000 tex_print_format(" at %p", font_size(f));
1001
1002 } else {
1003 tex_print_str("nofont");
1004 }
1005}
1006
1007
1008
1009void tex_short_display(halfword p)
1010{
1011
1012 if (p) {
1013 tex_print_short_node_contents(p);
1014 } else {
1015 tex_print_str("[empty list]");
1016 }
1017}
1018
1019
1020
1021void tex_print_token_list(const char *s, halfword p)
1022{
1023 tex_print_levels();
1024 tex_print_str("..");
1025 if (s) {
1026 tex_print_str(s);
1027 tex_print_char(' ');
1028 }
1029 tex_print_char('{');
1030 if ((p >= 0) && (p <= (int) lmt_token_memory_state.tokens_data.top)) {
1031 tex_show_token_list(p, 0, 0);
1032 } else {
1033 tex_print_str(error_string_clobbered(21));
1034 }
1035 tex_print_char('}');
1036}
1037
1038
1039
1040void tex_print_rule_dimension(scaled d)
1041{
1042 if (d == null_flag) {
1043 tex_print_char('*');
1044 } else {
1045 tex_print_dimension(d, pt_unit);
1046 }
1047}
1048
1049
1069
1070void tex_show_box(halfword p)
1071{
1072
1073 tex_show_node_list(p, show_box_depth_par, show_box_breadth_par);
1074 tex_print_ln();
1075}
1076
1077
1084
1085void tex_begin_diagnostic(void)
1086{
1087 lmt_print_state.saved_selector = lmt_print_state.selector;
1088 if ((tracing_online_par <= 0) && (lmt_print_state.selector == terminal_and_logfile_selector_code)) {
1089 lmt_print_state.selector = logfile_selector_code;
1090 if (lmt_error_state.history == spotless) {
1091 lmt_error_state.history = warning_issued;
1092 }
1093 }
1094 tex_print_levels();
1095}
1096
1097
1098
1099void tex_end_diagnostic(void)
1100{
1101 tex_print_nlp();
1102 lmt_print_state.selector = lmt_print_state.saved_selector;
1103}
1104
1105static void tex_print_padding(void)
1106{
1107 switch (lmt_print_state.selector) {
1108 case terminal_selector_code:
1109 if (! odd(lmt_print_state.terminal_offset)) {
1110 tex_print_char(' ');
1111 }
1112 break;
1113 case logfile_selector_code:
1114 case terminal_and_logfile_selector_code:
1115 if (! odd(lmt_print_state.logfile_offset)) {
1116 tex_print_char(' ');
1117 }
1118 break;
1119 case luabuffer_selector_code:
1120 break;
1121 }
1122}
1123
1124void tex_print_levels(void)
1125{
1126 int l0 = tracing_levels_par;
1127 tex_print_nlp();
1128 if (l0 > 0) {
1129 int l1 = (l0 & tracing_levels_group) == tracing_levels_group;
1130 int l2 = (l0 & tracing_levels_input) == tracing_levels_input;
1131 int l4 = (l0 & tracing_levels_catcodes) == tracing_levels_catcodes;
1132 if (l1) {
1133 tex_print_int(cur_level);
1134 tex_print_char(':');
1135 }
1136 if (l2) {
1137 tex_print_int(lmt_input_state.input_stack_data.ptr);
1138 tex_print_char(':');
1139 }
1140 if (l4) {
1141 tex_print_int(cat_code_table_par);
1142 tex_print_char(':');
1143 }
1144 if (l1 || l2 || l4) {
1145 tex_print_char(' ');
1146 }
1147 tex_print_padding();
1148 }
1149}
1150
1151
1178
1179const char *tex_print_format_args(const char *format, va_list args)
1180{
1181 while (1) {
1182 int chr = *format++;
1183 switch (chr) {
1184 case '\0':
1185 return va_arg(args, char *);
1186 case '%':
1187 {
1188 chr = *format++;
1189 switch (chr) {
1190 case '\0':
1191 return va_arg(args, char *);
1192 case 'c':
1193 tex_print_char(va_arg(args, int));
1194 break;
1195 case 'd':
1196 tex_print_str(tex_aux_subtype_str(va_arg(args, int)));
1197 break;
1198 case 'e':
1199 tex_print_str_esc(NULL);
1200 break;
1201 case 'i':
1202 tex_print_int(va_arg(args, int));
1203 break;
1204 case 'l':
1205 tex_print_levels();
1206 break;
1207 case 'n':
1208 tex_print_extended_subtype(null, (quarterword) va_arg(args, int));
1209 break;
1210 case 'm':
1211 tex_print_cs_checked(va_arg(args, int));
1212 break;
1213 case 's':
1214 tex_print_str(va_arg(args, char *));
1215 break;
1216 case 'p':
1217 tex_print_dimension(va_arg(args, scaled), pt_unit);
1218 break;
1219 case 'q':
1220 tex_print_char('\'');
1221 tex_print_str(va_arg(args, char *));
1222 tex_print_char('\'');
1223 break;
1224 case 'x':
1225 tex_print_qhex(va_arg(args, int));
1226 break;
1227
1232 case 'u':
1233 {
1234 unsigned char s[6] = { 0 };
1235 unsigned char *b = s;
1236 b = aux_uni2str(va_arg(args, int));
1237 tex_print_format(", %s", b);
1238 break;
1239 }
1240 case 'B':
1241 {
1242 scaled b = va_arg(args, halfword);
1243 if (b == awful_bad) {
1244 tex_print_char('*');
1245 } else {
1246 tex_print_int(b);
1247 }
1248 break;
1249 }
1250 case 'C':
1251 {
1252 int cmd = va_arg(args, int);
1253 int val = va_arg(args, int);
1254 tex_print_cmd_chr((singleword) cmd, val);
1255 break;
1256 }
1257 case 'D':
1258 {
1259 scaled s = va_arg(args, scaled);
1260 int u = va_arg(args, int);
1261 tex_print_dimension(s, u);
1262 break;
1263 }
1264 case 'E':
1265 tex_print_str_esc(va_arg(args, char *));
1266 break;
1267 case 'G':
1268 {
1269 halfword g = va_arg(args, int);
1270 tex_print_group(g);
1271 break;
1272 }
1273 case 'F':
1274 {
1275 halfword i = va_arg(args, int);
1276 tex_print_font_identifier(i);
1277 break;
1278 }
1279 case 'L':
1280 {
1281
1282 halfword line = va_arg(args, int);
1283 if (line) {
1284 tex_print_str(" entered on line ");
1285 tex_print_int(line);
1286 }
1287 break;
1288 }
1289 case 'N':
1290 {
1291 halfword node = va_arg(args, int);
1292 if (node) {
1293 tex_print_str(lmt_interface.node_data[node_type(node)].name);
1294 }
1295 break;
1296 }
1297 case 'M':
1298 {
1299 halfword mode = va_arg(args, int);
1300 tex_print_str(tex_string_mode(mode));
1301 break;
1302 }
1303 case 'P':
1304 {
1305 scaled total = va_arg(args, int);
1306 scaled stretch = va_arg(args, int);
1307 scaled fistretch = va_arg(args, int);
1308 scaled filstretch = va_arg(args, int);
1309 scaled fillstretch = va_arg(args, int);
1310 scaled filllstretch = va_arg(args, int);
1311 scaled shrink = va_arg(args, int);
1312 tex_print_dimension(total, pt_unit);
1313 if (stretch) {
1314 tex_print_str(" plus ");
1315 tex_print_dimension(stretch, pt_unit);
1316 } else if (fistretch) {
1317 tex_print_str(" plus ");
1318 tex_print_dimension(fistretch, no_unit);
1319 tex_print_str(" fi");
1320 } else if (filstretch) {
1321 tex_print_str(" plus ");
1322 tex_print_dimension(filstretch, no_unit);
1323 tex_print_str(" fil");
1324 } else if (fillstretch) {
1325 tex_print_str(" plus ");
1326 tex_print_dimension(fillstretch, no_unit);
1327 tex_print_str(" fill");
1328 } else if (filllstretch) {
1329 tex_print_str(" plus ");
1330 tex_print_dimension(fillstretch, no_unit);
1331 tex_print_str(" filll");
1332 }
1333 if (shrink) {
1334 tex_print_str(" minus ");
1335 tex_print_dimension(shrink, pt_unit);
1336 }
1337 break;
1338 }
1339 case 'Q':
1340 {
1341 scaled s = va_arg(args, scaled);
1342 int u = va_arg(args, int);
1343 tex_print_spec(s, u);
1344 break;
1345 }
1346 case 'R':
1347 {
1348 halfword d = va_arg(args, int);
1349 tex_print_rule_dimension(d);
1350 break;
1351 }
1352 case 'S':
1353 {
1354 halfword cs = va_arg(args, int);
1355 tex_print_cs(cs);
1356 break;
1357 }
1358 case 'T':
1359 {
1360 strnumber s = va_arg(args, int);
1361 tex_print_tex_str(s);
1362 break;
1363 }
1364 case 'U':
1365 {
1366 halfword c = va_arg(args, int);
1367 tex_print_uhex(c);
1368 break;
1369 }
1370 case 'X':
1371 {
1372 halfword x = va_arg(args, int);
1373 tex_print_xhex(x);
1374 break;
1375 }
1376 case '2':
1377 {
1378 halfword c = va_arg(args, int);
1379 switch (c) {
1380 case direction_l2r : tex_print_str("l2r"); break;
1381 case direction_r2l : tex_print_str("r2l"); break;
1382 default : tex_print_str("unset"); break;
1383 }
1384 break;
1385 }
1386 case '%':
1387 tex_print_char('%');
1388 break;
1389
1390
1391
1392
1393
1394
1395
1396
1397 default:
1398
1399 break;
1400 }
1401 }
1402 break;
1403 case '\n':
1404 case '\r':
1405 tex_print_nlp();
1406 break;
1407 default:
1408 tex_print_char(chr);
1409 break;
1410 }
1411 }
1412}
1413
1414void tex_print_format(const char *format, ...)
1415{
1416 va_list args;
1417 va_start(args, format);
1418 tex_print_format_args(format, args);
1419 va_end(args);
1420}
1421
1422
1430
1431void tex_print_group(int e)
1432{
1433 int line = tex_saved_line_at_level();
1434 tex_print_str(lmt_interface.group_code_values[cur_group].name);
1435 if (cur_group != bottom_level_group) {
1436 tex_print_str(" group");
1437 if (line) {
1438 tex_print_str(e ? " entered at line " : " at line ");
1439 tex_print_int(line);
1440 }
1441 }
1442}
1443
1444void tex_print_message(const char *s)
1445{
1446 tex_print_nlp();
1447 tex_print_char('(');
1448 tex_print_str(s);
1449 tex_print_char(')');
1450 tex_print_nlp();
1451}
1452 |