1*426d2b71SDavid du Colombier /*
2*426d2b71SDavid du Colombier * 7. Macros, strings, diversion, and position traps.
3*426d2b71SDavid du Colombier *
4*426d2b71SDavid du Colombier * macros can override builtins
5*426d2b71SDavid du Colombier * builtins can be renamed or removed!
6*426d2b71SDavid du Colombier */
7*426d2b71SDavid du Colombier
8*426d2b71SDavid du Colombier #include "a.h"
9*426d2b71SDavid du Colombier
10*426d2b71SDavid du Colombier enum
11*426d2b71SDavid du Colombier {
12*426d2b71SDavid du Colombier MAXARG = 10,
13*426d2b71SDavid du Colombier MAXMSTACK = 40
14*426d2b71SDavid du Colombier };
15*426d2b71SDavid du Colombier
16*426d2b71SDavid du Colombier /* macro invocation frame */
17*426d2b71SDavid du Colombier typedef struct Mac Mac;
18*426d2b71SDavid du Colombier struct Mac
19*426d2b71SDavid du Colombier {
20*426d2b71SDavid du Colombier int argc;
21*426d2b71SDavid du Colombier Rune *argv[MAXARG];
22*426d2b71SDavid du Colombier };
23*426d2b71SDavid du Colombier
24*426d2b71SDavid du Colombier Mac mstack[MAXMSTACK];
25*426d2b71SDavid du Colombier int nmstack;
26*426d2b71SDavid du Colombier void emitdi(void);
27*426d2b71SDavid du Colombier void flushdi(void);
28*426d2b71SDavid du Colombier
29*426d2b71SDavid du Colombier /*
30*426d2b71SDavid du Colombier * Run a user-defined macro.
31*426d2b71SDavid du Colombier */
32*426d2b71SDavid du Colombier void popmacro(void);
33*426d2b71SDavid du Colombier int
runmacro(int dot,int argc,Rune ** argv)34*426d2b71SDavid du Colombier runmacro(int dot, int argc, Rune **argv)
35*426d2b71SDavid du Colombier {
36*426d2b71SDavid du Colombier Rune *p;
37*426d2b71SDavid du Colombier int i;
38*426d2b71SDavid du Colombier Mac *m;
39*426d2b71SDavid du Colombier
40*426d2b71SDavid du Colombier if(verbose && isupperrune(argv[0][0])) fprint(2, "run: %S\n", argv[0]);
41*426d2b71SDavid du Colombier p = getds(argv[0]);
42*426d2b71SDavid du Colombier if(p == nil){
43*426d2b71SDavid du Colombier if(verbose)
44*426d2b71SDavid du Colombier warn("ignoring unknown request %C%S", dot, argv[0]);
45*426d2b71SDavid du Colombier if(verbose > 1){
46*426d2b71SDavid du Colombier for(i=0; i<argc; i++)
47*426d2b71SDavid du Colombier fprint(2, " %S", argv[i]);
48*426d2b71SDavid du Colombier fprint(2, "\n");
49*426d2b71SDavid du Colombier }
50*426d2b71SDavid du Colombier return -1;
51*426d2b71SDavid du Colombier }
52*426d2b71SDavid du Colombier if(nmstack >= nelem(mstack)){
53*426d2b71SDavid du Colombier fprint(2, "%L: macro stack overflow:");
54*426d2b71SDavid du Colombier for(i=0; i<nmstack; i++)
55*426d2b71SDavid du Colombier fprint(2, " %S", mstack[i].argv[0]);
56*426d2b71SDavid du Colombier fprint(2, "\n");
57*426d2b71SDavid du Colombier return -1;
58*426d2b71SDavid du Colombier }
59*426d2b71SDavid du Colombier m = &mstack[nmstack++];
60*426d2b71SDavid du Colombier m->argc = argc;
61*426d2b71SDavid du Colombier for(i=0; i<argc; i++)
62*426d2b71SDavid du Colombier m->argv[i] = erunestrdup(argv[i]);
63*426d2b71SDavid du Colombier pushinputstring(p);
64*426d2b71SDavid du Colombier nr(L(".$"), argc-1);
65*426d2b71SDavid du Colombier inputnotify(popmacro);
66*426d2b71SDavid du Colombier return 0;
67*426d2b71SDavid du Colombier }
68*426d2b71SDavid du Colombier
69*426d2b71SDavid du Colombier void
popmacro(void)70*426d2b71SDavid du Colombier popmacro(void)
71*426d2b71SDavid du Colombier {
72*426d2b71SDavid du Colombier int i;
73*426d2b71SDavid du Colombier Mac *m;
74*426d2b71SDavid du Colombier
75*426d2b71SDavid du Colombier if(--nmstack < 0){
76*426d2b71SDavid du Colombier fprint(2, "%L: macro stack underflow\n");
77*426d2b71SDavid du Colombier return;
78*426d2b71SDavid du Colombier }
79*426d2b71SDavid du Colombier m = &mstack[nmstack];
80*426d2b71SDavid du Colombier for(i=0; i<m->argc; i++)
81*426d2b71SDavid du Colombier free(m->argv[i]);
82*426d2b71SDavid du Colombier if(nmstack > 0)
83*426d2b71SDavid du Colombier nr(L(".$"), mstack[nmstack-1].argc-1);
84*426d2b71SDavid du Colombier else
85*426d2b71SDavid du Colombier nr(L(".$"), 0);
86*426d2b71SDavid du Colombier }
87*426d2b71SDavid du Colombier
88*426d2b71SDavid du Colombier void popmacro1(void);
89*426d2b71SDavid du Colombier jmp_buf runjb[10];
90*426d2b71SDavid du Colombier int nrunjb;
91*426d2b71SDavid du Colombier
92*426d2b71SDavid du Colombier void
runmacro1(Rune * name)93*426d2b71SDavid du Colombier runmacro1(Rune *name)
94*426d2b71SDavid du Colombier {
95*426d2b71SDavid du Colombier Rune *argv[2];
96*426d2b71SDavid du Colombier int obol;
97*426d2b71SDavid du Colombier
98*426d2b71SDavid du Colombier if(verbose) fprint(2, "outcb %p\n", outcb);
99*426d2b71SDavid du Colombier obol = bol;
100*426d2b71SDavid du Colombier argv[0] = name;
101*426d2b71SDavid du Colombier argv[1] = nil;
102*426d2b71SDavid du Colombier bol = 1;
103*426d2b71SDavid du Colombier if(runmacro('.', 1, argv) >= 0){
104*426d2b71SDavid du Colombier inputnotify(popmacro1);
105*426d2b71SDavid du Colombier if(!setjmp(runjb[nrunjb++]))
106*426d2b71SDavid du Colombier runinput();
107*426d2b71SDavid du Colombier else
108*426d2b71SDavid du Colombier if(verbose) fprint(2, "finished %S\n", name);
109*426d2b71SDavid du Colombier }
110*426d2b71SDavid du Colombier bol = obol;
111*426d2b71SDavid du Colombier }
112*426d2b71SDavid du Colombier
113*426d2b71SDavid du Colombier void
popmacro1(void)114*426d2b71SDavid du Colombier popmacro1(void)
115*426d2b71SDavid du Colombier {
116*426d2b71SDavid du Colombier popmacro();
117*426d2b71SDavid du Colombier if(nrunjb >= 0)
118*426d2b71SDavid du Colombier longjmp(runjb[--nrunjb], 1);
119*426d2b71SDavid du Colombier }
120*426d2b71SDavid du Colombier
121*426d2b71SDavid du Colombier /*
122*426d2b71SDavid du Colombier * macro arguments
123*426d2b71SDavid du Colombier *
124*426d2b71SDavid du Colombier * "" means " inside " "
125*426d2b71SDavid du Colombier * "" empty string
126*426d2b71SDavid du Colombier * \newline can be done
127*426d2b71SDavid du Colombier * argument separator is space (not tab)
128*426d2b71SDavid du Colombier * number register .$ = number of arguments
129*426d2b71SDavid du Colombier * no arguments outside macros or in strings
130*426d2b71SDavid du Colombier *
131*426d2b71SDavid du Colombier * arguments copied in copy mode
132*426d2b71SDavid du Colombier */
133*426d2b71SDavid du Colombier
134*426d2b71SDavid du Colombier /*
135*426d2b71SDavid du Colombier * diversions
136*426d2b71SDavid du Colombier *
137*426d2b71SDavid du Colombier * processed output diverted
138*426d2b71SDavid du Colombier * dn dl registers vertical and horizontal size of last diversion
139*426d2b71SDavid du Colombier * .z - current diversion name
140*426d2b71SDavid du Colombier */
141*426d2b71SDavid du Colombier
142*426d2b71SDavid du Colombier /*
143*426d2b71SDavid du Colombier * traps
144*426d2b71SDavid du Colombier *
145*426d2b71SDavid du Colombier * skip most
146*426d2b71SDavid du Colombier * .t register - distance to next trap
147*426d2b71SDavid du Colombier */
148*426d2b71SDavid du Colombier static Rune *trap0;
149*426d2b71SDavid du Colombier
150*426d2b71SDavid du Colombier void
outtrap(void)151*426d2b71SDavid du Colombier outtrap(void)
152*426d2b71SDavid du Colombier {
153*426d2b71SDavid du Colombier Rune *t;
154*426d2b71SDavid du Colombier
155*426d2b71SDavid du Colombier if(outcb)
156*426d2b71SDavid du Colombier return;
157*426d2b71SDavid du Colombier if(trap0){
158*426d2b71SDavid du Colombier if(verbose) fprint(2, "trap: %S\n", trap0);
159*426d2b71SDavid du Colombier t = trap0;
160*426d2b71SDavid du Colombier trap0 = nil;
161*426d2b71SDavid du Colombier runmacro1(t);
162*426d2b71SDavid du Colombier free(t);
163*426d2b71SDavid du Colombier }
164*426d2b71SDavid du Colombier }
165*426d2b71SDavid du Colombier
166*426d2b71SDavid du Colombier /* .wh - install trap */
167*426d2b71SDavid du Colombier void
r_wh(int argc,Rune ** argv)168*426d2b71SDavid du Colombier r_wh(int argc, Rune **argv)
169*426d2b71SDavid du Colombier {
170*426d2b71SDavid du Colombier int i;
171*426d2b71SDavid du Colombier
172*426d2b71SDavid du Colombier if(argc < 2)
173*426d2b71SDavid du Colombier return;
174*426d2b71SDavid du Colombier
175*426d2b71SDavid du Colombier i = eval(argv[1]);
176*426d2b71SDavid du Colombier if(argc == 2){
177*426d2b71SDavid du Colombier if(i == 0){
178*426d2b71SDavid du Colombier free(trap0);
179*426d2b71SDavid du Colombier trap0 = nil;
180*426d2b71SDavid du Colombier }else
181*426d2b71SDavid du Colombier if(verbose)
182*426d2b71SDavid du Colombier warn("not removing trap at %d", i);
183*426d2b71SDavid du Colombier }
184*426d2b71SDavid du Colombier if(argc > 2){
185*426d2b71SDavid du Colombier if(i == 0){
186*426d2b71SDavid du Colombier free(trap0);
187*426d2b71SDavid du Colombier trap0 = erunestrdup(argv[2]);
188*426d2b71SDavid du Colombier }else
189*426d2b71SDavid du Colombier if(verbose)
190*426d2b71SDavid du Colombier warn("not installing %S trap at %d", argv[2], i);
191*426d2b71SDavid du Colombier }
192*426d2b71SDavid du Colombier }
193*426d2b71SDavid du Colombier
194*426d2b71SDavid du Colombier void
r_ch(int argc,Rune ** argv)195*426d2b71SDavid du Colombier r_ch(int argc, Rune **argv)
196*426d2b71SDavid du Colombier {
197*426d2b71SDavid du Colombier int i;
198*426d2b71SDavid du Colombier
199*426d2b71SDavid du Colombier if(argc == 2){
200*426d2b71SDavid du Colombier if(trap0 && runestrcmp(argv[1], trap0) == 0){
201*426d2b71SDavid du Colombier free(trap0);
202*426d2b71SDavid du Colombier trap0 = nil;
203*426d2b71SDavid du Colombier }else
204*426d2b71SDavid du Colombier if(verbose)
205*426d2b71SDavid du Colombier warn("not removing %S trap", argv[1]);
206*426d2b71SDavid du Colombier return;
207*426d2b71SDavid du Colombier }
208*426d2b71SDavid du Colombier if(argc >= 3){
209*426d2b71SDavid du Colombier i = eval(argv[2]);
210*426d2b71SDavid du Colombier if(i == 0){
211*426d2b71SDavid du Colombier free(trap0);
212*426d2b71SDavid du Colombier trap0 = erunestrdup(argv[1]);
213*426d2b71SDavid du Colombier }else
214*426d2b71SDavid du Colombier if(verbose)
215*426d2b71SDavid du Colombier warn("not moving %S trap to %d", argv[1], i);
216*426d2b71SDavid du Colombier }
217*426d2b71SDavid du Colombier }
218*426d2b71SDavid du Colombier
219*426d2b71SDavid du Colombier void
r_dt(int argc,Rune ** argv)220*426d2b71SDavid du Colombier r_dt(int argc, Rune **argv)
221*426d2b71SDavid du Colombier {
222*426d2b71SDavid du Colombier USED(argc);
223*426d2b71SDavid du Colombier USED(argv);
224*426d2b71SDavid du Colombier warn("ignoring diversion trap");
225*426d2b71SDavid du Colombier }
226*426d2b71SDavid du Colombier
227*426d2b71SDavid du Colombier /* define macro - .de, .am, .ig */
228*426d2b71SDavid du Colombier void
r_de(int argc,Rune ** argv)229*426d2b71SDavid du Colombier r_de(int argc, Rune **argv)
230*426d2b71SDavid du Colombier {
231*426d2b71SDavid du Colombier Rune *end, *p;
232*426d2b71SDavid du Colombier Fmt fmt;
233*426d2b71SDavid du Colombier int ignore, len;
234*426d2b71SDavid du Colombier
235*426d2b71SDavid du Colombier delreq(argv[1]);
236*426d2b71SDavid du Colombier delraw(argv[1]);
237*426d2b71SDavid du Colombier ignore = runestrcmp(argv[0], L("ig")) == 0;
238*426d2b71SDavid du Colombier if(!ignore)
239*426d2b71SDavid du Colombier runefmtstrinit(&fmt);
240*426d2b71SDavid du Colombier end = L("..");
241*426d2b71SDavid du Colombier if(argc >= 3)
242*426d2b71SDavid du Colombier end = argv[2];
243*426d2b71SDavid du Colombier if(runestrcmp(argv[0], L("am")) == 0 && (p=getds(argv[1])) != nil)
244*426d2b71SDavid du Colombier fmtrunestrcpy(&fmt, p);
245*426d2b71SDavid du Colombier len = runestrlen(end);
246*426d2b71SDavid du Colombier while((p = readline(CopyMode)) != nil){
247*426d2b71SDavid du Colombier if(runestrncmp(p, end, len) == 0
248*426d2b71SDavid du Colombier && (p[len]==' ' || p[len]==0 || p[len]=='\t'
249*426d2b71SDavid du Colombier || (p[len]=='\\' && p[len+1]=='}'))){
250*426d2b71SDavid du Colombier free(p);
251*426d2b71SDavid du Colombier goto done;
252*426d2b71SDavid du Colombier }
253*426d2b71SDavid du Colombier if(!ignore)
254*426d2b71SDavid du Colombier fmtprint(&fmt, "%S\n", p);
255*426d2b71SDavid du Colombier free(p);
256*426d2b71SDavid du Colombier }
257*426d2b71SDavid du Colombier warn("eof in %C%S %S - looking for %#Q", dot, argv[0], argv[1], end);
258*426d2b71SDavid du Colombier done:
259*426d2b71SDavid du Colombier if(ignore)
260*426d2b71SDavid du Colombier return;
261*426d2b71SDavid du Colombier p = runefmtstrflush(&fmt);
262*426d2b71SDavid du Colombier if(p == nil)
263*426d2b71SDavid du Colombier sysfatal("out of memory");
264*426d2b71SDavid du Colombier ds(argv[1], p);
265*426d2b71SDavid du Colombier free(p);
266*426d2b71SDavid du Colombier }
267*426d2b71SDavid du Colombier
268*426d2b71SDavid du Colombier /* define string .ds .as */
269*426d2b71SDavid du Colombier void
r_ds(Rune * cmd)270*426d2b71SDavid du Colombier r_ds(Rune *cmd)
271*426d2b71SDavid du Colombier {
272*426d2b71SDavid du Colombier Rune *name, *line, *p;
273*426d2b71SDavid du Colombier
274*426d2b71SDavid du Colombier name = copyarg();
275*426d2b71SDavid du Colombier line = readline(CopyMode);
276*426d2b71SDavid du Colombier if(name == nil || line == nil){
277*426d2b71SDavid du Colombier free(name);
278*426d2b71SDavid du Colombier return;
279*426d2b71SDavid du Colombier }
280*426d2b71SDavid du Colombier p = line;
281*426d2b71SDavid du Colombier if(*p == '"')
282*426d2b71SDavid du Colombier p++;
283*426d2b71SDavid du Colombier if(cmd[0] == 'd')
284*426d2b71SDavid du Colombier ds(name, p);
285*426d2b71SDavid du Colombier else
286*426d2b71SDavid du Colombier as(name, p);
287*426d2b71SDavid du Colombier free(name);
288*426d2b71SDavid du Colombier free(line);
289*426d2b71SDavid du Colombier }
290*426d2b71SDavid du Colombier
291*426d2b71SDavid du Colombier /* remove request, macro, or string */
292*426d2b71SDavid du Colombier void
r_rm(int argc,Rune ** argv)293*426d2b71SDavid du Colombier r_rm(int argc, Rune **argv)
294*426d2b71SDavid du Colombier {
295*426d2b71SDavid du Colombier int i;
296*426d2b71SDavid du Colombier
297*426d2b71SDavid du Colombier emitdi();
298*426d2b71SDavid du Colombier for(i=1; i<argc; i++){
299*426d2b71SDavid du Colombier delreq(argv[i]);
300*426d2b71SDavid du Colombier delraw(argv[i]);
301*426d2b71SDavid du Colombier ds(argv[i], nil);
302*426d2b71SDavid du Colombier }
303*426d2b71SDavid du Colombier }
304*426d2b71SDavid du Colombier
305*426d2b71SDavid du Colombier /* .rn - rename request, macro, or string */
306*426d2b71SDavid du Colombier void
r_rn(int argc,Rune ** argv)307*426d2b71SDavid du Colombier r_rn(int argc, Rune **argv)
308*426d2b71SDavid du Colombier {
309*426d2b71SDavid du Colombier USED(argc);
310*426d2b71SDavid du Colombier renreq(argv[1], argv[2]);
311*426d2b71SDavid du Colombier renraw(argv[1], argv[2]);
312*426d2b71SDavid du Colombier ds(argv[2], getds(argv[1]));
313*426d2b71SDavid du Colombier ds(argv[1], nil);
314*426d2b71SDavid du Colombier }
315*426d2b71SDavid du Colombier
316*426d2b71SDavid du Colombier /* .di - divert output to macro xx */
317*426d2b71SDavid du Colombier /* .da - divert, appending to macro */
318*426d2b71SDavid du Colombier /* page offsetting is not done! */
319*426d2b71SDavid du Colombier Fmt difmt;
320*426d2b71SDavid du Colombier int difmtinit;
321*426d2b71SDavid du Colombier Rune di[20][100];
322*426d2b71SDavid du Colombier int ndi;
323*426d2b71SDavid du Colombier
324*426d2b71SDavid du Colombier void
emitdi(void)325*426d2b71SDavid du Colombier emitdi(void)
326*426d2b71SDavid du Colombier {
327*426d2b71SDavid du Colombier flushdi();
328*426d2b71SDavid du Colombier runefmtstrinit(&difmt);
329*426d2b71SDavid du Colombier difmtinit = 1;
330*426d2b71SDavid du Colombier fmtrune(&difmt, Uformatted);
331*426d2b71SDavid du Colombier }
332*426d2b71SDavid du Colombier
333*426d2b71SDavid du Colombier void
flushdi(void)334*426d2b71SDavid du Colombier flushdi(void)
335*426d2b71SDavid du Colombier {
336*426d2b71SDavid du Colombier int n;
337*426d2b71SDavid du Colombier Rune *p;
338*426d2b71SDavid du Colombier
339*426d2b71SDavid du Colombier if(ndi == 0 || difmtinit == 0)
340*426d2b71SDavid du Colombier return;
341*426d2b71SDavid du Colombier fmtrune(&difmt, Uunformatted);
342*426d2b71SDavid du Colombier p = runefmtstrflush(&difmt);
343*426d2b71SDavid du Colombier memset(&difmt, 0, sizeof difmt);
344*426d2b71SDavid du Colombier difmtinit = 0;
345*426d2b71SDavid du Colombier if(p == nil)
346*426d2b71SDavid du Colombier warn("out of memory in diversion %C%S", dot, di[ndi-1]);
347*426d2b71SDavid du Colombier else{
348*426d2b71SDavid du Colombier n = runestrlen(p);
349*426d2b71SDavid du Colombier if(n > 0 && p[n-1] != '\n'){
350*426d2b71SDavid du Colombier p = runerealloc(p, n+2);
351*426d2b71SDavid du Colombier p[n] = '\n';
352*426d2b71SDavid du Colombier p[n+1] = 0;
353*426d2b71SDavid du Colombier }
354*426d2b71SDavid du Colombier }
355*426d2b71SDavid du Colombier as(di[ndi-1], p);
356*426d2b71SDavid du Colombier free(p);
357*426d2b71SDavid du Colombier }
358*426d2b71SDavid du Colombier
359*426d2b71SDavid du Colombier void
outdi(Rune r)360*426d2b71SDavid du Colombier outdi(Rune r)
361*426d2b71SDavid du Colombier {
362*426d2b71SDavid du Colombier if(!difmtinit) abort();
363*426d2b71SDavid du Colombier if(r == Uempty)
364*426d2b71SDavid du Colombier return;
365*426d2b71SDavid du Colombier fmtrune(&difmt, r);
366*426d2b71SDavid du Colombier }
367*426d2b71SDavid du Colombier
368*426d2b71SDavid du Colombier /* .di, .da */
369*426d2b71SDavid du Colombier void
r_di(int argc,Rune ** argv)370*426d2b71SDavid du Colombier r_di(int argc, Rune **argv)
371*426d2b71SDavid du Colombier {
372*426d2b71SDavid du Colombier br();
373*426d2b71SDavid du Colombier if(argc > 2)
374*426d2b71SDavid du Colombier warn("extra arguments to %C%S", dot, argv[0]);
375*426d2b71SDavid du Colombier if(argc == 1){
376*426d2b71SDavid du Colombier /* end diversion */
377*426d2b71SDavid du Colombier if(ndi <= 0){
378*426d2b71SDavid du Colombier // warn("unmatched %C%S", dot, argv[0]);
379*426d2b71SDavid du Colombier return;
380*426d2b71SDavid du Colombier }
381*426d2b71SDavid du Colombier flushdi();
382*426d2b71SDavid du Colombier if(--ndi == 0){
383*426d2b71SDavid du Colombier _nr(L(".z"), nil);
384*426d2b71SDavid du Colombier outcb = nil;
385*426d2b71SDavid du Colombier }else{
386*426d2b71SDavid du Colombier _nr(L(".z"), di[ndi-1]);
387*426d2b71SDavid du Colombier runefmtstrinit(&difmt);
388*426d2b71SDavid du Colombier fmtrune(&difmt, Uformatted);
389*426d2b71SDavid du Colombier difmtinit = 1;
390*426d2b71SDavid du Colombier }
391*426d2b71SDavid du Colombier return;
392*426d2b71SDavid du Colombier }
393*426d2b71SDavid du Colombier /* start diversion */
394*426d2b71SDavid du Colombier /* various register state should be saved, but it's all useless to us */
395*426d2b71SDavid du Colombier flushdi();
396*426d2b71SDavid du Colombier if(ndi >= nelem(di))
397*426d2b71SDavid du Colombier sysfatal("%Cdi overflow", dot);
398*426d2b71SDavid du Colombier if(argv[0][1] == 'i')
399*426d2b71SDavid du Colombier ds(argv[1], nil);
400*426d2b71SDavid du Colombier _nr(L(".z"), argv[1]);
401*426d2b71SDavid du Colombier runestrcpy(di[ndi++], argv[1]);
402*426d2b71SDavid du Colombier runefmtstrinit(&difmt);
403*426d2b71SDavid du Colombier fmtrune(&difmt, Uformatted);
404*426d2b71SDavid du Colombier difmtinit = 1;
405*426d2b71SDavid du Colombier outcb = outdi;
406*426d2b71SDavid du Colombier }
407*426d2b71SDavid du Colombier
408*426d2b71SDavid du Colombier /* .wh - install trap */
409*426d2b71SDavid du Colombier /* .ch - change trap */
410*426d2b71SDavid du Colombier /* .dt - install diversion trap */
411*426d2b71SDavid du Colombier
412*426d2b71SDavid du Colombier /* set input-line count trap */
413*426d2b71SDavid du Colombier int itrapcount;
414*426d2b71SDavid du Colombier int itrapwaiting;
415*426d2b71SDavid du Colombier Rune *itrapname;
416*426d2b71SDavid du Colombier
417*426d2b71SDavid du Colombier void
r_it(int argc,Rune ** argv)418*426d2b71SDavid du Colombier r_it(int argc, Rune **argv)
419*426d2b71SDavid du Colombier {
420*426d2b71SDavid du Colombier if(argc < 3){
421*426d2b71SDavid du Colombier itrapcount = 0;
422*426d2b71SDavid du Colombier return;
423*426d2b71SDavid du Colombier }
424*426d2b71SDavid du Colombier itrapcount = eval(argv[1]);
425*426d2b71SDavid du Colombier free(itrapname);
426*426d2b71SDavid du Colombier itrapname = erunestrdup(argv[2]);
427*426d2b71SDavid du Colombier }
428*426d2b71SDavid du Colombier
429*426d2b71SDavid du Colombier void
itrap(void)430*426d2b71SDavid du Colombier itrap(void)
431*426d2b71SDavid du Colombier {
432*426d2b71SDavid du Colombier itrapset();
433*426d2b71SDavid du Colombier if(itrapwaiting){
434*426d2b71SDavid du Colombier itrapwaiting = 0;
435*426d2b71SDavid du Colombier runmacro1(itrapname);
436*426d2b71SDavid du Colombier }
437*426d2b71SDavid du Colombier }
438*426d2b71SDavid du Colombier
439*426d2b71SDavid du Colombier void
itrapset(void)440*426d2b71SDavid du Colombier itrapset(void)
441*426d2b71SDavid du Colombier {
442*426d2b71SDavid du Colombier if(itrapcount > 0 && --itrapcount == 0)
443*426d2b71SDavid du Colombier itrapwaiting = 1;
444*426d2b71SDavid du Colombier }
445*426d2b71SDavid du Colombier
446*426d2b71SDavid du Colombier /* .em - invoke macro when all input is over */
447*426d2b71SDavid du Colombier void
r_em(int argc,Rune ** argv)448*426d2b71SDavid du Colombier r_em(int argc, Rune **argv)
449*426d2b71SDavid du Colombier {
450*426d2b71SDavid du Colombier Rune buf[20];
451*426d2b71SDavid du Colombier
452*426d2b71SDavid du Colombier USED(argc);
453*426d2b71SDavid du Colombier runesnprint(buf, nelem(buf), ".%S\n", argv[1]);
454*426d2b71SDavid du Colombier as(L("eof"), buf);
455*426d2b71SDavid du Colombier }
456*426d2b71SDavid du Colombier
457*426d2b71SDavid du Colombier int
e_star(void)458*426d2b71SDavid du Colombier e_star(void)
459*426d2b71SDavid du Colombier {
460*426d2b71SDavid du Colombier Rune *p;
461*426d2b71SDavid du Colombier
462*426d2b71SDavid du Colombier p = getds(getname());
463*426d2b71SDavid du Colombier if(p)
464*426d2b71SDavid du Colombier pushinputstring(p);
465*426d2b71SDavid du Colombier return 0;
466*426d2b71SDavid du Colombier }
467*426d2b71SDavid du Colombier
468*426d2b71SDavid du Colombier int
e_t(void)469*426d2b71SDavid du Colombier e_t(void)
470*426d2b71SDavid du Colombier {
471*426d2b71SDavid du Colombier if(inputmode&CopyMode)
472*426d2b71SDavid du Colombier return '\t';
473*426d2b71SDavid du Colombier return 0;
474*426d2b71SDavid du Colombier }
475*426d2b71SDavid du Colombier
476*426d2b71SDavid du Colombier int
e_a(void)477*426d2b71SDavid du Colombier e_a(void)
478*426d2b71SDavid du Colombier {
479*426d2b71SDavid du Colombier if(inputmode&CopyMode)
480*426d2b71SDavid du Colombier return '\a';
481*426d2b71SDavid du Colombier return 0;
482*426d2b71SDavid du Colombier }
483*426d2b71SDavid du Colombier
484*426d2b71SDavid du Colombier int
e_backslash(void)485*426d2b71SDavid du Colombier e_backslash(void)
486*426d2b71SDavid du Colombier {
487*426d2b71SDavid du Colombier if(inputmode&ArgMode)
488*426d2b71SDavid du Colombier ungetrune('\\');
489*426d2b71SDavid du Colombier return backslash;
490*426d2b71SDavid du Colombier }
491*426d2b71SDavid du Colombier
492*426d2b71SDavid du Colombier int
e_dot(void)493*426d2b71SDavid du Colombier e_dot(void)
494*426d2b71SDavid du Colombier {
495*426d2b71SDavid du Colombier return '.';
496*426d2b71SDavid du Colombier }
497*426d2b71SDavid du Colombier
498*426d2b71SDavid du Colombier int
e_dollar(void)499*426d2b71SDavid du Colombier e_dollar(void)
500*426d2b71SDavid du Colombier {
501*426d2b71SDavid du Colombier int c;
502*426d2b71SDavid du Colombier
503*426d2b71SDavid du Colombier c = getnext();
504*426d2b71SDavid du Colombier if(c < '1' || c > '9'){
505*426d2b71SDavid du Colombier ungetnext(c);
506*426d2b71SDavid du Colombier return 0;
507*426d2b71SDavid du Colombier }
508*426d2b71SDavid du Colombier c -= '0';
509*426d2b71SDavid du Colombier if(nmstack <= 0 || mstack[nmstack-1].argc <= c)
510*426d2b71SDavid du Colombier return 0;
511*426d2b71SDavid du Colombier pushinputstring(mstack[nmstack-1].argv[c]);
512*426d2b71SDavid du Colombier return 0;
513*426d2b71SDavid du Colombier }
514*426d2b71SDavid du Colombier
515*426d2b71SDavid du Colombier void
t7init(void)516*426d2b71SDavid du Colombier t7init(void)
517*426d2b71SDavid du Colombier {
518*426d2b71SDavid du Colombier addreq(L("de"), r_de, -1);
519*426d2b71SDavid du Colombier addreq(L("am"), r_de, -1);
520*426d2b71SDavid du Colombier addreq(L("ig"), r_de, -1);
521*426d2b71SDavid du Colombier addraw(L("ds"), r_ds);
522*426d2b71SDavid du Colombier addraw(L("as"), r_ds);
523*426d2b71SDavid du Colombier addreq(L("rm"), r_rm, -1);
524*426d2b71SDavid du Colombier addreq(L("rn"), r_rn, -1);
525*426d2b71SDavid du Colombier addreq(L("di"), r_di, -1);
526*426d2b71SDavid du Colombier addreq(L("da"), r_di, -1);
527*426d2b71SDavid du Colombier addreq(L("it"), r_it, -1);
528*426d2b71SDavid du Colombier addreq(L("em"), r_em, 1);
529*426d2b71SDavid du Colombier addreq(L("wh"), r_wh, -1);
530*426d2b71SDavid du Colombier addreq(L("ch"), r_ch, -1);
531*426d2b71SDavid du Colombier addreq(L("dt"), r_dt, -1);
532*426d2b71SDavid du Colombier
533*426d2b71SDavid du Colombier addesc('$', e_dollar, CopyMode|ArgMode|HtmlMode);
534*426d2b71SDavid du Colombier addesc('*', e_star, CopyMode|ArgMode|HtmlMode);
535*426d2b71SDavid du Colombier addesc('t', e_t, CopyMode|ArgMode);
536*426d2b71SDavid du Colombier addesc('a', e_a, CopyMode|ArgMode);
537*426d2b71SDavid du Colombier addesc('\\', e_backslash, ArgMode|CopyMode);
538*426d2b71SDavid du Colombier addesc('.', e_dot, CopyMode|ArgMode);
539*426d2b71SDavid du Colombier
540*426d2b71SDavid du Colombier ds(L("eof"), L(".sp 0.5i\n"));
541*426d2b71SDavid du Colombier ds(L(".."), L(""));
542*426d2b71SDavid du Colombier }
543*426d2b71SDavid du Colombier
544