home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.freefriends.org
/
ftp.freefriends.org.tar
/
ftp.freefriends.org
/
arnold
/
Source
/
mush.rstevens.tar.gz
/
mush.tar
/
macros.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-05-03
|
9KB
|
403 lines
/* (@)# 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;
}