home *** CD-ROM | disk | FTP | other *** search
- /* (@)# macros.c (c) copyright 9/19/88 (Bart Schaefer, Dan Heller) */
-
- #include "bindings.h"
- #include "mush.h"
-
- extern struct cmd_map map_func_names[];
-
- struct cmd_map *mac_stack, *mac_hide;
-
- /*
- * print current binding to macro mappings if "str" is NULL.
- * else return the string "x_str" which the str is bound to.
- */
- char *
- c_macro(name, str, opts)
- char *name;
- register char *str;
- register struct cmd_map *opts;
- {
- register int incurses = iscurses;
- char buf[MAX_MACRO_LEN], buf2[sizeof buf * 3];
-
- if (!str) {
- for (; opts; opts = opts->m_next)
- if (opts->m_cmd == C_MACRO)
- break;
- if (!opts) {
- print("No %s settings.\n", name);
- return (char *)(-1);
- }
- if (incurses)
- clr_bot_line(), iscurses = FALSE;
- (void) do_pager(NULL, TRUE);
- (void) do_pager(sprintf(buf, "\nCurrent %s settings:\n\n",name), FALSE);
- }
-
- if (!opts)
- return NULL;
-
- for (; opts; opts = opts->m_next) {
- if (opts->m_cmd != C_MACRO)
- continue;
- if (!str) {
- (void) do_pager(sprintf(buf, "%-20.20s ",
- ctrl_strcpy(buf2, opts->m_str, FALSE)), FALSE);
- if (do_pager(sprintf(buf, "%s\n",
- ctrl_strcpy(buf2, opts->x_str, TRUE)), FALSE) == EOF)
- break;
- } else {
- if (strcmp(str, opts->m_str))
- continue;
- else
- return opts->x_str;
- }
- }
- iscurses = incurses;
- if (str)
- (void) do_pager(NULL, FALSE);
- return NULL;
- }
-
- mac_push(str)
- register char *str;
- {
- register struct cmd_map *tmp;
-
- /* now make a new macro struct and set fields */
- if (!(tmp = (struct cmd_map *)calloc((unsigned)1,sizeof(struct cmd_map)))) {
- error("calloc");
- return -1;
- }
- tmp->m_next = mac_stack;
- mac_stack = tmp;
- tmp->x_str = savestr(str); /* x_str is the text of the expansion */
- tmp->m_str = tmp->x_str; /* m_str is the current read position */
-
- /*
- * Save the current state of the glob_flags so
- * mac_push() can also serve as unget of stdin
- */
- tmp->m_cmd = glob_flags;
- return 0;
- }
-
- mac_queue(str)
- register char *str;
- {
- register struct cmd_map **tmp; /* NOTE pointer to pointer! */
-
- /* Find the bottom of the macro stack */
- for (tmp = &mac_stack; *tmp; tmp = &((*tmp)->m_next))
- ;
- /* now make a new macro struct and set fields */
- if (!(*tmp =
- (struct cmd_map *)calloc((unsigned)1,sizeof(struct cmd_map)))) {
- error("calloc");
- return -1;
- }
- (*tmp)->m_next = (struct cmd_map *)0; /* calloc should do this .... */
- (*tmp)->x_str = savestr(str); /* x_str is the text of the expansion */
- (*tmp)->m_str = (*tmp)->x_str; /* m_str is the current read position */
-
- /*
- * Save the current state of the glob_flags
- */
- (*tmp)->m_cmd = glob_flags;
- return 0;
- }
-
- void
- mac_pop()
- {
- register struct cmd_map *tmp;
-
- if (mac_stack) {
- tmp = mac_stack;
- mac_stack = tmp->m_next;
- xfree(tmp->x_str);
- xfree((char *) tmp);
- }
- /*
- * Restore saved MACRO glob_flags only (see mac_push())
- */
- if (mac_stack) {
- if (ison(mac_stack->m_cmd, IN_MACRO))
- turnon(glob_flags, IN_MACRO);
- else
- turnoff(glob_flags, IN_MACRO);
- if (ison(mac_stack->m_cmd, LINE_MACRO))
- turnon(glob_flags, LINE_MACRO);
- else
- turnoff(glob_flags, LINE_MACRO);
- if (ison(mac_stack->m_cmd, QUOTE_MACRO))
- turnon(glob_flags, QUOTE_MACRO);
- else
- turnoff(glob_flags, QUOTE_MACRO);
- }
- }
-
- /* Abandon macro processing */
- void
- mac_flush()
- {
- while (mac_stack)
- mac_pop();
- if (mac_hide) {
- mac_stack = mac_hide;
- mac_hide = NULL_MAP;
- while (mac_stack)
- mac_pop();
- }
- turnoff(glob_flags, IN_MACRO);
- turnoff(glob_flags, LINE_MACRO);
- turnoff(glob_flags, QUOTE_MACRO);
- }
-
- /* Check for pending input from a macro. */
- mac_pending()
- {
- register struct cmd_map *msp;
-
- for (msp = mac_stack; msp && !*(msp->m_str); msp = msp->m_next)
- ;
-
- return !!msp;
- }
-
- /* Get input and treat it as a macro. */
- get_mac_input(newline)
- int newline; /* 1 if newline to be appended, 0 otherwise */
- {
- register int len;
- char buf[MAX_MACRO_LEN];
-
- /* This call cannot be nested */
- if (mac_hide)
- return -1;
-
- /* Hide the mac_stack so input comes from stdin */
- mac_hide = mac_stack; mac_stack = NULL_MAP;
-
- if ((len = Getstr(buf, MAX_MACRO_LEN - 1, 0)) < 0)
- return len;
- if (newline) {
- buf[len++] = '\n';
- buf[len] = 0;
- }
-
- /* Restore the mac_stack */
- if (mac_stack) {
- /*
- * Somehow, a push happened even though mac_hide was
- * nonzero -- maybe by line wrap? Fix it as best we can.
- */
- struct cmd_map *msp;
- for (msp = mac_stack; msp->m_next; msp = msp->m_next)
- ;
- msp->m_next = mac_hide;
- } else
- mac_stack = mac_hide;
- mac_hide = NULL_MAP;
-
- /* Restore saved flags */
- if (mac_stack) {
- if (ison(mac_stack->m_cmd, IN_MACRO))
- turnon(glob_flags, IN_MACRO);
- else
- turnoff(glob_flags, IN_MACRO);
- if (ison(mac_stack->m_cmd, LINE_MACRO))
- turnon(glob_flags, LINE_MACRO);
- else
- turnoff(glob_flags, LINE_MACRO);
- }
- if (len > 0)
- Ungetstr(buf);
-
- return 1;
- }
-
- /* getchar() substitute -- reads from the current macro if one is active,
- * otherwise does a getchar().
- *
- * NOTE: In the mac_stack, x_str is the saved text of the current macro,
- * and m_str is the current read position within the macro.
- */
- m_getchar()
- {
- int c;
-
- while (mac_stack && (! *(mac_stack->m_str)))
- mac_pop();
- if (mac_stack) {
- c = *((mac_stack->m_str)++);
- return c;
- } else {
- turnoff(glob_flags, IN_MACRO);
- turnoff(glob_flags, LINE_MACRO);
- turnoff(glob_flags, QUOTE_MACRO);
- while ((c = getchar()) == 0) /* Ignore NUL chars from stdin */
- ; /* until better solution found */
- return c;
- }
- }
-
- m_ungetc(c)
- char c;
- {
- if (mac_stack && (mac_stack->m_str > mac_stack->x_str))
- *(--(mac_stack->m_str)) = c;
- else
- (void) ungetc(c, stdin);
- }
-
- /*
- * Try to read a long command; assumes MAC_LONG_CMD already seen.
- * On immediate failure, return 0.
- * On failure after reading some input, return less than zero.
- * On success, return greater than 0.
- * The absolute value of the return is the number of chars placed in buf.
- */
- read_long_cmd (buf)
- char *buf;
- {
- register char c, *p = buf;
- register int count = 0;
-
- /*
- * Test in_macro() in this loop because the _entire_
- * long command _must_ be in the macro -- if we run
- * out of macro in mid-long-command, it is an error.
- */
- while (in_macro() && (count < MAX_LONG_CMD - 1)
- && ((c = m_getchar()) != MAC_LONG_END)) {
- *p++ = c; ++count;
- }
- *p = '\0';
- if (c != MAC_LONG_END)
- return (-count);
- return count;
- }
-
- /*
- * Identify and possibly execute a reserved long macro command
- * Executes if do_exec is true. Otherwise, just parse.
- */
- reserved_cmd (buf, do_exec)
- char *buf;
- {
- int ret = 1;
-
- if (!strcmp(buf, MAC_GET_STR)) {
- if (do_exec)
- ret = get_mac_input(0);
- } else if (!strcmp(buf, MAC_GET_LINE)) {
- if (do_exec)
- ret = get_mac_input(1);
- } else
- ret = 0;
- return ret;
- }
-
- #ifdef CURSES
-
- /*
- * Identify (and possibly execute, if reserved) curses mode commands
- * that appear in macro strings enclosed by MAC_LONG_CMD and
- * MAC_LONG_END. Return the binding of the command.
- */
- long_mac_cmd (c, do_exec)
- int c;
- {
- char buf[MAX_LONG_CMD];
- register int count, binding;
- int y, x;
-
- if (c != MAC_LONG_CMD)
- return C_ERROR;
-
- if ((count = read_long_cmd(buf)) <= 0) {
- print("Invalid long macro command");
- if (ison(glob_flags, CNTD_CMD))
- putchar('\n');
- if (do_exec)
- mac_flush();
- return C_ERROR;
- }
-
- if (do_exec) {
- if (ison(glob_flags, CNTD_CMD))
- clr_bot_line();
- getyx(stdscr, y, x);
- move(LINES - 1, 0);
- }
- if (reserved_cmd(buf, do_exec)) {
- if (do_exec) {
- if (isoff(glob_flags, CNTD_CMD))
- move(y, x);
- return getcmd();
- } else
- return C_NULL;
- } else if (do_exec)
- move(y, x);
-
- /* Can start at C_NULL because of "no-op" command */
- for (count = 0; count <= C_HELP; count++) {
- if (!strcmp(buf, map_func_names[count].m_str)) {
- binding = (int)map_func_names[count].m_cmd;
- break;
- }
- }
- /* Don't allow C_MACRO to be called directly */
- if (count > C_HELP || binding == C_MACRO) {
- print("Invalid long macro command");
- if (ison(glob_flags, CNTD_CMD))
- putchar('\n');
- return C_ERROR;
- } else
- return binding;
- }
-
- #endif /* CURSES */
-
- /*
- * Check the validity of a macro binding as far as possible
- */
- check_mac_bindings(buf)
- char *buf;
- {
- int ok = TRUE;
-
- while (ok && buf && *buf) {
- if (*buf == MAC_LONG_CMD) {
- char *i;
- #ifdef CURSES
- int count;
- #endif /* CURSES */
-
- if (ok)
- ok = ((i = index(++buf, MAC_LONG_END)) != NULL);
- if (i)
- *i = '\0'; /* Don't worry, we'll fix it */
- else
- return ok;
- #ifdef CURSES
- /* OK to start at C_NULL because of "no-op" command */
- for (count = 0; count <= C_HELP; count++)
- if (! strcmp(buf, map_func_names[count].m_str))
- break;
- /* Don't allow C_MACRO to be called directly */
- if (count == C_MACRO)
- ok = FALSE;
- else if (count > C_HELP)
- #endif /* CURSES */
- if (ok && !(ok = reserved_cmd(buf, FALSE)))
- wprint("Warning: unrecognized curses command: \"%s\"\n", buf);
- buf = i;
- *buf++ = MAC_LONG_END;
- } else if (*buf++ == '\\' && *buf)
- ++buf;
- }
- return ok;
- }
-