Blame


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