1 /* rendering lines and managing traps */
8 #define NOPAGE 0x40000000 /* undefined bp_next */
9 #define cfmt env_fmt() /* current formatter */
10 #define cwb env_wb() /* current word buffer */
14 struct sbuf sbuf
; /* diversion output */
15 int reg
; /* diversion register */
16 int tpos
; /* diversion trap position */
17 int treg
; /* diversion trap register */
18 int dl
; /* diversion width */
19 int prev_d
; /* previous \n(.d value */
20 int prev_h
; /* previous \n(.h value */
21 int prev_mk
; /* previous .mk internal register */
22 int prev_ns
; /* previous .ns value */
24 static struct div divs
[NPREV
]; /* diversion stack */
25 static struct div
*cdiv
; /* current diversion */
26 static int ren_div
; /* rendering a diversion */
27 static int ren_divvs
; /* the amount of .v in diversions */
28 static int trap_em
= -1; /* end macro */
30 static int ren_nl
; /* just after a newline */
31 static int ren_partial
; /* reading an input line in render_rec() */
32 static int ren_unbuf
[8]; /* ren_back() buffer */
34 static int ren_aborted
; /* .ab executed */
36 static int bp_first
= 1; /* prior to the first page */
37 static int bp_next
= NOPAGE
; /* next page number */
38 static int bp_ejected
; /* current ejected page */
39 static int bp_final
; /* 1: executing em, 2: the final page, 3: the 2nd final page */
40 static int ren_level
; /* the depth of render_rec() calls */
42 static char c_fa
[GNLEN
]; /* field delimiter */
43 static char c_fb
[GNLEN
]; /* field padding */
45 static int ren_next(void)
47 return ren_un
> 0 ? ren_unbuf
[--ren_un
] : tr_next();
50 static void ren_back(int c
)
52 ren_unbuf
[ren_un
++] = c
;
55 void tr_di(char **args
)
58 cdiv
= cdiv
? cdiv
+ 1 : divs
;
59 memset(cdiv
, 0, sizeof(*cdiv
));
60 sbuf_init(&cdiv
->sbuf
);
61 cdiv
->reg
= map(args
[1]);
63 if (args
[0][2] == 'a' && str_get(cdiv
->reg
)) /* .da */
64 sbuf_append(&cdiv
->sbuf
, str_get(cdiv
->reg
));
65 sbuf_printf(&cdiv
->sbuf
, "%c%s\n", c_cc
, TR_DIVBEG
);
75 sbuf_printf(&cdiv
->sbuf
, "%c%s\n", c_cc
, TR_DIVEND
);
76 str_set(cdiv
->reg
, sbuf_buf(&cdiv
->sbuf
));
77 sbuf_done(&cdiv
->sbuf
);
84 cdiv
= cdiv
> divs
? cdiv
- 1 : NULL
;
90 return cdiv
? cdiv
->reg
: -1;
95 return fmt_wid(cfmt
) + wb_wid(cwb
);
98 void tr_divbeg(char **args
)
104 void tr_divend(char **args
)
107 errdie("neatroff: diversion stack empty\n");
112 void tr_divvs(char **args
)
114 ren_divvs
= eval(args
[1], 'u');
117 void tr_transparent(char **args
)
120 sbuf_printf(&cdiv
->sbuf
, "%s\n", args
[1]);
122 out("%s\n", args
[1]);
125 static int trap_reg(int pos
);
126 static int trap_pos(int pos
);
127 static void trap_exec(int reg
);
129 static void ren_page(int force
)
131 if (!force
&& bp_final
>= 2)
136 n_pg
= bp_next
!= NOPAGE
? bp_next
: n_pg
+ 1;
141 if (trap_pos(-1) == 0)
142 trap_exec(trap_reg(-1));
145 static int ren_first(void)
147 if (bp_first
&& !cdiv
) {
155 /* when nodiv, do not append .sp to diversions */
156 static void ren_sp(int n
, int nodiv
)
158 int linevs
= !n
; /* the vertical spacing before a line */
160 if (!n
&& ren_div
&& ren_divvs
&& !n_u
)
161 n
= ren_divvs
; /* .v at the time of diversion */
167 if (cdiv
&& !nodiv
) {
169 sbuf_printf(&cdiv
->sbuf
, "%c%s %du\n", c_cc
, TR_DIVVS
, n_v
);
171 sbuf_printf(&cdiv
->sbuf
, "%csp %du\n", c_cc
, n
? n
: n_v
);
177 static int render_rec(int level
);
179 static void trap_exec(int reg
)
182 int partial
= ren_partial
&& (!ren_un
|| ren_unbuf
[0] != '\n');
184 sprintf(cmd
, "%c%s %d\n", c_cc
, TR_POPREN
, ren_level
);
186 in_push(str_get(reg
), NULL
);
189 render_rec(++ren_level
);
190 /* executed the trap while in the middle of an input line */
192 fmt_suppressnl(cfmt
);
196 static int detect_traps(int beg
, int end
)
198 int pos
= trap_pos(beg
);
199 return pos
>= 0 && (cdiv
|| pos
< n_p
) && pos
<= end
;
202 /* return 1 if executed a trap */
203 static int ren_traps(int beg
, int end
, int dosp
)
205 int pos
= trap_pos(beg
);
206 if (detect_traps(beg
, end
)) {
207 if (dosp
&& pos
> beg
)
208 ren_sp(pos
- beg
, 0);
209 trap_exec(trap_reg(beg
));
215 static int detect_pagelimit(int ne
)
217 return !cdiv
&& n_nl
+ ne
>= n_p
;
220 /* start a new page if needed */
221 static int ren_pagelimit(int ne
)
223 if (detect_pagelimit(ne
)) {
230 /* return 1 if triggered a trap */
231 static int down(int n
)
233 if (ren_traps(n_d
, n_d
+ (n
? n
: n_v
), 1))
235 ren_sp(MAX(n
, -n_d
), 0);
236 return ren_pagelimit(0);
239 /* line adjustment */
240 static int ren_ljust(struct sbuf
*spre
, int w
, int ad
, int li
, int lI
, int ll
)
243 int llen
= ll
- lI
- li
;
245 if ((ad
& AD_B
) == AD_C
)
246 ljust
+= llen
> w
? (llen
- w
) / 2 : 0;
247 if ((ad
& AD_B
) == AD_R
)
250 sbuf_printf(spre
, "%ch'%du'", c_ec
, ljust
);
251 if (cdiv
&& cdiv
->dl
< w
+ ljust
)
252 cdiv
->dl
= w
+ ljust
;
256 /* append the line to the current diversion or send it to out.c */
257 static void ren_out(char *beg
, char *mid
, char *end
)
260 sbuf_append(&cdiv
->sbuf
, beg
);
261 sbuf_append(&cdiv
->sbuf
, mid
);
262 sbuf_append(&cdiv
->sbuf
, end
);
263 sbuf_append(&cdiv
->sbuf
, "\n");
273 static void ren_dir(struct sbuf
*sbuf
)
277 dir_fix(&fixed
, sbuf_buf(sbuf
));
280 sbuf_append(sbuf
, sbuf_buf(&fixed
));
284 static int zwid(void)
286 struct glyph
*g
= dev_glyph("0", n_f
);
287 return g
? font_gwid(g
->font
, dev_font(n_f
), n_s
, g
->wid
) : 0;
290 /* append the line number to the output line */
291 static void ren_lnum(struct sbuf
*spre
)
298 if (n_nn
<= 0 && (n_ln
% n_nM
) == 0)
299 sprintf(num
, "%d", n_ln
);
300 wb_hmov(&wb
, n_nI
* zwid());
302 wb_hmov(&wb
, (3 - strlen(num
)) * zwid());
307 wb_hmov(&wb
, n_nS
* zwid());
308 sbuf_append(spre
, wb_buf(&wb
));
316 /* append margin character */
317 static void ren_mc(struct sbuf
*sbuf
, int w
, int ljust
)
321 if (w
+ ljust
< n_l
+ n_mcn
)
322 wb_hmov(&wb
, n_l
+ n_mcn
- w
- ljust
);
323 wb_putexpand(&wb
, c_mc
);
324 sbuf_append(sbuf
, wb_buf(&wb
));
328 /* process a line and print it with ren_out() */
329 static int ren_line(char *line
, int w
, int ad
, int body
,
330 int li
, int lI
, int ll
, int els_neg
, int els_pos
)
332 struct sbuf sbeg
, send
, sbuf
;
333 int prev_d
, lspc
, ljust
;
338 sbuf_append(&sbuf
, line
);
339 lspc
= MAX(1, n_L
) * n_v
; /* line space, ignoreing \x */
341 if (!n_ns
|| line
[0] || els_neg
|| els_pos
) {
345 if (line
[0] && n_nm
&& body
)
347 if (!ren_div
&& dir_do
)
349 ljust
= ren_ljust(&sbeg
, w
, ad
, li
, lI
, ll
);
350 if (line
[0] && body
&& n_mc
)
351 ren_mc(&send
, w
, ljust
);
352 ren_out(sbuf_buf(&sbeg
), sbuf_buf(&sbuf
), sbuf_buf(&send
));
361 if (detect_traps(prev_d
, n_d
) || detect_pagelimit(lspc
- n_v
)) {
362 if (!ren_pagelimit(lspc
- n_v
))
363 ren_traps(prev_d
, n_d
, 0);
366 if (lspc
- n_v
&& down(lspc
- n_v
))
371 /* read a line from fmt and send it to ren_line() */
372 static int ren_passline(struct fmt
*fmt
)
375 int ll
, li
, lI
, els_neg
, els_pos
, w
, ret
;
378 if (!fmt_morewords(fmt
))
380 buf
= fmt_nextline(fmt
, &w
, &li
, &lI
, &ll
, &els_neg
, &els_pos
);
381 if ((n_cp
&& !n_u
) || n_na
)
383 else if ((ad
& AD_B
) == AD_B
)
384 ad
= n_td
> 0 ? AD_R
: AD_L
;
387 ret
= ren_line(buf
, w
, ad
, 1, li
, lI
, ll
, els_neg
, els_pos
);
392 /* output formatted lines in fmt */
393 static int ren_fmtpop(struct fmt
*fmt
)
396 while (fmt_morelines(fmt
))
397 ret
= ren_passline(fmt
);
401 /* format and output all lines in fmt */
402 static void ren_fmtpopall(struct fmt
*fmt
)
404 while (fmt_fill(fmt
, 0))
409 /* pass the given word buffer to the current line buffer (cfmt) */
410 static void ren_fmtword(struct wb
*wb
)
412 while (fmt_word(cfmt
, wb
))
417 /* output current line; returns 1 if triggered a trap */
418 static int ren_br(void)
422 while (fmt_fill(cfmt
, 1))
424 return ren_fmtpop(cfmt
);
427 void tr_br(char **args
)
429 if (args
[0][0] == c_cc
)
432 ren_fmtpopall(cfmt
); /* output the completed lines */
435 void tr_sp(char **args
)
439 if (args
[0][0] == c_cc
)
441 n
= args
[1] ? eval(args
[1], 'v') : n_v
;
442 if (n
&& (!n_ns
|| ren_div
) && !traps
)
446 void tr_sv(char **args
)
448 int n
= eval(args
[1], 'v');
450 if (n_d
+ n
< f_nexttrap())
456 void tr_ns(char **args
)
461 void tr_rs(char **args
)
466 void tr_os(char **args
)
473 void tr_mk(char **args
)
476 num_set(map(args
[1]), n_d
);
481 void tr_rt(char **args
)
483 int n
= args
[1] ? eval_re(args
[1], n_d
, 'v') : n_mk
;
484 if (n
>= 0 && n
< n_d
)
488 void tr_ne(char **args
)
490 int n
= args
[1] ? eval(args
[1], 'v') : n_v
;
493 if (!ren_traps(n_d
, n_d
+ n
- 1, 1))
497 static void ren_ejectpage(int br
)
503 while (n_PG
== bp_ejected
&& !cdiv
) {
504 if (detect_traps(n_d
, n_p
)) {
505 ren_traps(n_d
, n_p
, 1);
513 void tr_bp(char **args
)
515 if (!cdiv
&& (args
[1] || !n_ns
)) {
517 bp_next
= eval_re(args
[1], n_pg
, 0);
518 ren_ejectpage(args
[0][0] == c_cc
);
522 void tr_pn(char **args
)
525 bp_next
= eval_re(args
[1], n_pg
, 0);
528 static void ren_ps(char *s
)
530 int ps
= !s
|| !*s
|| !strcmp("0", s
) ?
531 n_s0
* SC_PT
: eval_re(s
, n_s
* SC_PT
, 'p');
533 n_s
= MAX(1, (ps
+ SC_PT
/ 2) / SC_PT
);
536 void tr_ps(char **args
)
541 void tr_ll(char **args
)
543 int ll
= args
[1] ? eval_re(args
[1], n_l
, 'm') : n_l0
;
548 void tr_in(char **args
)
550 int in
= args
[1] ? eval_re(args
[1], n_i
, 'm') : n_i0
;
551 if (args
[0][0] == c_cc
)
558 void tr_ti(char **args
)
560 if (args
[0][0] == c_cc
)
563 n_ti
= eval_re(args
[1], n_i
, 'm');
566 void tr_l2r(char **args
)
569 if (args
[0][0] == c_cc
)
575 void tr_r2l(char **args
)
578 if (args
[0][0] == c_cc
)
584 void tr_in2(char **args
)
586 int I
= args
[1] ? eval_re(args
[1], n_I
, 'm') : n_I0
;
587 if (args
[0][0] == c_cc
)
594 void tr_ti2(char **args
)
596 if (args
[0][0] == c_cc
)
599 n_tI
= eval_re(args
[1], n_I
, 'm');
602 static void ren_ft(char *s
)
604 int fn
= !s
|| !*s
|| !strcmp("P", s
) ? n_f0
: dev_pos(s
);
606 errmsg("neatroff: failed to mount <%s>\n", s
);
613 void tr_ft(char **args
)
618 void tr_fp(char **args
)
623 pos
= isdigit((unsigned char) args
[1][0]) ? atoi(args
[1]) : -1;
624 if (dev_mnt(pos
, args
[2], args
[3] ? args
[3] : args
[2]) < 0)
625 errmsg("neatroff: failed to mount <%s>\n", args
[2]);
628 void tr_nf(char **args
)
630 if (args
[0][0] == c_cc
)
635 void tr_fi(char **args
)
637 if (args
[0][0] == c_cc
)
642 void tr_ce(char **args
)
644 if (args
[0][0] == c_cc
)
646 n_ce
= args
[1] ? atoi(args
[1]) : 1;
649 void tr_fc(char **args
)
653 if (fa
&& charread(&fa
, c_fa
) >= 0) {
654 if (!fb
|| charread(&fb
, c_fb
) < 0)
662 static void ren_cl(char *s
)
664 int m
= !s
|| !*s
? n_m0
: clr_get(s
);
669 void tr_cl(char **args
)
674 void tr_ab(char **args
)
676 fprintf(stderr
, "%s\n", args
[1]);
680 static void ren_cmd(struct wb
*wb
, int c
, char *arg
)
684 wb_hmov(wb
, font_swid(dev_font(n_f
), n_s
, n_ss
));
696 wb_vmov(wb
, SC_EM
/ 2);
702 wb_hmov(wb
, eval(arg
, 'm'));
705 wb_setcost(wb
, eval(arg
, 0));
708 num_set(map(arg
), wb
== cwb
? f_hpos() - n_lb
: wb_wid(wb
));
724 while (fmt_fillreq(cfmt
))
734 wb_vmov(wb
, -SC_EM
/ 2);
737 wb_vmov(wb
, eval(arg
, 'v'));
743 wb_els(wb
, eval(arg
, 'v'));
752 wb_hmov(wb
, SC_EM
/ 6);
758 wb_hmov(wb
, SC_EM
/ 12);
761 wb_italiccorrection(wb
);
764 wb_italiccorrectionleft(wb
);
774 static void ren_field(struct wb
*wb
, int (*next
)(void), void (*back
)(int));
775 static void ren_tab(struct wb
*wb
, char *tc
, int (*next
)(void), void (*back
)(int));
777 /* insert a character, escape sequence, field or etc into wb */
778 static void ren_put(struct wb
*wb
, char *c
, int (*next
)(void), void (*back
)(int))
781 if (c
[0] == ' ' || c
[0] == '\n') {
785 if (c
[0] == '\t' || c
[0] == '\x01') {
786 ren_tab(wb
, c
[0] == '\t' ? c_tc
: c_lc
, next
, back
);
789 if (c_fa
[0] && !strcmp(c_fa
, c
)) {
790 ren_field(wb
, next
, back
);
796 ren_char(wb
, next
, back
);
797 wb_hmov(wb
, w
- wb_wid(wb
));
800 if (strchr(" bCcDdefHhjkLlmNoprSsuvXxZz0^|!{}&/,<>", c
[1])) {
802 if (strchr(ESC_P
, c
[1]))
803 arg
= unquotednext(c
[1], next
, back
);
804 if (strchr(ESC_Q
, c
[1]))
805 arg
= quotednext(next
, back
);
807 snprintf(c
, GNLEN
, "%c%c", c_ec
, c_ec
);
808 } else if (c
[1] == 'N') {
809 snprintf(c
, GNLEN
, "GID=%s", arg
);
811 ren_cmd(wb
, c
[1], arg
);
822 if (cdef_map(c
, n_f
)) /* .char characters */
828 /* read one character and place it inside wb buffer */
829 int ren_char(struct wb
*wb
, int (*next
)(void), void (*back
)(int))
832 if (charnext(c
, next
, back
) < 0)
834 ren_put(wb
, c
, next
, back
);
838 /* like ren_char(); return 1 if d1 was read and 2 if d2 was read */
839 static int ren_chardel(struct wb
*wb
, int (*next
)(void), void (*back
)(int),
843 if (charnext(c
, next
, back
) < 0)
845 if (d1
&& !strcmp(d1
, c
))
847 if (d2
&& !strcmp(d2
, c
))
849 ren_put(wb
, c
, next
, back
);
853 /* read the argument of \w and push its width */
854 int ren_wid(int (*next
)(void), void (*back
)(int))
860 charnext(delim
, next
, back
);
863 while (c
>= 0 && c
!= '\n') {
865 if (ren_chardel(&wb
, next
, back
, delim
, NULL
))
871 wb_wconf(&wb
, &n_ct
, &n_st
, &n_sb
, &n_llx
, &n_lly
, &n_urx
, &n_ury
);
876 /* return 1 if d1 was read and 2 if d2 was read */
877 static int ren_until(struct wb
*wb
, int (*next
)(void), void (*back
)(int),
882 while (c
>= 0 && c
!= '\n') {
884 ret
= ren_chardel(wb
, next
, back
, d1
, d2
);
894 /* like ren_until(); map src to dst */
895 static int ren_untilmap(struct wb
*wb
, int (*next
)(void), void (*back
)(int),
896 char *end
, char *src
, char *dst
)
899 while ((ret
= ren_until(wb
, next
, back
, src
, end
)) == 1) {
901 ren_until(wb
, sstr_next
, sstr_back
, end
, NULL
);
907 static void wb_cpy(struct wb
*dst
, struct wb
*src
, int left
)
909 wb_hmov(dst
, left
- wb_wid(dst
));
913 void ren_tl(int (*next
)(void), void (*back
)(int))
919 pgnum
= num_str(map("%"));
922 charnext(delim
, next
, back
);
923 if (!strcmp("\n", delim
))
925 /* the left-adjusted string */
926 ren_untilmap(&wb2
, next
, back
, delim
, c_pc
, pgnum
);
927 wb_cpy(&wb
, &wb2
, 0);
928 /* the centered string */
929 ren_untilmap(&wb2
, next
, back
, delim
, c_pc
, pgnum
);
930 wb_cpy(&wb
, &wb2
, (n_lt
- wb_wid(&wb2
)) / 2);
931 /* the right-adjusted string */
932 ren_untilmap(&wb2
, next
, back
, delim
, c_pc
, pgnum
);
933 wb_cpy(&wb
, &wb2
, n_lt
- wb_wid(&wb2
));
934 /* flushing the line */
935 ren_line(wb_buf(&wb
), wb_wid(&wb
), AD_L
, 0,
936 0, 0, n_lt
, wb
.els_neg
, wb
.els_pos
);
941 static void ren_field(struct wb
*wb
, int (*next
)(void), void (*back
)(int))
943 struct wb wbs
[NFIELDS
];
946 int left
, right
, cur_left
;
948 while (n
< LEN(wbs
)) {
950 if (ren_until(&wbs
[n
++], next
, back
, c_fb
, c_fa
) != 1)
953 left
= wb
== cwb
? f_hpos() : wb_wid(wb
);
954 right
= tab_next(left
);
955 for (i
= 0; i
< n
; i
++)
956 wid
+= wb_wid(&wbs
[i
]);
957 pad
= (right
- left
- wid
) / (n
> 1 ? n
- 1 : 1);
958 rem
= (right
- left
- wid
) % (n
> 1 ? n
- 1 : 1);
959 for (i
= 0; i
< n
; i
++) {
963 cur_left
= right
- wb_wid(&wbs
[i
]);
965 cur_left
= wb_wid(wb
) + pad
+ (i
+ rem
>= n
);
966 wb_cpy(wb
, &wbs
[i
], cur_left
);
971 static void ren_tab(struct wb
*wb
, char *tc
, int (*next
)(void), void (*back
)(int))
974 int pos
= wb
== cwb
? f_hpos() : wb_wid(wb
);
975 int ins
= tab_next(pos
); /* insertion position */
976 int typ
= tab_type(pos
); /* tab type */
979 if (typ
== 'R' || typ
== 'C') {
981 while (c
>= 0 && c
!= '\n' && c
!= '\t' && c
!= '\x01') {
983 ren_char(&t
, next
, back
);
989 ins
-= wb_wid(&t
) / 2;
992 if (!tc
[0] || ins
<= pos
)
993 wb_hmov(wb
, ins
- pos
);
995 ren_hline(wb
, ins
- pos
, tc
);
1000 /* parse characters and troff requests of s and append them to wb */
1001 int ren_parse(struct wb
*wb
, char *s
)
1009 if (ren_char(wb
, sstr_next
, sstr_back
))
1018 /* cause nested render_rec() to exit */
1019 void tr_popren(char **args
)
1021 ren_level
= args
[1] ? atoi(args
[1]) : 0;
1024 #define FMT_PAR() (n_u && !n_na && !n_ce && (n_j & AD_P) == AD_P)
1026 /* read characters from tr.c and pass the rendered lines to out.c */
1027 static int render_rec(int level
)
1029 int ren_div_saved
= ren_div
;
1032 while (ren_level
>= level
) {
1033 while (!ren_un
&& !tr_nextreq())
1034 if (ren_level
< level
)
1036 if (ren_level
< level
)
1044 if (bp_final
== 0) {
1054 ren_partial
= c
!= '\n';
1055 /* add cwb (the current word) to cfmt */
1056 if (c
== ' ' || c
== '\n') {
1057 if (!wb_part(cwb
)) { /* not after a \c */
1060 while (fmt_newline(cfmt
))
1063 ren_fmtpopall(cfmt
);
1068 /* flush the line if necessary */
1069 if (c
== ' ' || c
== '\n' || c
< 0)
1071 if (c
== '\n' || ren_nl
) /* end or start of input line */
1073 if (c
== '\n' && n_it
&& --n_itn
== 0)
1075 if (c
== '\n' && !wb_part(cwb
))
1076 n_ce
= MAX(0, n_ce
- 1);
1077 if (c
!= ' ' && c
>= 0) {
1079 ren_char(cwb
, ren_next
, ren_back
);
1084 /* restore ren_div after processing traps */
1085 ren_div
= ren_div_saved
;
1089 /* render input words */
1093 while (!tr_nextreq())
1095 ren_first(); /* transition to the first page */
1098 if (fmt_morewords(cfmt
))
1106 #define tposval(i) (tpos[i] < 0 ? n_p + tpos[i] : tpos[i])
1108 static int tpos
[NTRAPS
]; /* trap positions */
1109 static int treg
[NTRAPS
]; /* trap registers */
1112 static int trap_first(int pos
)
1116 for (i
= 0; i
< ntraps
; i
++)
1117 if (treg
[i
] >= 0 && tposval(i
) > pos
)
1118 if (best
< 0 || tposval(i
) < tposval(best
))
1123 static int trap_byreg(int reg
)
1126 for (i
= 0; i
< ntraps
; i
++)
1132 static int trap_bypos(int reg
, int pos
)
1135 for (i
= 0; i
< ntraps
; i
++)
1136 if (treg
[i
] >= 0 && tposval(i
) == pos
)
1137 if (reg
== -1 || treg
[i
] == reg
)
1142 void tr_wh(char **args
)
1147 pos
= eval(args
[1], 'v');
1148 id
= trap_bypos(-1, pos
);
1155 if (id
< 0) /* find an unused position in treg[] */
1156 id
= trap_byreg(-1);
1163 void tr_ch(char **args
)
1170 id
= trap_byreg(reg
);
1173 tpos
[id
] = eval(args
[2], 'v');
1179 void tr_dt(char **args
)
1184 cdiv
->tpos
= eval(args
[1], 'v');
1185 cdiv
->treg
= map(args
[2]);
1191 void tr_em(char **args
)
1193 trap_em
= args
[1] ? map(args
[1]) : -1;
1196 static int trap_pos(int pos
)
1198 int ret
= trap_first(pos
);
1202 return cdiv
->treg
&& cdiv
->tpos
> pos
? cdiv
->tpos
: -1;
1203 return ret
>= 0 ? tposval(ret
) : -1;
1206 static int trap_reg(int pos
)
1208 int ret
= trap_first(pos
);
1210 return cdiv
->treg
&& cdiv
->tpos
> pos
? cdiv
->treg
: -1;
1211 return ret
>= 0 ? treg
[ret
] : -1;
1214 int f_nexttrap(void)
1216 int pos
= trap_pos(n_d
);
1218 return pos
>= 0 ? pos
: 0x7fffffff;
1219 return (pos
>= 0 && pos
< n_p
? pos
: n_p
) - n_d
;