|
|
1.1 ! root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.