Annotation of 43BSDReno/contrib/jove/macros.c, revision 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.