Annotation of 43BSDReno/contrib/jove/macros.c, revision 1.1.1.1

1.1       root        1: /***************************************************************************
                      2:  * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
                      3:  * is provided to you without charge, and with no warranty.  You may give  *
                      4:  * away copies of JOVE, including sources, provided that this notice is    *
                      5:  * included in all the files.                                              *
                      6:  ***************************************************************************/
                      7: 
                      8: #include "jove.h"
                      9: #include "ctype.h"
                     10: #include "fp.h"
                     11: #include "chars.h"
                     12: #include "disp.h"
                     13: 
                     14: private void
                     15:        add_mac proto((struct macro *)),
                     16:        del_mac proto((struct macro *)),
                     17:        pop_macro_stack proto((void)),
                     18:        push_macro_stack proto((struct macro *, int));
                     19: 
                     20: private struct macro *mac_exists proto((char *));
                     21: 
                     22: #define SAVE           01      /* this macro needs saving to a file */
                     23: 
                     24: struct macro   *macros = 0;            /* macros */
                     25: int    InMacDefine = NO;
                     26: 
                     27: private void
                     28: add_mac(new)
                     29: struct macro   *new;
                     30: {
                     31:        register struct macro   *mp,
                     32:                                *prev = 0;
                     33: 
                     34:        for (mp = macros; mp != 0; prev = mp, mp = mp->m_nextm)
                     35:                if (mp == new)
                     36:                        return;
                     37: 
                     38:        if (prev)
                     39:                prev->m_nextm = new;
                     40:        else
                     41:                macros = new;
                     42:        new->m_nextm = 0;
                     43:        new->Type = MACRO;
                     44: }
                     45: 
                     46: private void
                     47: del_mac(mac)
                     48: struct macro   *mac;
                     49: {
                     50:        register struct macro   *m;
                     51: 
                     52:        for (m = macros; m != 0; m = m->m_nextm)
                     53:                if (m->m_nextm == mac) {
                     54:                        m->m_nextm = mac->m_nextm;
                     55:                        break;
                     56:                }
                     57:        free(mac->Name);
                     58:        free(mac->m_body);
                     59:        free((char *) mac);
                     60: }
                     61: 
                     62: struct macro   KeyMacro;       /* Macro used for defining */
                     63: 
                     64: /* To execute a macro, we have a "stack" of running macros.  Whenever
                     65:    we execute a macro, we push it on the stack, run it, then pop it
                     66:    from the stack.  */
                     67: struct m_thread {
                     68:        struct m_thread *mt_prev;
                     69:        struct macro    *mt_mp;
                     70:        int     mt_offset,
                     71:                mt_count;
                     72: };
                     73: 
                     74: private struct m_thread        *mac_stack = 0;
                     75: 
                     76: private struct m_thread *
                     77: alloc_mthread()
                     78: {
                     79:        return (struct m_thread *) emalloc(sizeof (struct m_thread));
                     80: }
                     81: 
                     82: private void
                     83: free_mthread(t)
                     84: struct m_thread        *t;
                     85: {
                     86:        free((char *) t);
                     87: }
                     88: 
                     89: void
                     90: unwind_macro_stack()
                     91: {
                     92:        while (mac_stack != 0)
                     93:                pop_macro_stack();
                     94: }
                     95: 
                     96: private void
                     97: pop_macro_stack()
                     98: {
                     99:        register struct m_thread        *m;
                    100: 
                    101:        if ((m = mac_stack) == 0)
                    102:                return;
                    103:        mac_stack = m->mt_prev;
                    104:        free_mthread(m);
                    105: }
                    106: 
                    107: private void
                    108: push_macro_stack(m, count)
                    109: register struct macro  *m;
                    110: int    count;
                    111: {
                    112:        register struct m_thread        *t;
                    113: 
                    114:        for (t = mac_stack; t != 0; t = t->mt_prev)
                    115:                if (t->mt_mp == m)
                    116:                        complain("[Cannot execute macro recusively]");
                    117:        if (count <= 0)
                    118:                complain("[Cannot execute macro a negative number of times]");
                    119:        t = alloc_mthread();
                    120:        t->mt_prev = mac_stack;
                    121:        mac_stack = t;
                    122:        t->mt_offset = 0;
                    123:        t->mt_mp = m;
                    124:        t->mt_count = count;
                    125: }
                    126: 
                    127: void
                    128: do_macro(mac)
                    129: struct macro   *mac;
                    130: {
                    131:        push_macro_stack(mac, arg_value());
                    132: }
                    133: 
                    134: private struct macro *
                    135: mac_exists(name)
                    136: char   *name;
                    137: {
                    138:        register struct macro   *mp;
                    139: 
                    140:        for (mp = macros; mp; mp = mp->m_nextm)
                    141:                if (strcmp(mp->Name, name) == 0)
                    142:                        return mp;
                    143:        return 0;
                    144: }
                    145: 
                    146: void
                    147: mac_init()
                    148: {
                    149:        add_mac(&KeyMacro);
                    150:        KeyMacro.Name = "keyboard-macro";
                    151:        KeyMacro.m_len = 0;
                    152:        KeyMacro.m_buflen = 16;
                    153:        KeyMacro.m_body = emalloc((size_t) KeyMacro.m_buflen);
                    154: }
                    155: 
                    156: void
                    157: mac_putc(c)
                    158: int    c;
                    159: {
                    160:        if (KeyMacro.m_len >= KeyMacro.m_buflen) {
                    161:                KeyMacro.m_buflen += 16;
                    162:                KeyMacro.m_body = realloc(KeyMacro.m_body, (size_t) KeyMacro.m_buflen);
                    163:                if (KeyMacro.m_body == 0) {
                    164:                        KeyMacro.m_buflen = KeyMacro.m_len = 0;
                    165:                        complain("[Can't allocate storage for keyboard macro]");
                    166:                }
                    167:        }
                    168:        KeyMacro.m_body[KeyMacro.m_len++] = c;
                    169: }
                    170: 
                    171: int
                    172: in_macro()
                    173: {
                    174:        return (mac_stack != NULL);
                    175: }
                    176: 
                    177: int
                    178: mac_getc()
                    179: {
                    180:        struct m_thread *mthread;
                    181:        struct macro    *m;
                    182: 
                    183:        if ((mthread = mac_stack) == NULL)
                    184:                return EOF;
                    185:        m = mthread->mt_mp;
                    186:        if (mthread->mt_offset == m->m_len) {
                    187:                mthread->mt_offset = 0;
                    188:                if (--mthread->mt_count == 0)
                    189:                        pop_macro_stack();
                    190:                return mac_getc();
                    191:        }
                    192:        return m->m_body[mthread->mt_offset++];
                    193: }
                    194: 
                    195: void
                    196: NameMac()
                    197: {
                    198:        char    *name;
                    199:        struct macro    *m;
                    200: 
                    201:        if (KeyMacro.m_len == 0)
                    202:                complain("[No keyboard macro to name!]");
                    203:        if (in_macro() || InMacDefine)
                    204:                complain("[Can't name while defining/executing]");
                    205:        if ((m = mac_exists(name = ask((char *) 0, ProcFmt))) == 0)
                    206:                m = (struct macro *) emalloc(sizeof *m);
                    207:        else {
                    208:                if (strcmp(name, KeyMacro.Name) == 0)
                    209:                        complain("[Can't name it that!]");
                    210:                free(m->Name);
                    211:                free(m->m_body);
                    212:        }
                    213:        name = copystr(name);
                    214:        m->Type = KeyMacro.Type;
                    215:        m->m_len = KeyMacro.m_len;
                    216:        m->m_buflen = KeyMacro.m_buflen;
                    217:        m->m_body = emalloc((size_t) m->m_buflen);
                    218:        byte_copy(KeyMacro.m_body, m->m_body, (size_t) m->m_len);
                    219:        m->m_flags = SAVE;
                    220:        m->Name = name;
                    221:        add_mac(m);
                    222: }
                    223: 
                    224: void
                    225: RunMacro()
                    226: {
                    227:        struct macro    *m;
                    228: 
                    229:        if ((m = (struct macro *) findmac(ProcFmt)) != NULL)
                    230:                do_macro(m);
                    231: }
                    232: 
                    233: private void
                    234: pr_putc(c, fp)
                    235: int    c;
                    236: File   *fp;
                    237: {
                    238:        if (c == '\\' || c == '^')
                    239:                jputc('\\', fp);
                    240:         else if (isctrl(c)) {
                    241:                jputc('^', fp);
                    242:                c = (c == RUBOUT) ? '?' : (c + '@');
                    243:        }
                    244:        jputc(c, fp);
                    245: }
                    246: 
                    247: void
                    248: WriteMacs()
                    249: {
                    250:        struct macro    *m;
                    251:        char    *file,
                    252:                filebuf[FILESIZE];
                    253:        File    *fp;
                    254:        int     i;
                    255: 
                    256:        file = ask_file((char *) 0, (char *) 0, filebuf);
                    257:        fp = open_file(file, iobuff, F_WRITE, YES, YES);
                    258: 
                    259:        /* Don't write the keyboard macro which is always the first */
                    260:        for (m = macros->m_nextm; m != 0; m = m->m_nextm) {
                    261:                fwritef(fp, "define-macro %s ", m->Name);
                    262:                for (i = 0; i < m->m_len; i++)
                    263:                        pr_putc(m->m_body[i], fp);
                    264:                jputc('\n', fp);
                    265:                m->m_flags &= ~SAVE;
                    266:        }
                    267:        close_file(fp);
                    268: }
                    269: 
                    270: void
                    271: DefKBDMac()
                    272: {
                    273:        char    *macro_name,
                    274:                *macro_body,
                    275:                nextc,
                    276:                c,
                    277:                macro_buffer[LBSIZE];
                    278:        int     i;
                    279:        struct macro    *m;
                    280: 
                    281:        macro_name = do_ask(" \r\n", (int (*) proto((int))) 0, (char *) 0,
                    282:                ProcFmt);
                    283:        if (macro_name == 0)
                    284:                complain("[No default]");
                    285:        macro_name = copystr(macro_name);
                    286:        if ((m = mac_exists(macro_name)) != NULL)
                    287:                del_mac(m);
                    288:        macro_body = ask((char *) 0, ": %f %s enter body: ", macro_name);
                    289:        i = 0;
                    290:        while ((c = *macro_body++) != '\0') {
                    291:                if (c == '\\') {
                    292:                        if ((nextc = *macro_body++) == LF)
                    293:                                complain("[Premature end of line]");
                    294:                        c = nextc;
                    295:                } else if (c == '^') {
                    296:                        if ((nextc = *macro_body++) == '?')
                    297:                                c = RUBOUT;
                    298:                        else if (isalpha(nextc) || strchr("@[\\]^_", nextc))
                    299:                                c = CTL(nextc);
                    300:                        else
                    301:                                complain("Bad control-character: '%c'", nextc);
                    302:                }
                    303:                macro_buffer[i++] = c;
                    304:        }
                    305:        m = (struct macro *) emalloc(sizeof (*m));
                    306:        m->Name = macro_name;
                    307:        m->m_len = m->m_buflen = i;
                    308:        m->m_body = emalloc((size_t) i);
                    309:        m->m_flags = InJoverc ? 0 : SAVE;
                    310:        byte_copy(macro_buffer, m->m_body, (size_t) i);
                    311:        add_mac(m);
                    312: }
                    313: 
                    314: void
                    315: Remember()
                    316: {
                    317:        /* We're already executing the macro; ignore any attempts
                    318:           to define the keyboard macro while we are executing. */
                    319:        if (in_macro())
                    320:                return;
                    321:        if (InMacDefine)
                    322:                message("[Already defining ... continue with definition]");
                    323:        else {
                    324:                UpdModLine = YES;
                    325:                InMacDefine = YES;
                    326:                KeyMacro.m_len = 0;
                    327:                message("Defining...");
                    328:        }
                    329: }
                    330: 
                    331: void
                    332: Forget()
                    333: {
                    334:        char    *cp;
                    335:        struct macro    *m = &KeyMacro;
                    336: 
                    337:        UpdModLine = YES;
                    338:        if (InMacDefine) {
                    339:                message("Keyboard macro defined.");
                    340:                InMacDefine = NO;
                    341: 
                    342:                /* try and strip off the key sequence that invoked us */
                    343:                cp = &m->m_body[m->m_len - 2];
                    344:                if (PrefChar(*cp))
                    345:                        m->m_len -= 2;
                    346:                else if (commands[cp[1]].c_proc == Forget)
                    347:                        m->m_len -= 1;
                    348:        } else
                    349:                complain("[end-kbd-macro: not currently defining macro!]");
                    350: }
                    351: 
                    352: void
                    353: ExecMacro()
                    354: {
                    355:        do_macro(&KeyMacro);
                    356: }
                    357: 
                    358: void
                    359: MacInter()
                    360: {
                    361:        if (!Asking)
                    362:                return;
                    363:        Interactive = 1;
                    364: }
                    365: 
                    366: int
                    367: ModMacs()
                    368: {
                    369:        register struct macro   *m;
                    370: 
                    371:        for (m = macros->m_nextm; m != 0; m = m->m_nextm)
                    372:                if (m->m_flags & SAVE)
                    373:                        return YES;
                    374:        return NO;
                    375: }
                    376: 
                    377: data_obj *
                    378: findmac(prompt)
                    379: char   *prompt;
                    380: {
                    381:        char    *strings[100];
                    382:        register char   **strs = strings;
                    383:        register int    com;
                    384:        register struct macro   *m = macros;
                    385: 
                    386:        for (; m != 0; m = m->m_nextm)
                    387:                *strs++ = m->Name;
                    388:        *strs = 0;
                    389: 
                    390:        if ((com = complete(strings, prompt, NOTHING)) < 0)
                    391:                return 0;
                    392:        m = macros;
                    393:        while (--com >= 0)
                    394:                m = m->m_nextm;
                    395:        return (data_obj *) m;
                    396: }
                    397: 
                    398: void
                    399: DelMacro()
                    400: {
                    401:        struct macro    *m;
                    402: 
                    403:        if ((m = (struct macro *) findmac(ProcFmt)) == 0)
                    404:                return;
                    405:        if (m == &KeyMacro)
                    406:                complain("[It's illegal to delete the keyboard-macro!]");
                    407:        del_mac(m);
                    408: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.