8 static int c_pc
= '%'; /* page number character */
13 /* skip everything until the end of line */
14 static void jmp_eol(void)
19 } while (c
>= 0 && c
!= '\n');
22 static void tr_vs(char **args
)
24 int vs
= args
[1] ? eval_re(args
[1], n_v
, 'p') : n_v0
;
29 static void tr_ls(char **args
)
31 int ls
= args
[1] ? eval_re(args
[1], n_L
, 0) : n_L0
;
36 static void tr_pl(char **args
)
38 int n
= eval_re(args
[1] ? args
[1] : "11i", n_p
, 'v');
42 static void tr_nr(char **args
)
48 num_set(id
, eval_re(args
[2], num_get(id
, 0), 'u'));
49 num_inc(id
, args
[3] ? eval(args
[3], 'u') : 0);
52 static void tr_rr(char **args
)
55 for (i
= 1; i
<= NARGS
; i
++)
57 num_del(map(args
[i
]));
60 static void tr_af(char **args
)
63 num_setfmt(map(args
[1]), args
[2]);
66 static void tr_ds(char **args
)
69 str_set(map(args
[1]), args
[2]);
72 static void tr_as(char **args
)
79 s1
= str_get(reg
) ? str_get(reg
) : "";
81 s
= malloc(strlen(s1
) + strlen(s2
) + 1);
88 static void tr_rm(char **args
)
91 for (i
= 1; i
<= NARGS
; i
++)
96 static void tr_rn(char **args
)
100 str_rn(map(args
[1]), map(args
[2]));
103 static void tr_po(char **args
)
105 int po
= args
[1] ? eval_re(args
[1], n_o
, 'm') : n_o0
;
110 static char *arg_regname(char *s
, int len
);
112 static void macrobody(struct sbuf
*sbuf
, char *end
)
118 cp_wid(0); /* copy-mode; disable \w handling */
119 while ((c
= cp_next()) >= 0) {
126 arg_regname(buf
, sizeof(buf
));
127 if ((n_cp
&& end
[0] == buf
[0] && end
[1] == buf
[1]) ||
135 for (i
= 0; buf
[i
]; i
++)
136 sbuf_add(sbuf
, (unsigned char) buf
[i
]);
146 static void tr_de(char **args
)
154 if (args
[0][1] == 'a' && args
[0][2] == 'm' && str_get(id
))
155 sbuf_append(&sbuf
, str_get(id
));
156 macrobody(&sbuf
, args
[2] ? args
[2] : ".");
157 str_set(id
, sbuf_buf(&sbuf
));
161 static void tr_ig(char **args
)
163 macrobody(NULL
, args
[1] ? args
[1] : ".");
166 /* read into sbuf until stop; if stop is NULL, stop at whitespace */
167 static int read_until(struct sbuf
*sbuf
, char *stop
)
169 char cs
[GNLEN
], cs2
[GNLEN
];
171 while ((c
= cp_next()) >= 0) {
175 if (!stop
&& (c
== ' ' || c
== '\t'))
177 charnext(cs
, cp_next
, cp_back
);
178 if (stop
&& !strcmp(stop
, cs
))
180 charnext_str(cs2
, cs
);
181 sbuf_append(sbuf
, cs2
);
186 /* evaluate .if strcmp (i.e. 'str'str') */
187 static int if_strcmp(void)
192 charnext(delim
, cp_next
, cp_back
);
195 read_until(&s1
, delim
);
196 read_until(&s2
, delim
);
197 ret
= !strcmp(sbuf_buf(&s1
), sbuf_buf(&s2
));
203 /* evaluate .if condition letters */
204 static int if_cond(void)
219 /* evaluate .if condition */
220 static int if_eval(void)
225 if (!read_until(&sbuf
, NULL
))
227 ret
= eval(sbuf_buf(&sbuf
), '\0') > 0;
232 static int ie_cond
[NIES
]; /* .ie condition stack */
235 static void tr_if(char **args
)
242 } while (c
== ' ' || c
== '\t');
248 if (strchr("oetn", c
)) {
250 } else if (!isdigit(c
) && !strchr("-+*/%<=>&:.|()", c
)) {
255 if (args
[0][1] == 'i' && args
[0][2] == 'e') /* .ie command */
257 ie_cond
[ie_depth
++] = ret
!= neg
;
261 static void tr_el(char **args
)
263 cp_blk(ie_depth
> 0 ? ie_cond
[--ie_depth
] : 1);
266 static void tr_na(char **args
)
271 static void tr_ad(char **args
)
276 switch (args
[1][0]) {
297 static void tr_tm(char **args
)
299 fprintf(stderr
, "%s\n", args
[1]);
302 static void tr_so(char **args
)
308 static void tr_nx(char **args
)
313 static void tr_ex(char **args
)
318 static void tr_sy(char **args
)
323 static void tr_lt(char **args
)
325 int lt
= args
[1] ? eval_re(args
[1], n_lt
, 'm') : n_t0
;
330 static void tr_pc(char **args
)
332 c_pc
= args
[1] ? args
[1][0] : -1;
335 static int tl_next(void)
338 if (c
>= 0 && c
== c_pc
) {
339 in_push(num_str(REG('%', '\0')), NULL
);
345 static void tr_tl(char **args
)
350 } while (c
>= 0 && (c
== ' ' || c
== '\t'));
352 ren_tl(tl_next
, cp_back
);
355 } while (c
>= 0 && c
!= '\n');
358 static void tr_ec(char **args
)
360 c_ec
= args
[1] ? args
[1][0] : '\\';
363 static void tr_cc(char **args
)
365 c_ec
= args
[1] ? args
[1][0] : '.';
368 static void tr_c2(char **args
)
370 c_ec
= args
[1] ? args
[1][0] : '\'';
373 static void tr_eo(char **args
)
378 static void tr_hc(char **args
)
381 if (!s
|| charread(&s
, c_hc
) < 0)
385 static void tr_nh(char **args
)
390 static void tr_hy(char **args
)
392 n_hy
= args
[1] ? atoi(args
[1]) : 1;
395 static void tr_lg(char **args
)
398 n_lg
= atoi(args
[1]);
401 static void tr_kn(char **args
)
404 n_kn
= atoi(args
[1]);
407 static void tr_cp(char **args
)
410 n_cp
= atoi(args
[1]);
413 static void tr_ss(char **args
)
416 n_ss
= eval_re(args
[1], n_ss
, 0);
419 static void tr_cs(char **args
)
423 dev_setcs(dev_pos(args
[1]), args
[2] ? eval(args
[2], 0) : 0);
426 static void tr_nm(char **args
)
433 n_ln
= eval_re(args
[1], n_ln
, 0);
435 if (args
[2] && isdigit(args
[2][0]))
436 n_nM
= MAX(1, eval(args
[2], 0));
437 if (args
[3] && isdigit(args
[3][0]))
438 n_nS
= MAX(0, eval(args
[3], 0));
439 if (args
[4] && isdigit(args
[4][0]))
440 n_nI
= MAX(0, eval(args
[4], 0));
443 static void tr_nn(char **args
)
445 n_nn
= args
[1] ? eval(args
[1], 0) : 1;
448 static void tr_bd(char **args
)
450 if (!args
[1] || !strcmp("S", args
[1]))
452 dev_setbd(dev_pos(args
[1]), args
[2] ? eval(args
[2], 'u') : 0);
455 static void tr_it(char **args
)
459 n_itn
= eval(args
[1], 0);
465 static void tr_mc(char **args
)
468 if (s
&& charread(&s
, c_mc
) >= 0) {
470 n_mcn
= args
[2] ? eval(args
[2], 'm') : SC_EM
;
476 static void tr_tc(char **args
)
479 if (!s
|| charread(&s
, c_tc
) < 0)
483 static void tr_lc(char **args
)
486 if (!s
|| charread(&s
, c_lc
) < 0)
490 static void tr_lf(char **args
)
493 in_lf(args
[2], eval(args
[1], 0));
496 /* character translation */
497 static char tr_src
[NTR
][GNLEN
];
498 static char tr_dst
[NTR
][GNLEN
];
501 static int tr_find(char *c
)
504 for (i
= 0; i
< tr_n
; i
++)
505 if (!strcmp(c
, tr_src
[i
]))
510 void tr_add(char *c1
, char *c2
)
513 if (i
< 0 && tr_n
< NTR
)
516 strcpy(tr_src
[i
], c1
);
517 strcpy(tr_dst
[i
], c2
);
521 char *tr_map(char *c
)
524 return i
>= 0 ? tr_dst
[i
] : c
;
527 static void tr_tr(char **args
)
530 char c1
[GNLEN
], c2
[GNLEN
];
531 while (s
&& charread(&s
, c1
) >= 0) {
532 if (charread(&s
, c2
) < 0)
538 static char *arg_regname(char *s
, int len
)
540 char *e
= n_cp
? s
+ 2 : s
+ len
;
542 while (c
== ' ' || c
== '\t')
544 while (s
< e
&& c
>= 0 && c
!= ' ' && c
!= '\t' && c
!= '\n') {
554 static char *arg_normal(char *s
, int len
)
556 char *e
= s
+ len
- 1;
566 while (s
< e
&& c
> 0 && c
!= '\n') {
567 if (!quoted
&& c
== ' ')
569 if (quoted
&& c
== '"') {
583 static char *arg_string(char *s
, int len
)
585 char *e
= s
+ len
- 1;
587 while ((c
= cp_next()) == ' ')
591 while (s
< e
&& c
> 0 && c
!= '\n') {
601 /* read macro arguments; trims tabs if rmtabs is nonzero */
602 static int mkargs(char **args
, char *buf
, int len
)
605 char *e
= buf
+ len
- 1;
611 if (c
< 0 || c
== '\n')
614 s
= arg_normal(s
, e
- s
);
622 /* read request arguments; trims tabs too */
623 static int mkargs_req(char **args
, char *buf
, int len
)
626 char *e
= buf
+ len
- 1;
630 while (n
< NARGS
&& s
< e
) {
632 while (c
== ' ' || c
== '\t')
634 while (c
>= 0 && c
!= '\n' && c
!= ' ' && c
!= '\t' && s
< e
) {
641 if (c
< 0 || c
== '\n')
648 /* read arguments for .ds */
649 static int mkargs_ds(char **args
, char *buf
, int len
)
652 char *e
= buf
+ len
- 1;
655 s
= arg_regname(s
, e
- s
);
658 s
= arg_string(s
, e
- s
);
661 if (c
>= 0 && c
!= '\n')
666 /* read arguments for commands .nr that expect a register name */
667 static int mkargs_reg1(char **args
, char *buf
, int len
)
670 char *e
= buf
+ len
- 1;
672 s
= arg_regname(s
, e
- s
);
673 return mkargs_req(args
+ 1, s
, e
- s
) + 1;
676 /* do not read arguments; for .if, .ie and .el */
677 static int mkargs_null(char **args
, char *buf
, int len
)
682 /* read the whole line for .tm */
683 static int mkargs_eol(char **args
, char *buf
, int len
)
686 char *e
= buf
+ len
- 1;
692 while (s
< e
&& c
>= 0 && c
!= '\n') {
702 void (*f
)(char **args
);
703 int (*args
)(char **args
, char *buf
, int len
);
705 {TR_DIVBEG
, tr_divbeg
},
706 {TR_DIVEND
, tr_divend
},
707 {TR_EJECT
, tr_eject
},
708 {"ab", tr_ab
, mkargs_eol
},
711 {"am", tr_de
, mkargs_reg1
},
712 {"as", tr_as
, mkargs_ds
},
723 {"de", tr_de
, mkargs_reg1
},
725 {"ds", tr_ds
, mkargs_ds
},
728 {"el", tr_el
, mkargs_null
},
740 {"ie", tr_if
, mkargs_null
},
741 {"if", tr_if
, mkargs_null
},
760 {"nr", tr_nr
, mkargs_reg1
},
778 {"sy", tr_sy
, mkargs_eol
},
782 {"tl", tr_tl
, mkargs_null
},
783 {"tm", tr_tm
, mkargs_eol
},
784 {"tr", tr_tr
, mkargs_eol
},
793 char *args
[NARGS
+ 3] = {NULL
};
797 while (tr_nl
&& c
>= 0 && (c
== c_cc
|| c
== c_c2
)) {
799 memset(args
, 0, sizeof(args
));
803 arg_regname(cmd
+ 1, sizeof(cmd
) - 1);
804 req
= str_dget(map(cmd
+ 1));
807 req
->args(args
+ 1, buf
, sizeof(buf
));
809 mkargs_req(args
+ 1, buf
, sizeof(buf
));
813 mkargs(args
+ 1, buf
, sizeof(buf
));
815 if (str_get(map(cmd
+ 1)))
816 in_push(str_get(map(cmd
+ 1)), args
+ 1);
828 for (i
= 0; i
< LEN(cmds
); i
++)
829 str_dset(map(cmds
[i
].id
), &cmds
[i
]);