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: 12: struct macro *macros = 0; /* Macros */ 13: data_obj *LastCmd; 14: 15: static 16: add_mac(new) 17: struct 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: 34: static 35: del_mac(mac) 36: struct 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: 50: struct macro KeyMacro; /* Macro used for defining */ 51: 52: #define NMACROS 40 /* This is bad, bad, BAD! */ 53: 54: struct macro *macstack[NMACROS]; 55: static int stackp = 0; 56: 57: fix_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: 71: static 72: mac_err(err) 73: char *err; 74: { 75: KeyMacro.m_flags = 0; 76: MacNolen(&KeyMacro); 77: complain(err); 78: } 79: 80: do_macro(mac) 81: struct 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: 93: static 94: MacNolen(m) 95: struct macro *m; 96: { 97: m->m_len = m->m_offset = 0; 98: } 99: 100: static struct macro * 101: mac_exists(name) 102: char *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: 112: mac_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: 123: mac_putc(c) 124: int 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: 136: in_macro() 137: { 138: return ((stackp >= 0) && ((macstack[stackp])->m_flags & EXECUTE)); 139: } 140: 141: mac_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: 158: NameMac() 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: 187: RunMacro() 188: { 189: struct macro *m; 190: 191: if (m = (struct macro *) findmac(ProcFmt)) 192: do_macro(m); 193: } 194: 195: static int mac_fd; 196: 197: static 198: mac_io(fcn, ptr, nbytes) 199: int (*fcn)(); 200: char *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: 211: WriteMacs() 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: 246: static 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 255: long htonl(x) 256: register 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: 264: short htons(x) 265: register short x; 266: { 267: return( (((x >> 0) & 0377) << 8) | 268: (((x >> 8) & 0377) << 0) ); 269: } 270: 271: long ntohl(x) 272: register 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: 280: short ntohs(x) 281: register short x; 282: { 283: return( (((x >> 0) & 0377) << 8) | 284: (((x >> 8) & 0377) << 0) ); 285: } 286: #else 287: long htonl(x) 288: register long x; 289: { 290: return(x); 291: } 292: 293: short htons(x) 294: register short x; 295: { 296: return(x); 297: } 298: 299: long ntohl(x) 300: register long x; 301: { 302: return(x); 303: } 304: 305: short ntohs(x) 306: register short x; 307: { 308: return(x); 309: } 310: #endif 311: #endif BSD4_2 312: 313: int_fmt(i) 314: { 315: if (int_how == NEWWAY) 316: return ntohl(i); 317: return i; 318: } 319: 320: ReadMacs() 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)) { 338: retry: 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: 384: Remember() 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: 402: static 403: PrefChar(c) 404: { 405: return (int) IsPrefix(mainmap[c]); 406: } 407: 408: Forget() 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: 425: ExecMacro() 426: { 427: do_macro(&KeyMacro); 428: } 429: 430: MacInter() 431: { 432: extern int Interactive; 433: 434: if (!Asking) 435: return; 436: Interactive = 1; 437: } 438: 439: ModMacs() 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: 449: data_obj * 450: findmac(prompt) 451: char *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: 470: DelMacro() 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: }