BSD 4_3 development
[unix-history] / usr / contrib / jove / macros.c
CommitLineData
b346cbec
C
1/*************************************************************************
2 * This program is copyright (C) 1985, 1986 by Jonathan Payne. It is *
3 * provided to you without charge for use only on a licensed Unix *
4 * system. You may copy JOVE provided that this notice is included with *
5 * the copy. You may not sell copies of this program or versions *
6 * modified for use on microcomputer systems, unless the copies are *
7 * included with a Unix system distribution and the source is provided. *
8 *************************************************************************/
9
10#include "jove.h"
11
12struct macro *macros = 0; /* Macros */
13data_obj *LastCmd;
14
15static
16add_mac(new)
17struct macro *new;
18{
19 register struct macro *mp,
20 *prev = 0;
21
22 for (mp = macros; mp != 0; prev = mp, mp = mp->m_nextm)
23 if (mp == new)
24 return;
25
26 if (prev)
27 prev->m_nextm = new;
28 else
29 macros = new;
30 new->m_nextm = 0;
31 new->Type = MACRO;
32}
33
34static
35del_mac(mac)
36struct macro *mac;
37{
38 register struct macro *m;
39
40 for (m = macros; m != 0; m = m->m_nextm)
41 if (m->m_nextm == mac) {
42 m->m_nextm = mac->m_nextm;
43 break;
44 }
45 free(mac->Name);
46 free(mac->m_body);
47 free((char *) mac);
48}
49
50struct macro KeyMacro; /* Macro used for defining */
51
52#define NMACROS 40 /* This is bad, bad, BAD! */
53
54struct macro *macstack[NMACROS];
55static int stackp = 0;
56
57fix_macros()
58{
59 register int i;
60 register struct macro *mp;
61
62 for (i = 0; macstack[i]; i++) {
63 mp = macstack[i];
64 macstack[i] = 0;
65 mp->m_flags = mp->m_offset = 0;
66 }
67 stackp = -1;
68 KeyMacro.m_flags = KeyMacro.m_offset = 0;
69}
70
71static
72mac_err(err)
73char *err;
74{
75 KeyMacro.m_flags = 0;
76 MacNolen(&KeyMacro);
77 complain(err);
78}
79
80do_macro(mac)
81struct macro *mac;
82{
83 if (mac->m_flags & EXECUTE)
84 mac_err("[Attempt to execute macro recursively!]");
85 if (++stackp >= NMACROS)
86 complain("[Too many macros at once!]");
87 macstack[stackp] = mac;
88 mac->m_offset = 0;
89 mac->m_ntimes = exp;
90 mac->m_flags |= EXECUTE;
91}
92
93static
94MacNolen(m)
95struct macro *m;
96{
97 m->m_len = m->m_offset = 0;
98}
99
100static struct macro *
101mac_exists(name)
102char *name;
103{
104 register struct macro *mp;
105
106 for (mp = macros; mp; mp = mp->m_nextm)
107 if (strcmp(mp->Name, name) == 0)
108 return mp;
109 return 0;
110}
111
112mac_init()
113{
114 add_mac(&KeyMacro);
115 MacNolen(&KeyMacro);
116 KeyMacro.Name = "keyboard-macro";
117 KeyMacro.m_buflen = 16;
118 KeyMacro.m_body = emalloc(KeyMacro.m_buflen);
119 KeyMacro.m_ntimes = KeyMacro.m_flags = 0;
120 fix_macros();
121}
122
123mac_putc(c)
124int c;
125{
126 if (KeyMacro.m_len >= KeyMacro.m_buflen) {
127 KeyMacro.m_buflen += 16;
128 KeyMacro.m_body = realloc(KeyMacro.m_body, (unsigned) KeyMacro.m_buflen);
129 if (KeyMacro.m_body == 0)
130 mac_err("[Can't allocate storage for keyboard macro]");
131 }
132 KeyMacro.m_body[KeyMacro.m_offset++] = c;
133 KeyMacro.m_len++;
134}
135
136in_macro()
137{
138 return ((stackp >= 0) && ((macstack[stackp])->m_flags & EXECUTE));
139}
140
141mac_getc()
142{
143 struct macro *m;
144
145 if (stackp < 0 || ((m = macstack[stackp])->m_flags & EXECUTE) == 0)
146 return -1;
147 if (m->m_offset == m->m_len) {
148 m->m_offset = 0;
149 if (--m->m_ntimes == 0) {
150 m->m_flags &= ~EXECUTE;
151 stackp--;
152 }
153 return mac_getc();
154 }
155 return m->m_body[m->m_offset++];
156}
157
158NameMac()
159{
160 char *name;
161 struct macro *m;
162
163 if (KeyMacro.m_len == 0)
164 complain("[No keyboard macro to name!]");
165 if (KeyMacro.m_flags & (DEFINE | EXECUTE))
166 complain("[Can't name while defining/executing]");
167 if ((m = mac_exists(name = ask((char *) 0, ProcFmt))) == 0)
168 m = (struct macro *) emalloc(sizeof *m);
169 else {
170 if (strcmp(name, KeyMacro.Name) == 0)
171 complain("[Can't name it that!]");
172 free(m->Name);
173 free(m->m_body);
174 }
175 name = copystr(name);
176 m->Type = KeyMacro.Type;
177 m->m_len = KeyMacro.m_len;
178 m->m_buflen = KeyMacro.m_buflen;
179 m->m_body = emalloc(m->m_buflen);
180 byte_copy(KeyMacro.m_body, m->m_body, m->m_len);
181 m->m_ntimes = m->m_offset = 0; /* At the beginning */
182 m->m_flags = SAVE;
183 m->Name = name;
184 add_mac(m);
185}
186
187RunMacro()
188{
189 struct macro *m;
190
191 if (m = (struct macro *) findmac(ProcFmt))
192 do_macro(m);
193}
194
195static int mac_fd;
196
197static
198mac_io(fcn, ptr, nbytes)
199int (*fcn)();
200char *ptr;
201{
202 int nio;
203
204 if ((nio = (*fcn)(mac_fd, ptr, nbytes)) != nbytes)
205 complain("[Macro %s error: %d got %d]",
206 (fcn == read) ? "read" : "write",
207 nbytes,
208 nio);
209}
210
211WriteMacs()
212{
213 struct macro *m;
214 int namelen,
215 netl,
216 nmacs = 0;
217 char *file,
218 filebuf[FILESIZE];
219
220 file = ask_file((char *) 0, filebuf);
221 if ((mac_fd = creat(file, 0666)) == -1)
222 complain(IOerr("create", file));
223 f_mess("\"%s\"", file);
224
225 /* Don't write the keyboard macro which is always the first */
226 for (m = macros->m_nextm; m != 0; m = m->m_nextm) {
227 if (m->m_len == 0)
228 continue;
229 nmacs++;
230 netl = htonl(m->m_len);
231 mac_io(write, (char *) &netl, sizeof m->m_len);
232 namelen = strlen(m->Name) + 1; /* Including the null */
233 netl = htonl(namelen);
234 mac_io(write, (char *) &netl, sizeof namelen);
235 mac_io(write, m->Name, namelen);
236 mac_io(write, m->m_body, m->m_len);
237 m->m_flags &= ~SAVE;
238 }
239 (void) close(mac_fd);
240 add_mess(" %d macro%n saved.", nmacs, nmacs);
241}
242
243#define NEWWAY 1
244#define OLDWAY 0
245
246static int int_how = NEWWAY;
247
248/* Formatting int's the old way or the new "improved" way? */
249
250#ifndef BSD4_2
251
252/* 4.2 (at least) has these functions defined. */
253
254#if vax || pdp11
255long htonl(x)
256register long x;
257{
258 return( (((x >> 0) & 0377) << 24) |
259 (((x >> 8) & 0377) << 16) |
260 (((x >> 16) & 0377) << 8) |
261 (((x >> 24) & 0377) << 0) );
262}
263
264short htons(x)
265register short x;
266{
267 return( (((x >> 0) & 0377) << 8) |
268 (((x >> 8) & 0377) << 0) );
269}
270
271long ntohl(x)
272register long x;
273{
274 return( (((x >> 0) & 0377) << 24) |
275 (((x >> 8) & 0377) << 16) |
276 (((x >> 16) & 0377) << 8) |
277 (((x >> 24) & 0377) << 0) );
278}
279
280short ntohs(x)
281register short x;
282{
283 return( (((x >> 0) & 0377) << 8) |
284 (((x >> 8) & 0377) << 0) );
285}
286#else
287long htonl(x)
288register long x;
289{
290 return(x);
291}
292
293short htons(x)
294register short x;
295{
296 return(x);
297}
298
299long ntohl(x)
300register long x;
301{
302 return(x);
303}
304
305short ntohs(x)
306register short x;
307{
308 return(x);
309}
310#endif
311#endif BSD4_2
312
313int_fmt(i)
314{
315 if (int_how == NEWWAY)
316 return ntohl(i);
317 return i;
318}
319
320ReadMacs()
321{
322 char *file,
323 filebuf[FILESIZE];
324 struct macro *m;
325 int nmacs = 0,
326 namelen,
327 bodylen,
328 tmp,
329 he_is_sure = 0,
330 save_em = FALSE;
331
332 file = ask_file((char *) 0, filebuf);
333 if ((mac_fd = open(file, 0)) == -1)
334 complain(IOerr("open", file));
335
336 f_mess("\"%s\"", file);
337 while (read(mac_fd, (char *) &tmp, sizeof tmp) == (sizeof tmp)) {
338retry: bodylen = int_fmt(tmp);
339 if (!he_is_sure && (bodylen <= 0 || bodylen > 10000)) {
340 if (int_how == NEWWAY) {
341 int_how = OLDWAY;
342 save_em = TRUE;
343 goto retry;
344 } else {
345 confirm("Are you sure \"%s\" is a JOVE macro file? ", filebuf);
346 he_is_sure = 1;
347 }
348 }
349 nmacs++;
350 m = (struct macro *) emalloc (sizeof *m);
351 m->m_flags = 0;
352 m->m_len = bodylen;
353 m->m_buflen = m->m_len;
354 mac_io(read, (char *) &namelen, sizeof namelen);
355 namelen = int_fmt(namelen);
356 m->Name = emalloc(namelen);
357 mac_io(read, m->Name, namelen);
358 m->m_body = emalloc(m->m_buflen);
359 mac_io(read, m->m_body, m->m_len);
360 add_mac(m);
361 }
362 (void) close(mac_fd);
363 add_mess(" %d macro%n defined.", nmacs, nmacs);
364 if (save_em) {
365 char *msg = "OK to convert to the new format? ",
366 ibuf[FILESIZE + 1];
367
368 if (!InJoverc) {
369 TOstart("Warning", TRUE);
370 Typeout("Warning: your macros file is in the old format.");
371 Typeout("Do you want me to convert \"%s\" to the new", pr_name(file));
372 Typeout("format?");
373 f_mess(msg);
374 TOstop();
375 confirm(msg);
376 }
377 /* WriteMacs requests a file name. This is what it'll get. */
378 sprintf(ibuf, "%s\n", file);
379 Inputp = ibuf;
380 WriteMacs();
381 }
382}
383
384Remember()
385{
386 if (KeyMacro.m_flags & EXECUTE)
387 /* We're already executing the macro; ignore any attempts
388 to define the keyboard macro while we are executing. */
389 return;
390 if (KeyMacro.m_flags & DEFINE)
391 message("[Already remembering ... continue with definition]");
392 else {
393 UpdModLine++;
394 KeyMacro.m_flags |= DEFINE;
395 MacNolen(&KeyMacro);
396 message("Remembering...");
397 }
398}
399
400/* Is `c' a prefix character */
401
402static
403PrefChar(c)
404{
405 return (int) IsPrefix(mainmap[c]);
406}
407
408Forget()
409{
410 char *cp;
411 struct macro *m = &KeyMacro;
412
413 UpdModLine++;
414 if (m->m_flags & DEFINE) {
415 message("Keyboard macro defined.");
416 m->m_flags &= ~DEFINE;
417 cp = &m->m_body[m->m_len - 2];
418 if (PrefChar(*cp))
419 m->m_len -= 2;
420 else if (commands[*++cp].c_proc == Forget)
421 m->m_len--;
422 }
423}
424
425ExecMacro()
426{
427 do_macro(&KeyMacro);
428}
429
430MacInter()
431{
432 extern int Interactive;
433
434 if (!Asking)
435 return;
436 Interactive = 1;
437}
438
439ModMacs()
440{
441 register struct macro *m;
442
443 for (m = macros->m_nextm; m != 0; m = m->m_nextm)
444 if (m->m_flags & SAVE)
445 return 1;
446 return 0;
447}
448
449data_obj *
450findmac(prompt)
451char *prompt;
452{
453 char *strings[100];
454 register char **strs = strings;
455 register int com;
456 register struct macro *m = macros;
457
458 for (; m != 0; m = m->m_nextm)
459 *strs++ = m->Name;
460 *strs = 0;
461
462 if ((com = complete(strings, prompt, NOTHING)) < 0)
463 return 0;
464 m = macros;
465 while (--com >= 0)
466 m = m->m_nextm;
467 return (data_obj *) m;
468}
469
470DelMacro()
471{
472 struct macro *m;
473
474 if ((m = (struct macro *) findmac(ProcFmt)) == 0)
475 return;
476 if (m == &KeyMacro)
477 complain("[It's illegal to delete the keyboard-macro!]");
478 del_mac(m);
479}